a0899994fd4ab79cf0b9f994b5cb900911e9de8e
[framework/uifw/libscl-ui.git] / scl / sclcontroller.cpp
1 /*
2  * Copyright (c) 2012 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  *
16  */
17
18 #include <time.h>
19 #include <math.h>
20 #include <assert.h>
21 #include <vector>
22
23 #include "sclcontroller.h"
24 #include "scldebug.h"
25 #include "sclresourcecache.h"
26 #include "sclactionstate.h"
27 #include "scluibuilder.h"
28 #include "sclkeydefines.h"
29 #include "sclfeedback.h"
30 #include "sclerroradjustment.h"
31 #include "sclimageproxy.h"
32 #include "sclres_manager.h"
33 #include "scleventhandler.h"
34 #include "sclanimator.h"
35 #include <dlog.h>
36
37 //#define DIRECTLY_DRAW_ON_EVENTS
38
39 using namespace scl;
40
41 static sclboolean
42 _play_tts_for_input_mode_name(int mode) {
43     SCL_DEBUG();
44
45     CSCLContext *context = CSCLContext::get_instance();
46     if (context->get_tts_enabled() == FALSE) {
47         return FALSE;
48     }
49
50     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
51     const SclInputModeConfigure *pinput_mode_table = sclres_manager->get_input_mode_configure_table();
52     if (NULL == pinput_mode_table) {
53         return FALSE;
54     }
55
56     const char* name = pinput_mode_table[mode].name;
57     if (NULL == name) {
58         return FALSE;
59     }
60
61     CSCLUtils *utils = CSCLUtils::get_instance();
62     utils->play_tts(name);
63     return TRUE;
64 }
65
66 static sclboolean
67 _play_tts_for_layout_autopopup_name() {
68     SCL_DEBUG();
69
70     CSCLContext *context = CSCLContext::get_instance();
71     if (context->get_tts_enabled() == FALSE) {
72         return FALSE;
73     }
74
75     CSCLUtils *utils = CSCLUtils::get_instance();
76     utils->play_tts(SCL_LAYOUT_AUTOPOPUP_NAME);
77     return TRUE;
78 }
79
80 CSCLController::CSCLController()
81 {
82     SCL_DEBUG();
83
84     m_long_key_duration = SCL_LONGKEY_DURATION;
85     m_long_key_cancel_distance = SCL_LONGKEY_CANCEL_DIST;
86     m_repeat_key_duration = SCL_REPEATKEY_DURATION;
87     m_autopopup_key_duration = SCL_AUTOPOPUP_KEY_DURATION;
88
89     m_button_delay_duration = SCL_BUTTON_MIN_DURATION;
90
91     m_key_repeated_num = 0;
92
93     m_debug_mode = DEBUGMODE_DISABLED;
94     m_debug_variable = 0;
95
96     m_input_events_disabled = FALSE;
97 }
98
99 CSCLController::~CSCLController()
100 {
101     SCL_DEBUG();
102 }
103
104 CSCLController*
105 CSCLController::get_instance()
106 {
107     static CSCLController instance;
108     return &instance;
109 }
110
111 void
112 CSCLController::init()
113 {
114     SCL_DEBUG();
115 }
116
117 //#define TEST_NEWBACKEND
118 #ifdef TEST_NEWBACKEND
119 #include <Ecore_Evas.h>
120 #include <Ecore.h>
121 #include <vector>
122 typedef enum {
123     EFLOBJECT_NONE,
124     EFLOBJECT_IMAGE,
125     EFLOBJECT_CLIPOBJECT,
126     EFLOBJECT_TEXTBLOCK,
127 } EFLOBJECT_TYPE;
128
129     typedef struct {
130         EFLOBJECT_TYPE type;
131         SclRectangle position;
132         Evas_Object *object;
133         char *etc_info;
134         sclboolean extracted;
135         void *data;
136     } EFLObject;
137 #include <Ecore_Evas.h>
138 #include <Ecore.h>
139     typedef struct {
140         sclboolean used;
141
142         Evas_Object *image;
143         Evas_Object *clipper;
144
145         sclwindow window;
146         sclchar image_path[_POSIX_PATH_MAX];
147         sclint imgPathHash;
148         sclint dest_x;
149         sclint dest_y;
150         sclint dest_width;
151         sclint dest_height;
152         sclint src_x;
153         sclint src_y;
154         sclint src_width;
155         sclint src_height;
156         sclboolean extrace_image;
157     } ImageCache;
158
159     typedef struct {
160         sclboolean used;
161
162         Evas_Object *text;
163
164         sclwindow window;
165         scl::SclFontInfo font_info;
166         SclColor color;
167         sclchar str[_POSIX_PATH_MAX];;
168         sclint strHash;
169         sclint pos_x;
170         sclint pos_y;
171         sclint width;
172         sclint height;
173         SCLLabelAlignment align;
174         sclshort padding_x;
175         sclshort padding_y;
176         sclbyte inner_width;
177         sclbyte inner_height;
178     } TextCache;
179
180 extern std::vector<ImageCache> g_ImageCache;
181 extern std::vector<TextCache> g_TextCache;
182 #else
183 #endif
184
185 /**
186  * Sets the current input mode to the given mode
187  */
188 sclboolean
189 CSCLController::process_input_mode_change(const sclbyte mode)
190 {
191     SCL_DEBUG();
192
193     sclboolean ret = FALSE;
194
195     CSCLUtils *utils = CSCLUtils::get_instance();
196     CSCLContext *context = CSCLContext::get_instance();
197     CSCLWindows *windows = CSCLWindows::get_instance();
198     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
199     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
200     PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
201     assert(sclres_input_mode_configure != NULL);
202
203     if (context && windows && cache && utils) {
204         if (mode == context->get_input_mode() || mode == (sclbyte)NOT_USED) {
205             /* ButtonContext does not get initialized if we don't call here */
206             cache->recompute_layout(windows->get_base_window());
207             return FALSE;
208         }
209
210         context->set_input_mode(mode);
211         /* FIXME : NEWXML temporary commenting out */
212         //context->set_base_layout(sclres_input_mode_configure[mode].layouts[context->get_display()]);
213
214         _play_tts_for_input_mode_name(mode);
215
216         sclwindow window = windows->get_base_window();
217         handle_engine_signal(SCL_SIG_INPMODE_CHANGE, window);
218
219 #ifdef TEST_NEWBACKEND
220         SclWindowContext *window_context= windows->get_window_context(window, FALSE);
221         if (window_context) {
222             if (window_context->etc_info) {
223
224                 Eina_List *list = (Eina_List*)(window_context->etc_info);
225                 Eina_List *iter = NULL;
226                 Eina_List *iter_next = NULL;
227                 void *data = NULL;
228                 int iIndex = 0;
229
230                 EINA_LIST_FOREACH_SAFE(list, iter, iter_next, data) {
231                     if (data) {
232                         EFLObject *object = (EFLObject*)(data);
233                         if (object) {
234                             Evas_Object* eo = object->object;
235                             if (object->extracted) {
236                                 void *data = evas_object_image_data_get(eo, 1);
237                                 if (data) {
238                                     free(data);
239                                 }
240                             }
241
242                             sclint loop;
243                             for(loop = 0;loop < g_ImageCache.size();loop++) {
244                                 if (g_ImageCache[loop].image == object->object) {
245                                     g_ImageCache[loop].used = FALSE;
246                                 }
247                             }
248                             for(loop = 0;loop < g_TextCache.size();loop++) {
249                                 if (g_TextCache[loop].text == object->object) {
250                                     g_TextCache[loop].used = FALSE;
251                                 }
252                             }
253
254                             if (eo) {
255                                 evas_object_del(eo);
256                                 object->object = NULL;
257                             }
258                             delete object;
259                         }
260                         list = eina_list_remove_list(list, iter);
261                     }
262                     iIndex++;
263                 }
264                 window_context->etc_info= list;
265             }
266         }
267 #endif
268     }
269
270     return ret;
271 }
272
273 /**
274  * Sets the current display mode to the given mode
275  */
276 sclboolean
277 CSCLController::process_rotation_change(const SCLRotation rotation)
278 {
279     SCL_DEBUG();
280     CSCLContext *context = CSCLContext::get_instance();
281     CSCLWindows *windows = CSCLWindows::get_instance();
282     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
283     PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
284     assert(sclres_input_mode_configure != NULL);
285
286     if (context && windows) {
287         SCLDisplayMode mode;
288         if (rotation == ROTATION_90_CW || rotation == ROTATION_90_CCW) {
289             mode = DISPLAYMODE_LANDSCAPE;
290         } else {
291             mode = DISPLAYMODE_PORTRAIT;
292         }
293
294         //if (mode == context->get_display()) return FALSE;
295         context->set_display_mode(mode);
296         context->set_rotation(rotation);
297         /* FIXME : NEWXML temporary commenting out */
298         //context->set_base_layout(sclres_input_mode_configure[context->get_input_mode()].layouts[context->get_display()]);
299
300         sclwindow window = windows->get_base_window();
301         handle_engine_signal(SCL_SIG_DISP_CHANGE, window);
302         windows->update_window(window);
303
304         /* Moved to here since the new WMSync requires the rotation call be invoked as the
305            last step of display change process */
306         /* Make sure to set window's rotation degree before sending engine signal, which adjusts the size of main window */
307         windows->set_window_rotation(NULL, rotation);
308     }
309     return TRUE;
310 }
311
312 /**
313  * Checks if the given button with given touch_id needs magnifier window
314  */
315 sclboolean
316 CSCLController::check_magnifier_available(sclwindow window, sclbyte key_index, scltouchdevice touch_id)
317 {
318     sclboolean ret = FALSE;
319
320     CSCLContext *context = CSCLContext::get_instance();
321     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
322     const SclLayout *layout = NULL;
323     SclButtonContext *button_context = NULL;
324     const SclLayoutKeyCoordinate *coordinate = NULL;
325
326     if (context && cache) {
327         layout = cache->get_cur_layout(window);
328         button_context = cache->get_cur_button_context(window, key_index);
329         coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
330
331         SCLShiftState shift_index = context->get_shift_state();
332         if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
333         if (context->get_caps_lock_mode()) {
334             shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
335         }
336
337         if (layout && coordinate && button_context && context->get_magnifier_enabled() ) {
338             if (coordinate->key_type != KEY_TYPE_CONTROL &&
339                 coordinate->key_type != KEY_TYPE_MODECHANGE &&
340                 coordinate->key_type != KEY_TYPE_NONE) {
341
342                     ret = TRUE;
343
344                     /* Do not show if current layout does not allow magnifier */
345                     if (!(layout->use_magnifier_window)) {
346                         //utils->log("show_magnifier !(layout->use_magnifier_window \n");
347                         ret = FALSE;
348                     }
349
350                     /* Do not show if there's nothing to show */
351                     const sclchar* custom_label = NULL;
352                     for(sclint label_index = 0;label_index < MAX_SIZE_OF_LABEL_FOR_ONE && !custom_label;label_index++) {
353                         const sclchar *temp_label = context->get_custom_magnifier_label(touch_id, label_index);
354                         if (temp_label) {
355                             custom_label = temp_label;
356                         }
357                     }
358                     if (!custom_label) {
359                         //if (coordinate->key_value[shift_index][button_context->multikeyIdx] == NULL) {
360                         if (coordinate->label[shift_index][button_context->multikeyIdx] == NULL) {
361                             //utils->log("show_magnifier coordinate->key_value[shift][button_context->multikeyIdx] == NULL \n");
362                             ret = FALSE;
363                             //} else if (strlen(coordinate->key_value[shift_index][button_context->multikeyIdx]) == 0) {
364                         } else if (strlen(coordinate->label[shift_index][button_context->multikeyIdx]) == 0) {
365                             //utils->log("show_magnifier coordinate->key_value[shift][button_context->multikeyIdx]) == 0 \n");
366                             ret = FALSE;
367                         }
368                     }
369
370                     if (touch_id != context->get_last_touch_device_id()) {
371                         ret = FALSE;
372                     }
373                 }
374         }
375     }
376
377     return ret;
378 }
379
380 sclboolean
381 CSCLController::process_button_pressed_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
382                                              scltouchdevice touch_id, sclboolean actual_event)
383 {
384     SCL_DEBUG();
385
386     sclboolean ret = FALSE;
387     sclboolean redraw = FALSE;
388
389     CSCLContext *context = CSCLContext::get_instance();
390     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
391     CSCLWindows *windows = CSCLWindows::get_instance();
392     CSCLEvents *events = CSCLEvents::get_instance();
393     CSCLUtils *utils = CSCLUtils::get_instance();
394     CSCLFeedback *feedback = CSCLFeedback::get_instance();
395     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
396     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
397     PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
398     PSclLayout sclres_layout = sclres_manager->get_layout_table();
399     assert(sclres_input_mode_configure != NULL);
400     assert(sclres_layout != NULL);
401
402     SclButtonContext *button_context = NULL;
403     const SclLayoutKeyCoordinate *coordinate = NULL;
404
405     if (context && cache) {
406         button_context = cache->get_cur_button_context(window, key_index);
407         coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
408     }
409
410     if (context && cache && windows && events && utils && feedback && handler && button_context && coordinate) {
411         /* First check if this button is enabled in current active sublayout */
412         sclboolean sub_layout_match = TRUE;
413         if (coordinate->sub_layout && context->get_cur_sublayout()) {
414             if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
415                 sub_layout_match = FALSE;
416             }
417         }
418         /* If this button is pressed */
419         if ( x >= coordinate->x - coordinate->add_hit_left &&
420                 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
421                 y >= coordinate->y - coordinate->add_hit_top &&
422                 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
423                 /* Process the event only if the this item's sublayout id is active one */
424                 sub_layout_match ) {
425             //utils->log("process_button_pressed_event___TRUE\n");
426
427             /* If newly pressed key has type MULTI_TOUCH_TYPE_EXCLUSIVE, release all existing pressed events */
428             if (actual_event) {
429                 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_EXCLUSIVE) {
430                     /* When calling mouse_release, the seq order of current multitouch events will be changed,
431                     so we put all the multitouch events into a vector and use them afterwards forreleasing */
432                     sclint loop = 0;
433                     sclint multi_touch_context_num = context->get_multi_touch_context_num();
434                     std::vector<SclUIEventDesc> multi_touch_events;
435                     for(loop = 0;loop < multi_touch_context_num;loop++) {
436                         SclUIEventDesc desc;
437                         context->get_multi_touch_event(loop, &desc);
438                         multi_touch_events.push_back(desc);
439                     }
440                     for(loop = 0;loop < multi_touch_context_num;loop++) {
441                         SclUIEventDesc desc = multi_touch_events[loop];
442                         if (desc.touch_id != touch_id) {
443                             mouse_release(context->get_cur_moving_window(desc.touch_id),
444                                 context->get_cur_moving_point(desc.touch_id).x,
445                                 context->get_cur_moving_point(desc.touch_id).y,
446                                 desc.touch_id, FALSE);
447                         }
448                     }
449                 }
450             }
451
452             /* Make an unique ID for timer */
453             const scl16 uniqId = utils->get_unique_id();
454
455             context->set_cur_pressed_event_id(touch_id, uniqId);
456             context->set_cur_pressed_key(touch_id, key_index);
457             context->set_cur_pressed_window(touch_id, window);
458
459             button_context->state = BUTTON_STATE_PRESSED;
460
461             redraw = TRUE;
462             ret = TRUE;
463
464 #ifndef DIRECTLY_DRAW_ON_EVENTS
465             /* If the window doesn't get exposed before corresponding release event,
466              * the inverted state of a button will never be drawn onto screen.
467              * To prevent such a case, we draw the inverted state of button forcefully and directly,
468              * without waiting for expose event */
469             /*CSCLGraphics *grps = CSCLGraphics::get_instance();
470             CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
471             scldrawctx draw_ctx = grps->begin_paint(window, TRUE);
472             builder->draw_button(window, draw_ctx, key_index, button_context->state, TRUE);
473             grps->end_paint(window, draw_ctx);*/
474 #endif
475
476             /* for feedback */
477             feedback->button_pressed(window, key_index);
478
479             /* Special routine for autopopup */
480             if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
481                 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
482             } else {
483                 /* for long key & repeat key */
484                 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
485             }
486
487             SCLShiftState shift_index = context->get_shift_state();
488             if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
489             if (context->get_caps_lock_mode()) {
490                 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
491             }
492
493             SclUIEventDesc key_event_desc;
494             key_event_desc.key_value = coordinate->key_value[shift_index][0];
495             key_event_desc.key_event = coordinate->key_event[shift_index][0];
496             key_event_desc.key_type = coordinate->key_type;
497             key_event_desc.key_modifier = KEY_MODIFIER_NONE;
498             key_event_desc.event_type = EVENT_TYPE_PRESS;
499
500             SclPoint curpoint = {x, y};
501             key_event_desc.touch_id = touch_id;
502             key_event_desc.mouse_pressed_point = curpoint;
503             key_event_desc.mouse_current_point = curpoint;
504             key_event_desc.mouse_farthest_point = curpoint;
505
506             key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
507
508             SCLEventReturnType processed = handler->on_event_drag_state_changed(key_event_desc);
509
510             /* Only if the handler didn't return SCL_EVENT_DONE */
511             if (processed == SCL_EVENT_PASS_ON) {
512                 /* Now process normal behaviours of each button type */
513                 switch (coordinate->button_type) {
514                 case BUTTON_TYPE_NORMAL:
515                 case BUTTON_TYPE_GRAB:
516                 case BUTTON_TYPE_SELFISH:
517                 case BUTTON_TYPE_DIRECTION:
518                 case BUTTON_TYPE_RELATIVE_DIRECTION: {
519                     /* Send click event right away if this button uses repeat key */
520                     if (coordinate->use_repeat_key) {
521                         handler->on_event_key_clicked(key_event_desc);
522                     }
523                 }
524                 break;
525                 case BUTTON_TYPE_MULTITAP: {
526                 }
527                 break;
528                 case BUTTON_TYPE_ROTATION: {
529                 }
530                 break;
531                 case BUTTON_TYPE_DRAG: {
532                     /* Drag buttons fires click event immediately when they are pressed */
533                     handler->on_event_key_clicked(key_event_desc);
534                 }
535                 break;
536                 case BUTTON_TYPE_UIITEM: break;
537                 case MAX_BUTTON_TYPE: break;
538                 default: break;
539                 }
540                 switch (coordinate->popup_type) {
541                 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: {
542                     SclNotiPopupOpeningDesc desc;
543                     desc.ui_event_desc = &key_event_desc;
544                     desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
545                     if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
546                         sclint popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
547                         SCLDisplayMode display_mode = context->get_display_mode();
548                         /* FIXME */
549                         //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
550                         if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
551                             scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
552                             sclshort popupLayoutId =
553                                 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
554                             SclRectangle popupRect;
555                             SclRectangle baseWndRect;
556                             SclLayout *layout = NULL;
557                             /* FIXME */
558                             //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
559                             if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
560                                 layout = &sclres_layout[popupLayoutId];
561                             }
562                             if (layout) {
563                                 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
564                                 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
565                                 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
566                                 //popupRect.width = utils->get_scale_x(layout->width);
567                                 //popupRect.height= utils->get_scale_y(layout->height);
568                                 popupRect.width = layout->width;
569                                 popupRect.height= layout->height;
570                                 windows->close_all_popups();
571
572                                 SclWindowOpener opener;
573                                 opener.window = window;
574                                 opener.key = key_index;
575
576                                 sclwindow popup_window = windows->open_popup(opener,
577                                     popupRect,
578                                     popup_input_mode,
579                                     popupLayoutId,
580                                     coordinate->popup_type,
581                                     sclres_input_mode_configure[popup_input_mode].use_virtual_window,
582                                     sclres_input_mode_configure[popup_input_mode].use_dim_window,
583                                     coordinate->extract_offset_x,
584                                     coordinate->extract_offset_y,
585                                     sclres_input_mode_configure[popup_input_mode].timeout
586                                     );
587
588                                 SclNotiPopupOpenedDesc opened_desc;
589                                 opened_desc.ui_event_desc = &key_event_desc;
590                                 opened_desc.input_mode = desc.input_mode;
591                                 opened_desc.window = popup_window;
592                                 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
593
594                                 windows->hide_window(windows->get_magnifier_window());
595                                 /* FIXME : The parent key should be turned back to NORMAL state when RELEASED,
596                                     in case of POPUP_TYPE_BTN_PRESS_POPUP_DRAG type. Temporariliy setting NORMAL here. */
597                                 button_context->state = BUTTON_STATE_NORMAL;
598                                 _play_tts_for_input_mode_name(popup_input_mode);
599                             }
600                         }
601                     }
602                 }
603                 break;
604                 case POPUP_TYPE_BTN_RELEASE_POPUP:
605                 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
606                 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
607                 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
608                 case POPUP_TYPE_AUTO_POPUP:
609                 case POPUP_TYPE_NONE:
610                 case MAX_POPUP_TYPE:
611                 default:
612                     /* Nothing to do in here */
613                     break;
614                 }
615             }
616
617             /* Shows the magnifier window(the magnifier window will display when a kind of button type is character) */
618             //if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
619             if (coordinate->use_magnifier) {
620                 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
621
622                 PSclMagnifierWndConfigure magnifier_configure = NULL;
623                 if (sclres_manager) {
624                     magnifier_configure = sclres_manager->get_magnifier_configure();
625                 }
626                 if (showMagnifier && magnifier_configure) {
627                     SclPoint pos = {0,0};
628                     /* calculates x position to be set */
629                     pos.x = (coordinate->x + (coordinate->width / 2)) -
630                         (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
631
632                     /* calculates y position to be set */
633                     sclint scnWidth, scnHeight;
634                     utils->get_screen_resolution(&scnWidth, &scnHeight);
635
636                     pos.y = coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
637
638                     /* FIXME : Temporary way of clearing magnifier window */
639                     /*SclWindowContext *window_context = windows->get_window_context(windows->get_magnifier_window(), FALSE);
640                     sclboolean clearmagwin = FALSE;
641                     if (window_context) {
642                         clearmagwin = !(window_context->hidden);
643                     }
644                     static int clearnum = 0;
645                     if (key_index == prevkey && window == prevwin) {
646                         clearmagwin = FALSE;
647                     }
648                     if (clearmagwin) {
649                         if (++clearnum > 1) {
650                             clearmagwin = FALSE;
651                         }
652                     } else {
653                         clearnum = 0;
654                     }
655
656                     if (clearmagwin) {
657                         CSCLGraphics *graphics = CSCLGraphics::get_instance();
658                         CSCLUtils *utils = CSCLUtils::get_instance();
659                         sclchar composed_path[_POSIX_PATH_MAX] = {0,};
660                         scldrawctx draw_ctx = graphics->begin_paint(windows->get_magnifier_window());
661                         utils->get_composed_path(composed_path, scl_magnifier_configure.bg_image_path);
662                         graphics->draw_image(windows->get_magnifier_window(), draw_ctx, composed_path, 0, 0);
663                         graphics->end_paint(windows->get_magnifier_window(), draw_ctx);
664                     }
665                     */
666                     windows->hide_window(windows->get_magnifier_window());
667
668                     SclWindowContext *window_context = windows->get_window_context(window);
669                     if (window_context) {
670                         pos.x += window_context->geometry.x;
671                         pos.y += window_context->geometry.y;
672                     }
673
674                     if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
675                         pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
676                     }
677                     if (pos.x > scnWidth +
678                         magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
679                         magnifier_configure->width * utils->get_custom_scale_rate_x()) {
680                         pos.x = scnWidth + magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
681                             magnifier_configure->width * utils->get_custom_scale_rate_x();
682                     }
683                     pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
684                     pos.x += coordinate->magnifier_offset_x;
685                     pos.y += coordinate->magnifier_offset_y;
686                     windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
687                     //windows->resize_window(windows->get_magnifier_window(), utils->get_scale_x(scl_magnifier_configure.width), utils->get_scale_y(scl_magnifier_configure.height));
688                     /*If we use transient_for them the ISE will occure some crash. It needs to check X11 */
689                     /*windows->set_parent(windows->get_base_window(), windows->get_magnifier_window());*/
690
691                     windows->show_window(windows->get_magnifier_window(), TRUE);
692                     //windows->update_window(windows->get_magnifier_window());
693                 }
694 #if 0
695                 static int fFirst = true;
696                 if (fFirst) {
697                     windows->show_window(windows->get_magnifier_window());
698                     fFirst = false;
699                 } else {
700                     windows->update_window(windows->get_magnifier_window());
701                 }
702 #endif
703                 /* We cannot use move_resize_window. It had occured some wrong behavior */
704                 /*windows->move_resize_window(windows->get_magnifier_window(), pos.x, pos.y, scl_magnifier_configure.width, scl_magnifier_configure.height);*/
705                 if (!showMagnifier) {
706                     windows->hide_window(windows->get_magnifier_window());
707                 }
708             }
709         } else {
710             /* COMMENTED OUT FOR TESTING MULTITOUCH!! */
711             ///* In case the current button is not the given key index */
712             //if (button_context->state == BUTTON_STATE_PRESSED) {
713             //    /* Even if the press event occured outside of this button's physical area, reset its context */
714             //    button_context->state = BUTTON_STATE_NORMAL;
715             //    redraw = TRUE;
716             //}
717             /* BUTTON_TYPE_MULTITAP type button should restore its multikey index when another button is clicked */
718             if (coordinate->button_type & BUTTON_TYPE_MULTITAP) {
719                 button_context->multikeyIdx = 0;
720             }
721         }
722
723         /* If there is any need for redrawing */
724         if (redraw) {
725 #ifdef DIRECTLY_DRAW_ON_EVENTS
726             CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
727             if (builder) {
728                 builder->draw_button(window, NULL, key_index, button_context->state, TRUE);
729             }
730 #else
731             if (windows) {
732                 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
733             }
734 #endif
735         }
736     }
737
738     return ret;
739 }
740
741 sclboolean
742 CSCLController::process_button_long_pressed_event(sclwindow window, sclbyte key_index,
743                                                   scltouchdevice touch_id, sclboolean actual_event)
744 {
745     SCL_DEBUG();
746
747     sclboolean ret = FALSE;
748
749     CSCLContext *context = CSCLContext::get_instance();
750     CSCLWindows *windows = CSCLWindows::get_instance();
751     CSCLActionState *state = CSCLActionState::get_instance();
752     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
753     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
754     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
755     PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
756     PSclLayout sclres_layout = sclres_manager->get_layout_table();
757
758     assert(sclres_input_mode_configure != NULL);
759     assert(sclres_layout != NULL);
760     if (context && cache && handler && windows && state) {
761         const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
762
763         /* Should return FALSE if this key does not have any longkey related property */
764         if (coordinate) {
765             if (actual_event) {
766                 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
767                     /* When calling mouse_release, the seq order of current multitouch events will be ch anged,
768                        so we put all the multitouch events into a vector and use them afterwards for rel easing */
769                     sclboolean finished = FALSE;
770                     sclint loop = 0;
771                     sclint multi_touch_context_num = context->get_multi_touch_context_num();
772                     std::vector<SclUIEventDesc> multitouch_events;
773                     for (loop = 0;loop < multi_touch_context_num;loop++) {
774                         SclUIEventDesc desc;
775                         context->get_multi_touch_event(loop, &desc);
776                         multitouch_events.push_back(desc);
777                     }
778                     for (loop = 0;loop < multi_touch_context_num && !finished;loop++) {
779                         SclUIEventDesc desc = multitouch_events[loop];
780                         if (desc.touch_id != touch_id) {
781                             sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
782                             scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
783                             const SclLayoutKeyCoordinate *cur_pressed_coordinate =
784                                 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
785                             if (cur_pressed_coordinate) {
786                                 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
787                                     mouse_release(context->get_cur_moving_window(desc.touch_id),
788                                         context->get_cur_moving_point(desc.touch_id).x,
789                                         context->get_cur_moving_point(desc.touch_id).y,
790                                         desc.touch_id, FALSE);
791                                 }
792                             }
793                         } else {
794                             finished = TRUE;
795                         }
796                     }
797                 }
798             }
799         }
800
801         /* Should return FALSE if this key does not have any longkey related property */
802         if (coordinate) {
803             if (coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP ||
804                 coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE ) {
805
806                     SclUIEventDesc key_event_desc;
807                     key_event_desc.key_type = coordinate->long_key_type;
808                     if (coordinate->long_key_value == NULL && coordinate->long_key_event == 0) {
809                         SCLShiftState shift_index = context->get_shift_state();
810                         if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
811                         if (context->get_caps_lock_mode()) {
812                             shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
813                         }
814
815                         key_event_desc.key_value = coordinate->key_value[shift_index][0];
816                         key_event_desc.key_event = coordinate->key_event[shift_index][0];
817                     } else {
818                         key_event_desc.key_value = coordinate->long_key_value;
819                         key_event_desc.key_event = coordinate->long_key_event;
820                     }
821                     key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
822
823                     key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
824                     key_event_desc.touch_id = touch_id;
825                     key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
826                     key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
827                     key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
828
829                     key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
830
831                     SCLEventReturnType processed = handler->on_event_drag_state_changed(key_event_desc);
832
833                     /* Only if the handler didn't return SCL_EVENT_DONE */
834                     if (processed == SCL_EVENT_PASS_ON) {
835                         SclRectangle popupRect;
836                         SclRectangle baseWndRect;
837                         windows->get_window_rect(windows->get_base_window(), &baseWndRect);
838                         popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
839                         popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
840
841                         SclNotiPopupOpeningDesc desc;
842                         desc.ui_event_desc = &key_event_desc;
843                         desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
844                         if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
845                             sclint popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
846                             SCLDisplayMode display_mode = context->get_display_mode();
847                             /* FIXME */
848                             //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
849                             if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
850                                 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
851                                 SclLayout *layout = NULL;
852                                 sclshort popupLayoutId =
853                                     sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
854                                 /* FIXME */
855                                 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
856                                 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
857                                     layout = &sclres_layout[popupLayoutId];
858                                 }
859                                 if (layout) {
860                                     //popupRect.width = utils->get_scale_x(layout->width);
861                                     //popupRect.height= utils->get_scale_y(layout->height);
862                                     popupRect.width = layout->width;
863                                     popupRect.height= layout->height;
864
865                                     SclWindowOpener opener;
866                                     opener.window = window;
867                                     opener.key = key_index;
868
869                                     sclwindow popup_window = windows->open_popup(
870                                         opener,
871                                         popupRect,
872                                         popup_input_mode,
873                                         popupLayoutId,
874                                         coordinate->popup_type,
875                                         sclres_input_mode_configure[popup_input_mode].use_virtual_window,
876                                         sclres_input_mode_configure[popup_input_mode].use_dim_window,
877                                         coordinate->extract_offset_x,
878                                         coordinate->extract_offset_y,
879                                         sclres_input_mode_configure[popup_input_mode].timeout
880                                         );
881
882                                     SclNotiPopupOpenedDesc opened_desc;
883                                     opened_desc.ui_event_desc = &key_event_desc;
884                                     opened_desc.input_mode = desc.input_mode;
885                                     opened_desc.window = popup_window;
886                                     handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
887
888                                     windows->hide_window(windows->get_magnifier_window());
889                                     _play_tts_for_input_mode_name(popup_input_mode);
890                                     ret = TRUE;
891                                 }
892                             }
893                         }
894                     }
895             } else if (coordinate->long_key_value) {
896                 if (strlen(coordinate->long_key_value) > 0) {
897                         if (windows->is_base_window(window)) {
898                             state->set_cur_action_state(ACTION_STATE_BASE_LONGKEY);
899                         } else {
900                             state->set_cur_action_state(ACTION_STATE_POPUP_LONGKEY);
901                         }
902                         ret = TRUE;
903
904                         PSclMagnifierWndConfigure magnifier_configure = NULL;
905                         if (sclres_manager) {
906                             magnifier_configure = sclres_manager->get_magnifier_configure();
907                         }
908                         if (coordinate->use_long_key_magnifier && magnifier_configure) {
909                             CSCLUtils *utils = CSCLUtils::get_instance();
910                             SclPoint pos = {0,0};
911
912                             const SclLayout* layout = cache->get_cur_layout(window);
913                             if (layout) {
914                                 sclint scnWidth, scnHeight;
915                                 utils->get_screen_resolution(&scnWidth, &scnHeight);
916
917                                 //SclWindowContext *window_context = windows->get_window_context(window, TRUE);
918                                 SclWindowContext *window_context = windows->get_window_context(window);
919                                 if (window_context) {
920                                     pos.x = window_context->geometry.x + (coordinate->x + (coordinate->width / 2)) -
921                                         (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
922                                     pos.y = window_context->geometry.y + coordinate->y -
923                                         magnifier_configure->height * utils->get_custom_scale_rate_y();
924                                 }
925                                 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
926                                     pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
927                                 }
928                                 if (pos.x > scnWidth +
929                                     magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
930                                     magnifier_configure->width * utils->get_custom_scale_rate_x()) {
931                                     pos.x = scnWidth +
932                                         magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
933                                         magnifier_configure->width * utils->get_custom_scale_rate_x();
934                                 }
935                                 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
936                                 pos.x += coordinate->magnifier_offset_x;
937                                 pos.y += coordinate->magnifier_offset_y;
938                                 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
939                                 windows->update_window(windows->get_magnifier_window());
940                                 windows->show_window(windows->get_magnifier_window(),TRUE);
941                             }
942                         }
943
944                         SclUIEventDesc key_event_desc;
945                         key_event_desc.key_type = coordinate->long_key_type;
946                         key_event_desc.key_value = coordinate->long_key_value;
947                         key_event_desc.key_event = coordinate->long_key_event;
948                         key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
949
950                         key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
951                         key_event_desc.touch_id = touch_id;
952                         key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
953                         key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
954                         key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
955
956                         key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
957
958                         handler->on_event_key_clicked(key_event_desc);
959                     //}
960                 }
961             }
962         }
963         if (ret) {
964             context->set_cur_key_modifier(touch_id, KEY_MODIFIER_LONGKEY);
965         }
966     }
967     /* Longkey processing in here */
968     return ret;
969 }
970
971 sclboolean
972 CSCLController::process_button_repeat_pressed_event(sclwindow window, sclbyte key_index,
973                                                     scltouchdevice touch_id, sclboolean actual_event)
974 {
975     SCL_DEBUG();
976     CSCLContext *context = CSCLContext::get_instance();
977     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
978     CSCLWindows *windows = CSCLWindows::get_instance();
979     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
980
981     if (context && cache && windows && handler) {
982         const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
983
984         SCLShiftState shift_index = context->get_shift_state();
985         if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
986         if (context->get_caps_lock_mode()) {
987             shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
988         }
989
990         if (coordinate) {
991             switch (coordinate->button_type) {
992                 case BUTTON_TYPE_NORMAL:
993                 case BUTTON_TYPE_GRAB:
994                 case BUTTON_TYPE_SELFISH:
995                 case BUTTON_TYPE_DIRECTION:
996                 case BUTTON_TYPE_RELATIVE_DIRECTION: {
997                     /* This is for enabling backspace key in search layout*/
998                     //if (coordinate->key_type != KEY_TYPE_MODECHANGE && coordinate->key_type != KEY_TYPE_COMPOSITION) {
999                     //if (coordinate->key_type != KEY_TYPE_MODECHANGE || coordinate->key_event[0][0] == MVK_BackSpace) {
1000                     if (coordinate->key_type != KEY_TYPE_MODECHANGE) {
1001                         sclulong repeatKeyEvent = coordinate->key_event[shift_index][0];
1002
1003                         /* In case of Delete key, Change from Char deletion to Word deletion
1004                            when the input acceleration speed is reached to Max */
1005                         SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1006                         PSclDefaultConfigure default_configure = NULL;
1007                         if (sclres_manager) {
1008                             default_configure = sclres_manager->get_default_configure();
1009                         }
1010                         if (default_configure) {
1011                             if (default_configure->use_word_deletion) {
1012                                 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
1013                                 if (repeatKeyEvent == MVK_BackSpace &&
1014                                     interval <= SCL_REPEATKEY_WORD_DELETION_START_DURATION) {
1015                                     repeatKeyEvent = MVK_3270_DeleteWord;
1016                                 }
1017                             }
1018                         }
1019
1020                         SclUIEventDesc key_event_desc;
1021                         key_event_desc.key_value = coordinate->key_value[shift_index][0];
1022                         key_event_desc.key_event = repeatKeyEvent;
1023                         key_event_desc.key_type = coordinate->key_type;
1024                         key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1025
1026                         key_event_desc.event_type = EVENT_TYPE_REPEAT;
1027                         key_event_desc.touch_id = touch_id;
1028                         key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1029                         key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1030                         key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1031
1032                         key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1033
1034                         handler->on_event_key_clicked(key_event_desc);
1035                     }
1036                 }
1037                 break;
1038                 case BUTTON_TYPE_UIITEM: break;
1039                 case MAX_BUTTON_TYPE: break;
1040                 default: break;
1041             }
1042         }
1043     }
1044
1045     /* Longkey processing in here */
1046     return TRUE;
1047 }
1048
1049 sclboolean
1050 CSCLController::process_button_move_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1051                                           scltouchdevice touch_id, sclboolean actual_event)
1052 {
1053     SCL_DEBUG();
1054
1055     sclboolean ret = FALSE;
1056
1057     CSCLUtils *utils = CSCLUtils::get_instance();
1058     CSCLEvents *events = CSCLEvents::get_instance();
1059     CSCLContext *context = CSCLContext::get_instance();
1060     CSCLWindows *windows = CSCLWindows::get_instance();
1061     CSCLFeedback *feedback = CSCLFeedback::get_instance();
1062     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1063     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1064
1065     SclButtonContext *button_context = NULL;
1066
1067     const SclLayoutKeyCoordinate *coordinate = NULL;
1068
1069     if (cache) {
1070         coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1071         button_context = cache->get_cur_button_context(window, key_index);
1072     }
1073
1074     if (button_context && coordinate && feedback && utils && context && handler && cache && events && windows) {
1075         /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1076         sclint thresholdX = 0;
1077         sclint thresholdY = 0;
1078         if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1079             thresholdX = utils->get_scaled_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1080             thresholdY = utils->get_scaled_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1081         }
1082
1083         /* First check if this button is enabled in current active sublayout */
1084         sclboolean subLayoutMatch = TRUE;
1085         if (coordinate->sub_layout && context->get_cur_sublayout()) {
1086             if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1087                 subLayoutMatch = FALSE;
1088             }
1089         }
1090         if ( x >= coordinate->x - coordinate->add_hit_left  - thresholdX &&
1091             x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX&&
1092                 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1093                 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1094                 subLayoutMatch ) {
1095             ret = TRUE;
1096
1097             SCLShiftState shift_index = context->get_shift_state();
1098             if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1099             if (context->get_caps_lock_mode()) {
1100                 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1101             }
1102
1103             const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1104
1105             sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1106             scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1107             SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1108             const SclLayoutKeyCoordinate *pressed_coordinate =
1109                 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1110
1111             if (pressed_context == NULL || pressed_coordinate == NULL) {
1112                 return FALSE;
1113             }
1114
1115             if (key_index != pressed_key || window != pressed_window ) {
1116                 /* When the focus has moved to another button, destroy all the timers */
1117                 events->destroy_all_timer();
1118
1119                 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1120                     if (layout) {
1121                         const scl16 uniqId = utils->get_unique_id();
1122                         context->set_cur_pressed_event_id(touch_id, uniqId);
1123                         /* Special routine for autopopup */
1124                         if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
1125                             events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
1126                         } else {
1127                             /* for long key & repeat key */
1128                             events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
1129                         }
1130
1131                         context->set_cur_pressed_window(touch_id, window);
1132                         context->set_cur_pressed_key(touch_id, key_index);
1133
1134                         sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
1135
1136                         SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1137                         PSclMagnifierWndConfigure magnifier_configure = NULL;
1138                         if (sclres_manager) {
1139                             magnifier_configure = sclres_manager->get_magnifier_configure();
1140                         }
1141                         if (showMagnifier && magnifier_configure) {
1142                             SclPoint pos = {0,0};
1143                             /* calculates x position to be set */
1144                             pos.x = (coordinate->x + (coordinate->width / 2)) -
1145                                 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
1146
1147                             /* calculates y position to be set */
1148                             sclint scnWidth, scnHeight;
1149                             utils->get_screen_resolution(&scnWidth, &scnHeight);
1150
1151                             pos.y = (scnHeight - layout->height) + coordinate->y -
1152                                 magnifier_configure->height * utils->get_custom_scale_rate_y();
1153
1154                             if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
1155                                 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
1156                             }
1157                             if (pos.x > scnWidth +
1158                                 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1159                                 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
1160                                 pos.x = scnWidth +
1161                                     magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1162                                     magnifier_configure->width * utils->get_custom_scale_rate_x();
1163                             }
1164                             pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1165                             if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
1166                                 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
1167                                 windows->update_window(windows->get_magnifier_window());
1168                             }
1169                         }
1170
1171                         /* for feedback */
1172                         feedback->button_moved(window, key_index);
1173
1174                         button_context->state = BUTTON_STATE_PRESSED;
1175                         if (pressed_context) {
1176                             /* But, if this button should be in pressed state in other multitouch id, do not initialize it */
1177                             sclboolean found = FALSE;
1178                             for(sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1179                                 SclUIEventDesc desc;
1180                                 context->get_multi_touch_event(loop, &desc);
1181                                 if (desc.touch_id != touch_id) {
1182                                     MultiTouchContext *multi_touch_context =
1183                                         context->find_multi_touch_context(desc.touch_id);
1184                                     if (multi_touch_context) {
1185                                         if (multi_touch_context->cur_pressed_window == pressed_window &&
1186                                             multi_touch_context->cur_pressed_key == pressed_key) {
1187                                             found = TRUE;
1188                                         }
1189                                     }
1190                                 }
1191                             }
1192                             if (!found) {
1193                                 pressed_context->state = BUTTON_STATE_NORMAL;
1194                             }
1195                         }
1196                         /* If the window doesn't get exposed before corresponding release event,
1197                         * the inverted state of a button will never be drawn onto screen.
1198                         * To prevent such a case, we draw the inverted state of button forcefully and directly,
1199                         * without waiting for expose event */
1200                         /* Redrawing pressed button does not work properly, commented out */
1201                         /*
1202                         CSCLGraphics *grps = CSCLGraphics::get_instance();
1203                         CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1204                         scldrawctx draw_ctx;
1205                         if (pressed_window != SCLWINDOW_INVALID && pressed_key != NOT_USED) {
1206                             draw_ctx = grps->begin_paint(pressed_window, TRUE);
1207                             builder->draw_button(pressed_window, draw_ctx, pressed_key, FALSE);
1208                             grps->end_paint(pressed_window, draw_ctx);
1209                         }
1210                         draw_ctx = grps->begin_paint(window, TRUE);
1211                         builder->draw_button(window, draw_ctx, key_index, TRUE);
1212                         grps->end_paint(window, draw_ctx);
1213                         */
1214
1215                         switch (coordinate->button_type) {
1216                         case BUTTON_TYPE_DRAG: {
1217                             SclUIEventDesc key_event_desc;
1218                             key_event_desc.key_value = coordinate->key_value[shift_index][0];
1219                             key_event_desc.key_event = coordinate->key_event[shift_index][0];
1220                             key_event_desc.key_type = coordinate->key_type;
1221                             key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1222
1223                             key_event_desc.event_type = EVENT_TYPE_MOVE;
1224                             key_event_desc.touch_id = touch_id;
1225                             key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1226                             key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1227                             key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1228
1229                             key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1230
1231                             if (sclres_manager) {
1232                                 magnifier_configure = sclres_manager->get_magnifier_configure();
1233                             }
1234                             sclboolean processed = handler->on_event_drag_state_changed(key_event_desc);
1235                             if (processed && context->get_magnifier_enabled() && magnifier_configure) {
1236                                 SclPoint zoomwinpos = {0,0};
1237                                 /* calculates x position to be set */
1238                                 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
1239                                     (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
1240
1241                                 /* calculates y position to be set */
1242                                 sclint scnWidth, scnHeight;
1243                                 utils->get_screen_resolution(&scnWidth, &scnHeight);
1244
1245                                 zoomwinpos.y = coordinate->y -
1246                                     magnifier_configure->height * utils->get_custom_scale_rate_y();
1247                                 SclWindowContext *window_context = windows->get_window_context(window);
1248                                 if (window_context) {
1249                                     zoomwinpos.x += window_context->geometry.x;
1250                                     zoomwinpos.y += window_context->geometry.y;
1251                                 }
1252                                 if (zoomwinpos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
1253                                     zoomwinpos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
1254                                 }
1255                                 if (zoomwinpos.x > scnWidth +
1256                                     magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1257                                     magnifier_configure->width * utils->get_custom_scale_rate_x()) {
1258                                         zoomwinpos.x = scnWidth +
1259                                             magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1260                                             magnifier_configure->width * utils->get_custom_scale_rate_x();
1261                                 }
1262                                 zoomwinpos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1263                                 zoomwinpos.x += coordinate->magnifier_offset_x;
1264                                 zoomwinpos.y += coordinate->magnifier_offset_y;
1265                                 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y);
1266                                 windows->show_window(windows->get_magnifier_window(), 0);
1267                             }
1268
1269                             handler->on_event_key_clicked(key_event_desc);
1270                             if (!(windows->is_base_window(window))) {
1271                                 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
1272                                 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
1273                                 SclWindowContext *window_context = windows->get_window_context(window);
1274                                 if (window_context) {
1275                                     if (window_context->timeout > 0) {
1276                                         events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
1277                                         events->create_timer(SCL_TIMER_POPUP_TIMEOUT, window_context->timeout, 0, TRUE);
1278                                     }
1279                                 }
1280                             }
1281                         }
1282                         break;
1283                         case BUTTON_TYPE_NORMAL: break;
1284                         case BUTTON_TYPE_GRAB: break;
1285                         case BUTTON_TYPE_SELFISH: break;
1286                         case BUTTON_TYPE_MULTITAP: break;
1287                         case BUTTON_TYPE_ROTATION: break;
1288                         case BUTTON_TYPE_DIRECTION: break;
1289                         case BUTTON_TYPE_RELATIVE_DIRECTION: break;
1290                         case BUTTON_TYPE_UIITEM: break;
1291                         case MAX_BUTTON_TYPE: break;
1292                         default:
1293                             break;
1294                         }
1295
1296 #ifdef DIRECTLY_DRAW_ON_EVENTS
1297                         CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1298                         if (builder) {
1299                             if (button_context) {
1300                                 builder->draw_button(window, NULL, key_index, button_context->state);
1301                             }
1302                             if (pressedContext) {
1303                                 builder->draw_button(pressed_window, NULL, pressed_key, pressedContext->state, TRUE);
1304                             }
1305                         }
1306 #else
1307                         windows->update_window(window,
1308                                 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1309                         if (pressed_coordinate) {
1310                             windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1311                                     pressed_coordinate->width, pressed_coordinate->height);
1312                         }
1313 #endif
1314                     }
1315
1316                     //utils->log("Now Moving : %d %d\n", pos.x, pos.y);
1317                 } else {
1318                     /* If the focus went out from our SELFISH button */
1319                     if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH) {
1320                         pressed_context->state = BUTTON_STATE_NORMAL;
1321                         windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1322                             pressed_coordinate->width, pressed_coordinate->height);
1323                         /* And if this SELFISH button was the last button pressed */
1324                         if (touch_id == context->get_last_touch_device_id()) {
1325                             windows->hide_window(windows->get_magnifier_window());
1326                         }
1327                     }
1328                 }
1329             } else {
1330                 /* If the focus came back into our SELFISH button */
1331                 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH && pressed_context->state != BUTTON_STATE_PRESSED) {
1332                     pressed_context->state = BUTTON_STATE_PRESSED;
1333                     windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1334                         pressed_coordinate->width, pressed_coordinate->height);
1335                     /* And if this SELFISH button was the last button pressed */
1336                     if (touch_id == context->get_last_touch_device_id()) {
1337                         sclboolean showMagnifier = check_magnifier_available(pressed_window, pressed_key, touch_id);
1338
1339                         if (showMagnifier) {
1340                             windows->show_window(windows->get_magnifier_window());
1341                         }
1342                     }
1343                 }
1344             }
1345         }
1346     }
1347
1348     return ret;
1349 }
1350
1351 sclboolean
1352 CSCLController::process_button_over_event(sclwindow window, sclint x, sclint y, sclbyte key_index)
1353 {
1354     SCL_DEBUG();
1355
1356     sclboolean ret = FALSE;
1357
1358     CSCLUtils *utils = CSCLUtils::get_instance();
1359     CSCLEvents *events = CSCLEvents::get_instance();
1360     CSCLContext *context = CSCLContext::get_instance();
1361     CSCLWindows *windows = CSCLWindows::get_instance();
1362     CSCLFeedback *feedback = CSCLFeedback::get_instance();
1363     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1364
1365     SclButtonContext *button_context = NULL;
1366
1367     const SclLayoutKeyCoordinate *coordinate = NULL;
1368     if(cache) {
1369         coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1370         button_context = cache->get_cur_button_context(window, key_index);
1371     }
1372
1373     if(button_context && coordinate && feedback && utils && context && cache && events && windows) {
1374        /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1375         sclboolean subLayoutMatch = TRUE;
1376         if (coordinate->sub_layout && context->get_cur_sublayout()) {
1377             if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1378                 subLayoutMatch = FALSE;
1379             }
1380         }
1381         if ( x >= coordinate->x - coordinate->add_hit_left &&
1382             x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
1383                 y >= coordinate->y - coordinate->add_hit_top &&
1384                 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
1385                 subLayoutMatch ) {
1386             ret = TRUE;
1387
1388             SCLShiftState shift_index = context->get_shift_state();
1389             if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1390             if (context->get_caps_lock_mode()) {
1391                 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1392             }
1393
1394             const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1395
1396             sclwindow highlighted_window = context->get_cur_highlighted_window();
1397             scl8 highlighted_key = context->get_cur_highlighted_key();
1398             SclButtonContext *cur_context = cache->get_cur_button_context(window, key_index);
1399
1400             if(cur_context == NULL) {
1401                 return FALSE;
1402             }
1403             if (key_index != highlighted_key || window != highlighted_window ) {
1404                 SECURE_LOGD("%d != %d || %p != %p", key_index, highlighted_key, window, highlighted_window);
1405                 if(layout) {
1406                     if (coordinate->key_type != KEY_TYPE_NONE) {
1407                         if (context->get_tts_enabled()) {
1408                             const sclchar *targetstr = coordinate->hint_string[shift_index][button_context->multikeyIdx];
1409                             if (targetstr == NULL) {
1410                                 targetstr = coordinate->label[shift_index][0];
1411                             }
1412                             if (targetstr == NULL) {
1413                                 targetstr = coordinate->key_value[shift_index][button_context->multikeyIdx];
1414                             }
1415                             /*if(state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
1416                                 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ) {
1417                                     targetstr = coordinate->long_key_value;
1418                             }*/
1419                             const sclchar *sayit = cache->find_substituted_string(targetstr);
1420                             utils->play_tts(sayit);
1421                         }
1422                     }
1423                 }
1424
1425                 context->set_cur_highlighted_window(window);
1426                 context->set_cur_highlighted_key(key_index);
1427             }
1428         }
1429     }
1430
1431     return ret;
1432 }
1433 SCLKeyModifier
1434 CSCLController::get_drag_key_modifier(sclint deltax, sclint deltay, sclfloat dist, sclboolean check_farthest,
1435                                       scltouchdevice touch_id, sclbyte extra_option) {
1436     typedef struct {
1437         double lowerbound;
1438         double upperbound;
1439         SCLKeyModifier modifier;
1440     } DIRECTIONINFO;
1441
1442     CSCLContext *context = CSCLContext::get_instance();
1443     SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1444
1445     if (context) {
1446         double theta = atan2(deltay , (deltax ? deltax : 1)); /* Avoid divide by 0 exception */
1447         sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
1448         SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
1449         if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS ||
1450             extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1451             extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN) { /* 8 directions */
1452                 /* If the theta is below 0, the direction is upward since the y coordinate grows downward */
1453                 /* The below angle values are customized for MoAKey, need to provide customizing API */
1454                 DIRECTIONINFO info[] = {
1455                     {-8 * (M_PI / 8), -7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1456                     {-7 * (M_PI / 8), -5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_LEFT},
1457                     {-5 * (M_PI / 8), -2.7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP},
1458                     {-2.7 * (M_PI / 8), -1.5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_RIGHT},
1459                     {-1.5 * (M_PI / 8),  1 * (M_PI / 8), KEY_MODIFIER_DIRECTION_RIGHT},
1460                     { 1 * (M_PI / 8),  3 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_RIGHT},
1461                     { 3 * (M_PI / 8),  5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN},
1462                     { 5 * (M_PI / 8),  7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_LEFT},
1463                     { 7 * (M_PI / 8),  8 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1464                 };
1465                 for (size_t loop = 0; loop < sizeof(info) / sizeof(DIRECTIONINFO); loop++) {
1466                     if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1467                         key_modifier = info[loop].modifier;
1468                     }
1469                 }
1470         } else { /* 4 directions */
1471             /* If the state was dragging to one of 4 directions and the final release point is
1472             * far enough from inital press point, and the angle is in between out predefined angle value */
1473             if (extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE &&
1474                 cur_drag_state != SCL_DRAG_STATE_NONE && cur_drag_state != SCL_DRAG_STATE_INVALID &&
1475                 dist > SCL_DRAG_CURVE_RECOG_DIST &&
1476                 ratio > (1 / SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) &&
1477                 ratio < SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) {
1478                     if (cur_drag_state == SCL_DRAG_STATE_DOWN) {
1479                         if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_RIGHT;
1480                         else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_LEFT;
1481                     }
1482                     if (cur_drag_state == SCL_DRAG_STATE_UP) {
1483                         if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_RIGHT;
1484                         else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_LEFT;
1485                     }
1486                     if (cur_drag_state == SCL_DRAG_STATE_LEFT) {
1487                         if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_DOWN;
1488                         else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_UP;
1489                     }
1490                     if (cur_drag_state == SCL_DRAG_STATE_RIGHT) {
1491                         if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_DOWN;
1492                         else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_UP;
1493                     }
1494             } else {
1495                 DIRECTIONINFO info[] = {
1496                     {-4 * (M_PI / 4), -3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1497                     {-3 * (M_PI / 4), -1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_UP},
1498                     {-1 * (M_PI / 4),  1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_RIGHT},
1499                     { 1 * (M_PI / 4),  3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_DOWN},
1500                     { 3 * (M_PI / 4),  4 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1501                 };
1502                 for (size_t loop = 0; loop < sizeof(info) / sizeof(DIRECTIONINFO); loop++) {
1503                     if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1504                         key_modifier = info[loop].modifier;
1505                     }
1506                 }
1507             }
1508         }
1509
1510         if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1511             extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_LONG) {
1512                 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1513                     key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1514                         key_modifier = (SCLKeyModifier)(key_modifier + 8); // Add LONG attribute;
1515                 }
1516         }
1517         if (check_farthest || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
1518             if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1519                 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1520                     key_modifier = (SCLKeyModifier)(key_modifier + 16); // Add RETURN attribute;
1521             }
1522         }
1523     }
1524
1525     return key_modifier;
1526 }
1527
1528 sclboolean
1529 CSCLController::process_button_release_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1530                                              scltouchdevice touch_id, sclboolean actual_event)
1531 {
1532     SCL_DEBUG();
1533
1534     sclboolean ret = FALSE;
1535     sclboolean redraw = FALSE;
1536     sclboolean fireEvt = FALSE;
1537     SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1538
1539     static sclwindow lastFiredWin = SCLWINDOW_INVALID;
1540     static sclbyte lastFiredKey = NOT_USED;
1541
1542     CSCLUtils *utils = CSCLUtils::get_instance();
1543     CSCLFeedback *feedback = CSCLFeedback::get_instance();
1544     CSCLWindows *windows = CSCLWindows::get_instance();
1545     CSCLContext *context = CSCLContext::get_instance();
1546     CSCLActionState *state = CSCLActionState::get_instance();
1547     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1548     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1549
1550     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1551     PSclLayout sclres_layout = sclres_manager->get_layout_table();
1552     PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
1553     assert(sclres_layout != NULL);
1554     assert(sclres_input_mode_configure != NULL);
1555     SclButtonContext *button_context = NULL;
1556     const SclLayoutKeyCoordinate *coordinate = NULL;
1557
1558     if (cache) {
1559         button_context = cache->get_cur_button_context(window, key_index);
1560         coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1561     }
1562
1563     const SclLayoutKeyCoordinate *targetCoordinate = NULL;
1564
1565     if (utils && feedback && windows && context && state && handler && cache && button_context && coordinate) {
1566         scl8 savedInputMode = context->get_input_mode();
1567
1568         sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1569         scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1570
1571         if (actual_event) {
1572              if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1573                  /* When calling mouse_release, the seq order of current multitouch events will be changed,
1574                     so we put all the multitouch events into a vector and use them afterwards for releasing */
1575                  sclboolean finished = FALSE;
1576                  sclint loop = 0;
1577                  sclint multi_touch_context_num = context->get_multi_touch_context_num();
1578                  std::vector<SclUIEventDesc> multi_touch_events;
1579                  for(loop = 0;loop < multi_touch_context_num;loop++) {
1580                      SclUIEventDesc desc;
1581                      context->get_multi_touch_event(loop, &desc);
1582                      multi_touch_events.push_back(desc);
1583                  }
1584                  for(loop = 0;loop < multi_touch_context_num && !finished;loop++) {
1585                      SclUIEventDesc desc = multi_touch_events[loop];
1586                      if (desc.touch_id != touch_id) {
1587                          sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
1588                          scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
1589                          const SclLayoutKeyCoordinate *cur_pressed_coordinate =
1590                              cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
1591                          if (cur_pressed_coordinate) {
1592                              if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1593                                  mouse_release(context->get_cur_moving_window(desc.touch_id),
1594                                      context->get_cur_moving_point(desc.touch_id).x,
1595                                      context->get_cur_moving_point(desc.touch_id).y,
1596                                      desc.touch_id, FALSE);
1597                              }
1598                          }
1599                      } else {
1600                          finished = TRUE;
1601                      }
1602                  }
1603              }
1604          }
1605
1606         /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1607         sclint thresholdX = 0;
1608         sclint thresholdY = 0;
1609         if (context) {
1610             if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1611                 thresholdX = utils->get_scaled_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1612                 thresholdY = utils->get_scaled_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1613             }
1614         }
1615
1616         /* Check if the pressed button's type is directional button */
1617         if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1618             if (context) {
1619                 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1620                     ret = TRUE;
1621                     sclboolean check_farthest = FALSE;
1622
1623                     sclint startx = x;
1624                     sclint starty = y;
1625
1626                     /* If the buttontype is RELATIVE_DIRECTION, get the distance from last move point */
1627                     if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1628                         startx = context->get_prev_moving_point(touch_id).x;
1629                         starty = context->get_prev_moving_point(touch_id).y;
1630                     } else {
1631                         startx = context->get_cur_pressed_point(touch_id).x;
1632                         starty = context->get_cur_pressed_point(touch_id).y;
1633                     }
1634
1635                     sclint deltax = x - startx;
1636                     sclint deltay = y - starty;
1637
1638                     sclfloat dist = utils->get_distance(x, y, startx, starty);
1639                     sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
1640                     if (coordinate->is_side_button) {
1641                         direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
1642                     };
1643                     if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1644                         direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
1645                     }
1646                     if (context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN &&
1647                         coordinate->button_type != BUTTON_TYPE_RELATIVE_DIRECTION) {
1648                         if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
1649                             coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
1650                             coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
1651                                 deltax = context->get_farthest_move_point(touch_id).x - context->get_cur_pressed_point(touch_id).x;
1652                                 deltay = context->get_farthest_move_point(touch_id).y - context->get_cur_pressed_point(touch_id).y;
1653                                 dist = utils->get_distance(context->get_farthest_move_point(touch_id), context->get_cur_pressed_point(touch_id));
1654                                 check_farthest = TRUE;
1655                         }
1656                     }
1657                     if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1658                         key_modifier = context->get_cur_key_modifier(touch_id);
1659                     } else if (dist > direction_recog_dist) {
1660                         key_modifier = get_drag_key_modifier(deltax, deltay, dist, check_farthest, touch_id, coordinate->extra_option);
1661                     }
1662                 }
1663             }
1664         }
1665
1666         /* First check if this button is enabled in current active sublayout */
1667         sclboolean subLayoutMatch = TRUE;
1668         if (coordinate->sub_layout && context->get_cur_sublayout()) {
1669             if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1670                 subLayoutMatch = FALSE;
1671             }
1672         }
1673         /* Check if the event occured inside this button's rectangle */
1674         if ( x >= coordinate->x - coordinate->add_hit_left  - thresholdX &&
1675                 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX &&
1676                 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1677                 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1678                 subLayoutMatch ) {
1679             ret = TRUE;
1680         }
1681
1682         if (ret) {
1683             /* for feedback */
1684             feedback->button_released(window, key_index);
1685
1686             /* If this button's index is the same as the one initially pressed */
1687             if (pressed_window == window && pressed_key == key_index) {
1688                 fireEvt = TRUE;
1689                 targetCoordinate = coordinate;
1690             } else {
1691                 const SclLayoutKeyCoordinate *pressed_coordinate =
1692                     cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1693
1694                 if (pressed_coordinate) {
1695                     if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1696                         fireEvt = TRUE;
1697                         targetCoordinate = pressed_coordinate;
1698                     } else {
1699                         ret = FALSE;
1700                     }
1701                 }
1702             }
1703         }
1704
1705         /* In case of mode change buttons, event should be fired only when it was pressed lastly */
1706         if (fireEvt) {
1707             if (coordinate->key_type == KEY_TYPE_MODECHANGE) {
1708                 if (touch_id != context->get_last_touch_device_id()) {
1709                     fireEvt = FALSE;
1710                 }
1711             }
1712         }
1713
1714         /* If this key's modifier is LONGKEY, this means the event is already fired so skip this one */
1715         if (context->get_cur_key_modifier(touch_id) == KEY_MODIFIER_LONGKEY) {
1716             fireEvt = FALSE;
1717         }
1718
1719         /* Don't fire any events if we're in longkey state */
1720         if (state->get_cur_action_state() != ACTION_STATE_BASE_LONGKEY &&
1721                 state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
1722                 state->get_cur_action_state() != ACTION_STATE_POPUP_LONGKEY &&
1723                 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY) {
1724             /* An event occured? */
1725             if (fireEvt) {
1726                 if (targetCoordinate) {
1727                     SCLShiftState shift_index = context->get_shift_state();
1728                     if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1729                     if (context->get_caps_lock_mode()) {
1730                         shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1731                     }
1732
1733                     SclUIEventDesc key_event_desc;
1734                     key_event_desc.key_type = targetCoordinate->key_type;
1735
1736                     key_event_desc.event_type = EVENT_TYPE_RELEASE;
1737                     key_event_desc.touch_id = touch_id;
1738                     key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1739                     key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1740                     key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1741
1742                     key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1743
1744                     switch (targetCoordinate->button_type) {
1745                     case BUTTON_TYPE_NORMAL:
1746                     case BUTTON_TYPE_GRAB :
1747                     case BUTTON_TYPE_SELFISH:
1748                     case BUTTON_TYPE_DIRECTION :
1749                     case BUTTON_TYPE_RELATIVE_DIRECTION: {
1750                         SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1751                         if (pressed_context) {
1752                             if (!(targetCoordinate->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1753                                 key_event_desc.key_value = targetCoordinate->key_value[shift_index][0];
1754                                 key_event_desc.key_event = targetCoordinate->key_event[shift_index][0];
1755                                 key_event_desc.key_modifier = key_modifier;
1756                                 handler->on_event_key_clicked(key_event_desc);
1757                             }
1758                         }
1759                     }
1760                     break;
1761                     case BUTTON_TYPE_MULTITAP:
1762                     case BUTTON_TYPE_ROTATION: {
1763                         if (targetCoordinate->button_type == BUTTON_TYPE_MULTITAP) {
1764                             if (window == lastFiredWin && key_index == lastFiredKey) {
1765                                 key_modifier = KEY_MODIFIER_MULTITAP_REPEAT;
1766                             } else {
1767                                 key_modifier = KEY_MODIFIER_MULTITAP_START;
1768                             }
1769                         } else {
1770                             key_modifier = KEY_MODIFIER_NONE;
1771                         }
1772                         if (button_context->multikeyIdx < MAX_SIZE_OF_MULTITAP_CHAR) {
1773                             key_event_desc.key_value = coordinate->key_value[shift_index][button_context->multikeyIdx];
1774                             key_event_desc.key_event = coordinate->key_event[shift_index][button_context->multikeyIdx];
1775                             key_event_desc.key_modifier = key_modifier;
1776                             handler->on_event_key_clicked(key_event_desc);
1777                         }
1778                         /* Check if the multikey index is in valid range, and increase by one */
1779                         if (button_context->multikeyIdx >= MAX_SIZE_OF_MULTITAP_CHAR - 1) {
1780                             button_context->multikeyIdx = 0;
1781                         } else {
1782                             sclbyte orgindex = button_context->multikeyIdx;
1783                             button_context->multikeyIdx = 0;
1784                             if (targetCoordinate->key_value[shift_index][orgindex + 1]) {
1785                                 if (strlen(targetCoordinate->key_value[shift_index][orgindex + 1]) > 0) {
1786                                     button_context->multikeyIdx = orgindex + 1;
1787                                 }
1788                             }
1789                         }
1790                     }
1791                     break;
1792                     case BUTTON_TYPE_DRAG : {
1793                     }
1794                     break;
1795                     case BUTTON_TYPE_TOGGLE : {
1796                         SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1797                         if (pressed_context) {
1798                             if (!(targetCoordinate->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1799                                 key_event_desc.key_value = targetCoordinate->key_value[shift_index][0];
1800                                 key_event_desc.key_event = targetCoordinate->key_event[shift_index][0];
1801                                 if (pressed_context->toggled) {
1802                                     key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1803                                 } else {
1804                                     key_event_desc.key_modifier = KEY_MODIFIER_TOGGLED;
1805                                 }
1806                                 if (SCL_EVENT_PASS_ON == handler->on_event_key_clicked(key_event_desc)) {
1807                                     pressed_context->toggled = !(pressed_context->toggled);
1808                                 }
1809                             }
1810                         }
1811                     }
1812                     case BUTTON_TYPE_UIITEM: break;
1813                     case MAX_BUTTON_TYPE: break;
1814                     default: break;
1815
1816                     }
1817                     switch (coordinate->popup_type) {
1818                     case POPUP_TYPE_BTN_RELEASE_POPUP:
1819                     case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE: {
1820                         SCLDragState dragstate = context->get_cur_drag_state(touch_id);
1821                         sclint popup_input_mode = NOT_USED;
1822
1823                         SclNotiPopupOpeningDesc desc;
1824                         desc.ui_event_desc = &key_event_desc;
1825
1826                         if (scl_check_arrindex(dragstate, SCL_DRAG_STATE_MAX)) {
1827                             desc.input_mode = coordinate->popup_input_mode[dragstate];
1828                             popup_input_mode = sclres_manager->get_inputmode_id(coordinate->popup_input_mode[dragstate]);
1829                             /* FIXME */
1830                             //if (!scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP)) {
1831                             if (!scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE)) {
1832                                 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
1833                             }
1834                         }
1835                         if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
1836                             popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
1837                             SCLDisplayMode display_mode = context->get_display_mode();
1838                             /* FIXME */
1839                             //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
1840                             if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
1841                                 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
1842                                 sclshort popupLayoutId =
1843                                     sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
1844                                 if (popupLayoutId == NOT_USED){
1845                                     // deal with NOT_USED
1846                                     LOGD("popupLayoutID is not used.");
1847                                 }
1848                                 SclLayout *layout = NULL;
1849                                 /* FIXME */
1850                                 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
1851                                 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
1852                                     layout = &sclres_layout[popupLayoutId];
1853                                 }
1854                                 if (layout) {
1855                                     SclRectangle popupRect;
1856                                     SclRectangle baseWndRect;
1857                                     windows->get_window_rect(windows->get_base_window(), &baseWndRect);
1858                                     popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
1859                                     popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
1860
1861                                     //popupRect.width = utils->get_scale_x(layout->width);
1862                                     //popupRect.height= utils->get_scale_y(layout->height);
1863                                     popupRect.width = layout->width;
1864                                     popupRect.height= layout->height;
1865
1866                                     /* Let's make sure this popup window does not go beyond the screen area */
1867                                     sclint scr_w, scr_h;
1868                                     utils->get_screen_resolution(&scr_w, &scr_h);
1869
1870                                     if (popupRect.x + popupRect.width > scr_w) {
1871                                         popupRect.x = scr_w - popupRect.width;
1872                                     }
1873                                     if (popupRect.y + popupRect.height > scr_h) {
1874                                         popupRect.y = scr_h - popupRect.height;
1875                                     }
1876
1877                                     SclWindowOpener opener;
1878                                     opener.window = window;
1879                                     opener.key = key_index;
1880
1881                                     sclwindow popup_window = windows->open_popup(
1882                                         opener,
1883                                         popupRect,
1884                                         popup_input_mode,
1885                                         popupLayoutId,
1886                                         coordinate->popup_type,
1887                                         sclres_input_mode_configure[popup_input_mode].use_virtual_window,
1888                                         sclres_input_mode_configure[popup_input_mode].use_dim_window,
1889                                         coordinate->extract_offset_x,
1890                                         coordinate->extract_offset_y,
1891                                         sclres_input_mode_configure[popup_input_mode].timeout
1892                                         );
1893
1894                                     SclNotiPopupOpenedDesc opened_desc;
1895                                     opened_desc.ui_event_desc = &key_event_desc;
1896                                     opened_desc.input_mode = desc.input_mode;
1897                                     opened_desc.window = popup_window;
1898                                     handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
1899
1900                                     windows->hide_window(windows->get_magnifier_window());
1901                                     _play_tts_for_input_mode_name(popup_input_mode);
1902                                 }
1903                             }
1904                         }
1905                     }
1906                     break;
1907                     case POPUP_TYPE_AUTO_POPUP:
1908                     case POPUP_TYPE_BTN_PRESS_POPUP_DRAG:
1909                     case POPUP_TYPE_NONE:
1910                         /* Nothing to do in here */
1911                         break;
1912                     case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE: break;
1913                     case POPUP_TYPE_BTN_LONGPRESS_POPUP: break;
1914                     case MAX_POPUP_TYPE: break;
1915                     default: break;
1916                     }
1917                 }
1918
1919                 lastFiredWin = window;
1920                 lastFiredKey = key_index;
1921             }
1922         } else {
1923             if (targetCoordinate) {
1924                 SCLShiftState shift_index = context->get_shift_state();
1925                 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1926                 if (context->get_caps_lock_mode()) {
1927                     shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1928                 }
1929
1930                 SclUIEventDesc key_event_desc;
1931                 key_event_desc.key_type = targetCoordinate->key_type;
1932
1933                 key_event_desc.key_value = targetCoordinate->key_value[shift_index][button_context->multikeyIdx];
1934                 key_event_desc.key_event = targetCoordinate->key_event[shift_index][button_context->multikeyIdx];
1935                 key_event_desc.key_modifier = key_modifier;
1936
1937                 key_event_desc.event_type = EVENT_TYPE_RELEASE;
1938                 key_event_desc.touch_id = touch_id;
1939                 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1940                 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1941                 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1942
1943                 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1944
1945                 SCLEventReturnType evt = handler->on_event_drag_state_changed(key_event_desc);
1946             }
1947         }
1948
1949         /* If this button was pressed, initialize the button context regardless of event  */
1950         if (button_context->state == BUTTON_STATE_PRESSED) {
1951             /* But, if this button should be in pressed state in other multitouch id, do not initialize */
1952             sclboolean found = FALSE;
1953             for(sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1954                 SclUIEventDesc desc;
1955                 context->get_multi_touch_event(loop, &desc);
1956                 if (desc.touch_id != touch_id) {
1957                     MultiTouchContext *multi_touch_context = context->find_multi_touch_context(desc.touch_id);
1958                     if (multi_touch_context) {
1959                         if (multi_touch_context->cur_pressed_window == window &&
1960                             multi_touch_context->cur_pressed_key == key_index) {
1961                             found = TRUE;
1962                         }
1963                     }
1964                 }
1965             }
1966             if (!found) {
1967                 button_context->state = BUTTON_STATE_NORMAL;
1968                 redraw = TRUE;
1969             }
1970         }
1971
1972         /* If this button needs to be redrawn */
1973         if (redraw) {
1974 #ifdef DIRECTLY_DRAW_ON_EVENTS
1975             CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1976             if (builder) {
1977                 builder->draw_button(window, NULL, key_index, button_context->state, TRUE);
1978             }
1979 #else
1980             if (savedInputMode == context->get_input_mode()) {
1981                 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1982             }
1983
1984 #endif
1985         }
1986     }
1987
1988     return ret;
1989 }
1990
1991 sclboolean
1992 CSCLController::mouse_press(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
1993 {
1994     SCL_DEBUG();
1995     sclboolean ret = FALSE;
1996
1997     if (m_input_events_disabled) return FALSE;
1998
1999     //utils->log("Controller::mouse_press : %d %d\n", x, y);
2000
2001     /* Adjust x,y coordinate by touch offset */
2002     CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2003
2004     CSCLContext *context = CSCLContext::get_instance();
2005     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2006     CSCLActionState *state = CSCLActionState::get_instance();
2007     CSCLWindows *windows = CSCLWindows::get_instance();
2008     CSCLUtils *utils = CSCLUtils::get_instance();
2009
2010     sclint button_index = NOT_USED;
2011     SclWindowContext *window_context = NULL;
2012     if (windows) {
2013         const SclLayout *layout = cache->get_cur_layout(window);
2014         if (layout) {
2015             x += layout->mouse_manipulate_x;
2016             y += layout->mouse_manipulate_y;
2017         }
2018         window_context = windows->get_window_context(window);
2019         /* If the dim window is virtual and currently active, let's just skip this event */
2020         if (windows->is_base_window(window)) {
2021             SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2022             if (dim_window_context) {
2023                 LOGD ("dim window is_virtual:%d, hidden:%d", dim_window_context->is_virtual, dim_window_context->hidden);
2024                 if (/*dim_window_context->is_virtual &&*/ !(dim_window_context->hidden)) {
2025                     window = windows->get_dim_window();
2026                     window_context = dim_window_context;
2027                 }
2028             }
2029         }
2030     }
2031
2032     if (cache && state && windows && context && window_context) {
2033         SCLDisplayMode display_mode = context->get_display_mode();
2034         SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2035         PSclDefaultConfigure default_configure = NULL;
2036         if (sclres_manager) {
2037             default_configure = sclres_manager->get_default_configure();
2038         }
2039         if (default_configure) {
2040             adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2041         }
2042
2043         sclboolean isSubEvent = FALSE;
2044         if (context->get_multi_touch_context_num() > 0) {
2045             SclUIEventDesc desc;
2046             context->get_multi_touch_event(0, &desc);
2047             sclwindow pressed_window = context->get_cur_pressed_window(desc.touch_id);
2048             scl8 pressed_key = context->get_cur_pressed_key(desc.touch_id);
2049             SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2050             if (coordinate) {
2051                 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_GRAB_SUB_EVENTS) {
2052                     isSubEvent = TRUE;
2053                     utils->play_vibration(DEFAULT_VIBRATION_STYLE, DEFAULT_VIBRATION_DURATION);
2054                 }
2055             }
2056         }
2057         context->create_multi_touch_context(touch_id, isSubEvent);
2058         context->set_cur_pressed_window(touch_id, window);
2059         context->set_cur_pressed_point(touch_id, x, y);
2060         context->set_cur_pressed_time(touch_id);
2061         context->set_cur_moving_window(touch_id, window);
2062         context->set_cur_moving_point(touch_id, x, y);
2063         context->set_last_touch_device_id(touch_id);
2064         context->set_cur_drag_state(touch_id, SCL_DRAG_STATE_NONE);
2065         context->set_cur_key_modifier(touch_id, KEY_MODIFIER_NONE);
2066         for(sclint labelidx = 0;labelidx < MAX_SIZE_OF_LABEL_FOR_ONE;labelidx++) {
2067             context->set_custom_magnifier_label(touch_id, labelidx, NULL);
2068         }
2069
2070         /* If there is postponed update of button, update it now */
2071         CSCLEvents *events = CSCLEvents::get_instance();
2072         sclwindow last_win = context->get_last_pressed_window();
2073         scl8 last_key = context->get_last_pressed_key();
2074         if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2075             const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2076             if (coords) {
2077                 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2078             }
2079         }
2080         context->set_prev_pressed_window(touch_id, SCLWINDOW_INVALID);
2081         context->set_prev_pressed_key(touch_id, NOT_USED);
2082         context->set_prev_drag_state(touch_id, SCL_DRAG_STATE_NONE);
2083         context->set_prev_moving_point(touch_id, x, y);
2084
2085         /* Destroy key related timers */
2086         events->destroy_timer(SCL_TIMER_BUTTON_DELAY);
2087         events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2088         events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2089         events->destroy_timer(SCL_TIMER_LONGKEY);
2090         events->destroy_timer(SCL_TIMER_REPEATKEY);
2091
2092         /* Do what has to be done when mouse gets pressed */
2093         handle_engine_signal(SCL_SIG_MOUSE_PRESS, window);
2094
2095         /* Adjust event x and y positions as relative position to the virtual window */
2096         if (window_context) {
2097             /*if (window_context->isVirtual) {
2098                 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2099                 if (base_window_context) {
2100                     x -= (window_context->x - base_window_context->x);
2101                     y -= (window_context->y - base_window_context->y);
2102                 }
2103             }*/
2104         }
2105
2106         if (!isSubEvent) {
2107             sclboolean process_finished = FALSE;
2108             do {
2109                 /* Iterate all the buttons and inform the event */
2110                 sclboolean ended = FALSE;
2111                 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2112                     SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
2113                     const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2114                     if (button_context && coordinate) {
2115                         if (!(button_context->used)) {
2116                             ended = TRUE;
2117                         } else if (button_context->state != BUTTON_STATE_DISABLED &&
2118                                     coordinate->button_type != BUTTON_TYPE_UIITEM) {
2119                             if (process_button_pressed_event(window, x, y, loop, touch_id, actual_event)) {
2120                                 if (windows->is_base_window(window)) {
2121                                     state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2122                                 } else {
2123                                     state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2124                                 }
2125                                 button_index = loop;
2126                                 ret = TRUE;
2127                             }
2128                         }
2129                     }
2130                 }
2131
2132                 /* For covering a missing area about 1 pixel */
2133                 if (!ret) {
2134                     for (int loop = 0;loop < MAX_KEY;loop++) {
2135                         SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
2136                         const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2137                         if (button_context && coordinate) {
2138                             if (!(button_context->used)) {
2139                                 break;
2140                             } else if (button_context->state != BUTTON_STATE_DISABLED &&
2141                                         coordinate->button_type != BUTTON_TYPE_UIITEM) {
2142                                 if (process_button_pressed_event(window, x+1, y+1, loop, touch_id, actual_event)) {
2143                                     if (windows->is_base_window(window)) {
2144                                         state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2145                                     } else {
2146                                         state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2147                                     }
2148                                     button_index = loop;
2149                                     break;
2150                                 }
2151                             }
2152                         } else {
2153                             break;
2154                         }
2155                     }
2156                 }
2157
2158                 if (windows->is_base_window(window)) {
2159                     process_finished = TRUE;
2160                 } else if (button_index != NOT_USED) {
2161                     process_finished = TRUE;
2162                 } else {
2163                     const SclLayout *layout = cache->get_cur_layout(window);
2164                     if (layout) {
2165                         if (layout->use_sw_background && layout->bg_color.a == 0) {
2166                             /* If we could not find appropriate button in this popup window and the popup is transparent */
2167                             SclWindowContext *base_window_context =
2168                                 windows->get_window_context(windows->get_base_window());
2169                             if (base_window_context) {
2170                                 x = (window_context->geometry.x + x - base_window_context->geometry.x);
2171                                 y = (window_context->geometry.y + y - base_window_context->geometry.y);
2172                             }
2173                             window = windows->get_base_window();
2174                         } else {
2175                             process_finished = TRUE;
2176                         }
2177                     } else {
2178                         process_finished = TRUE;
2179                     }
2180                 }
2181             } while (!process_finished);
2182         }
2183
2184         sclwindow skip_window = window;
2185         if (ret && button_index != NOT_USED) {
2186             const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, button_index);
2187             if (coordinate) {
2188                 sclboolean dont_close_popup = FALSE;
2189                 if (coordinate->dont_close_popup) {
2190                     dont_close_popup = TRUE;
2191                 }
2192                 /* If the button's popup type is drag type, the opened popup could be the one opened by this press event */
2193                 if (coordinate->popup_type == POPUP_TYPE_BTN_PRESS_POPUP_DRAG) {
2194                     /* Check the opened popup was opened by this button */
2195                     sclwindow popupwin = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2196                     SclWindowContext *popup_window_context = windows->get_window_context(popupwin);
2197                     if (popup_window_context) {
2198                         SclWindowOpener opener = popup_window_context->opener;
2199                         if (opener.window == window && opener.key == button_index) {
2200                             dont_close_popup = TRUE;
2201                         }
2202                     }
2203                 }
2204                 if (dont_close_popup) {
2205                     skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2206                 }
2207             }
2208         }
2209         windows->close_all_popups(skip_window);
2210
2211         /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
2212         if (!(windows->is_base_window(window))) {
2213             if (window_context->timeout > 0) {
2214                 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2215                 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, window_context->timeout, 0, TRUE);
2216             }
2217         } else if (skip_window != window) { /* Or the pressed button has dont_close_popup property, reset POPUP_TIMEOUT timer */
2218             //SclWindowContext *skip_window_context = windows->get_window_context(skip_window, FALSE);
2219             SclWindowContext *skip_window_context = windows->get_window_context(skip_window);
2220             if (skip_window_context) {
2221                 if (skip_window_context->timeout > 0) {
2222                     events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2223                     events->create_timer(SCL_TIMER_POPUP_TIMEOUT, skip_window_context->timeout, 0, TRUE);
2224                 }
2225             }
2226         }
2227     }
2228
2229     return TRUE;
2230 }
2231
2232 sclboolean
2233 CSCLController::mouse_release(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2234 {
2235     SCL_DEBUG();
2236     sclboolean ret = FALSE;
2237
2238     //if (m_input_events_disabled) return FALSE;
2239
2240     //utils->log("Controller::mouse_release : %d %d\n", x, y);
2241     /* Adjust x,y coordinate by touch offset */
2242     CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2243
2244     CSCLContext *context = CSCLContext::get_instance();
2245     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2246     CSCLActionState *state = CSCLActionState::get_instance();
2247     CSCLWindows *windows = CSCLWindows::get_instance();
2248     CSCLUtils *utils = CSCLUtils::get_instance();
2249     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2250     CSCLEvents *events = CSCLEvents::get_instance();
2251
2252     sclint button_index = NOT_USED;
2253
2254     if (cache && state && windows && context && utils && handler && events &&
2255         context->find_multi_touch_context(touch_id)) {
2256         const SclLayout *layout = cache->get_cur_layout(window);
2257         if (layout) {
2258             x += layout->mouse_manipulate_x;
2259             y += layout->mouse_manipulate_y;
2260         }
2261
2262         sclwindow skip_window = SCLWINDOW_INVALID;
2263         SCLDisplayMode display_mode = context->get_display_mode();
2264
2265         SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2266         PSclDefaultConfigure default_configure = NULL;
2267         if (sclres_manager) {
2268             default_configure = sclres_manager->get_default_configure();
2269         }
2270         if (default_configure) {
2271             adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2272         }
2273
2274         context->set_cur_moving_window(touch_id, SCLWINDOW_INVALID);
2275
2276         sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2277         scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2278         //SclWindowContext *window_context = windows->get_window_context(window, TRUE);
2279         SclWindowContext *window_context = windows->get_window_context(window);
2280         /* Adjust event x and y positions as relative position to the virtual window */
2281         if (window_context) {
2282             /*if (window_context->isVirtual) {
2283                 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2284                 if (base_window_context) {
2285                     x -= (window_context->x - base_window_context->x);
2286                     y -= (window_context->y - base_window_context->y);
2287                 }
2288             }*/
2289             /* If the dim window is virtual and currently active, consider base window's event is occured in dim window */
2290             if (windows->is_base_window(window)) {
2291                 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2292                 if (dim_window_context) {
2293                     if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2294                         window = windows->get_dim_window();
2295                         window_context = dim_window_context;
2296                     }
2297                 }
2298             }
2299         }
2300
2301         /* Iterate all the buttons and inform the event */
2302         sclboolean ended = FALSE;
2303
2304         /* FIXME : The routine below seems to be removed, which was originally requested by Vodafone,
2305          * to slow down the speed of repeat key right before stopping repeatkey event */
2306         /* if (state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY) {
2307             if (m_key_repeated_num > 10) {
2308                 utils->sleep(100);
2309                 process_button_repeat_pressed_event(pressed_window, pressed_key, touch_id);
2310             }
2311             ended = TRUE;
2312         }*/
2313
2314         if (context->get_cur_pressed_window(touch_id) == window) {
2315             if (abs(context->get_cur_pressed_point(touch_id).x - x) > utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD) ||
2316                 abs(context->get_cur_pressed_point(touch_id).y - y) > utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD) )
2317             {
2318                 struct timeval t0 = context->get_cur_pressed_time(touch_id);
2319                 struct timeval t1;
2320                 gettimeofday(&t1, NULL);
2321                 float etime;
2322                 etime = ((t1.tv_sec * 1000000 + t1.tv_usec) - (t0.tv_sec * 1000000 + t0.tv_usec))/1000.0;
2323                 if (etime < SCL_FLICK_GESTURE_RECOG_TIME) {
2324                     SCLDragType drag_type = DRAG_NONE;
2325                     if (x > context->get_cur_pressed_point(touch_id).x + utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2326                         drag_type = DRAG_RIGHT;
2327                     }
2328                     if (x < context->get_cur_pressed_point(touch_id).x - utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2329                         drag_type = DRAG_LEFT;
2330                     }
2331                     if (y > context->get_cur_pressed_point(touch_id).y + utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2332                         drag_type = DRAG_DOWN;
2333                     }
2334                     if (y < context->get_cur_pressed_point(touch_id).y - utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2335                         drag_type = DRAG_UP;
2336                     }
2337                     SclNotiGestureFlickDesc desc;
2338                     SclUIEventDesc ui_event_desc;
2339                     ui_event_desc.key_value = NULL;
2340                     ui_event_desc.key_event = NOT_USED;
2341                     ui_event_desc.key_modifier = KEY_MODIFIER_NONE;
2342                     ui_event_desc.event_type = EVENT_TYPE_RELEASE;
2343                     ui_event_desc.touch_id = touch_id;
2344                     ui_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2345                     ui_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2346                     ui_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2347                     ui_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2348                     desc.ui_event_desc = &ui_event_desc;
2349                     desc.drag_type = drag_type;
2350                     if (handler->on_event_notification(SCL_UINOTITYPE_GESTURE_FLICK, &desc)) {
2351                         ended = TRUE;
2352                     }
2353                 }
2354             }
2355         }
2356
2357         /* FIXME : We should consider this kind of action in general manner, not only specific to autopopup */
2358         /* And also, this kind of implementation only selects button that was highlighted at least once. */
2359         // {
2360         //SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window, FALSE);
2361         SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window);
2362         if (pressed_window_context) {
2363             utils->log("PRESSED CTX : %p %d %d\n", pressed_window,
2364                 pressed_window_context->geometry.x, pressed_window_context->geometry.y);
2365             //if (pressedCtx->popuptype == POPUP_TYPE_AUTO_POPUP) {
2366             sclboolean grab_event = FALSE;
2367             const SclLayout *pressed_layout = cache->get_cur_layout(pressed_window);
2368             if (pressed_layout) {
2369                 if (pressed_layout->style == LAYOUT_STYLE_POPUP_GRAB) {
2370                     grab_event = TRUE;
2371                 }
2372                 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
2373                 if (grab_event) {
2374                     /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
2375                     sclboolean in_grab_area = TRUE;
2376                     if (pressed_layout->add_grab_left != NOT_USED &&
2377                         x < (pressed_window_context->geometry.x - pressed_layout->add_grab_left)) {
2378                         in_grab_area = FALSE;
2379                     }
2380                     if (pressed_layout->add_grab_right != NOT_USED &&
2381                         x > (pressed_window_context->geometry.x + pressed_window_context->geometry.width
2382                         + pressed_layout->add_grab_right)) {
2383                         in_grab_area = FALSE;
2384                     }
2385                     if (pressed_layout->add_grab_top != NOT_USED &&
2386                         y < (pressed_window_context->geometry.y - pressed_layout->add_grab_top)) {
2387                         in_grab_area = FALSE;
2388                     }
2389                     if (pressed_layout->add_grab_bottom != NOT_USED &&
2390                         y > (pressed_window_context->geometry.y + pressed_window_context->geometry.height
2391                         + pressed_layout->add_grab_bottom)) {
2392                         in_grab_area = FALSE;
2393                     }
2394                     if (in_grab_area) {
2395                         SclLayoutKeyCoordinate *coord = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2396                         if (coord) {
2397                             x = coord->x + (coord->width / 2);
2398                             y = coord->y + (coord->height / 2);
2399
2400                             for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2401                                 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, loop);
2402                                 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2403                                 if (button_context && coordinate) {
2404                                     if (!(button_context->used)) {
2405                                         ended = TRUE;
2406                                     } else if (button_context->state != BUTTON_STATE_DISABLED &&
2407                                                 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2408                                         if (process_button_release_event(pressed_window, x, y, loop, touch_id, actual_event)) {
2409                                             ret = TRUE;
2410                                             ended = TRUE;
2411                                         }
2412                                     }
2413                                 }
2414                             }
2415                         }
2416                     }
2417                 }
2418             }
2419         }
2420         // }
2421
2422         SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2423         const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2424
2425         /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2426         /* Ignore base window's release event if a popup window is opened */
2427         if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2428                 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2429                 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2430                 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2431                 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2432                 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2433             if (windows->is_base_window(window)) {
2434                 ended = TRUE;
2435                 /* In case of direction button, the release event on other window should be processed */
2436                 if (coordinate && window_context && pressed_window_context) {
2437                     if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2438                         sclint relx = (window_context->geometry.x + x) - pressed_window_context->geometry.x;
2439                         sclint rely = (window_context->geometry.y + y) - pressed_window_context->geometry.y;
2440                         if (process_button_release_event(pressed_window, relx, rely, pressed_key, touch_id, actual_event)) {
2441                             button_index = pressed_key;
2442                             ret = TRUE;
2443                             x = coordinate->x + (coordinate->width / 2);
2444                             y = coordinate->y + (coordinate->height / 2);
2445                             skip_window = pressed_window;
2446                         }
2447                     }
2448                 }
2449             }
2450         }
2451
2452         sclboolean process_finished = FALSE;
2453         do {
2454             MultiTouchContext *multi_touch_context = context->find_multi_touch_context(touch_id);
2455             if (multi_touch_context) {
2456                 if (!(multi_touch_context->is_sub_event)) {
2457                     /* First check if the event occured in pressed key's threshold area */
2458                     if (button_context && coordinate && !ended) {
2459                         if (button_context->used && button_context->state != BUTTON_STATE_DISABLED) {
2460                             if (process_button_release_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
2461                                 button_index = pressed_key;
2462                                 ret = TRUE;
2463                                 x = coordinate->x + (coordinate->width / 2);
2464                                 y = coordinate->y + (coordinate->height / 2);
2465                             }
2466                         }
2467                     }
2468                     for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2469                         SclButtonContext *cur_context = cache->get_cur_button_context(window, loop);
2470                         const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2471                         if (cur_context && cur_coordinate) {
2472                             if (!(cur_context->used)) {
2473                                 ended = TRUE;
2474                             } else if (cur_context->state != BUTTON_STATE_DISABLED &&
2475                                         cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
2476                                 if (window != pressed_window || loop != pressed_key) {
2477                                     if (process_button_release_event(window, x, y, loop, touch_id, actual_event)) {
2478                                         button_index = loop;
2479                                         ret = TRUE;
2480                                     }
2481                                 }
2482                             }
2483                         }
2484                     }
2485                 } else {
2486                     process_finished = TRUE;
2487
2488                     SclUIEventDesc key_event_desc;
2489                     key_event_desc.key_value = NULL;
2490                     key_event_desc.key_event = NOT_USED;
2491                     key_event_desc.key_modifier = KEY_MODIFIER_NONE;
2492                     key_event_desc.event_type = EVENT_TYPE_NONE;
2493                     key_event_desc.touch_id = touch_id;
2494                     key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2495                     key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2496                     key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2497
2498                     key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2499
2500                     handler->on_event_key_clicked(key_event_desc);
2501                 }
2502             }
2503
2504             /* For covering a missing area about 1 pixel */
2505             if (!ret) {
2506                 ended = FALSE;
2507
2508                 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2509                         state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2510                         state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2511                         state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2512                         state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2513                         state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2514                     if (windows->is_base_window(window)) {
2515                         ended = TRUE;
2516                     }
2517                 }
2518
2519                 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2520                     SclButtonContext *cur_context = cache->get_cur_button_context(window, loop);
2521                     if (cur_context && coordinate) {
2522                         if (!(cur_context->used)) {
2523                             ended = TRUE;
2524                             break;
2525                         } else if (cur_context->state != BUTTON_STATE_DISABLED &&
2526                                     coordinate->button_type != BUTTON_TYPE_UIITEM) {
2527                             if (process_button_release_event(window, x+1, y+1, loop, touch_id)) {
2528                                 button_index = loop;
2529                                 ret = TRUE;
2530                                 break;
2531                             }
2532                         }
2533                     }
2534                 }
2535             }
2536             if (windows->is_base_window(window)) {
2537                 process_finished = TRUE;
2538             } else if (button_index != NOT_USED) {
2539                 process_finished = TRUE;
2540             } else {
2541                 if (layout && layout->use_sw_background && layout->bg_color.a == 0) {
2542                     /* If we could not find appropriate button in this popup window and the popup is transparent */
2543                     SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2544                     if (base_window_context && window_context) {
2545                         x = (window_context->geometry.x + x - base_window_context->geometry.x);
2546                         y = (window_context->geometry.y + y - base_window_context->geometry.y);
2547                     }
2548                     window = windows->get_base_window();
2549                 } else {
2550                     process_finished = TRUE;
2551                 }
2552             }
2553         } while (!process_finished);
2554
2555         if (windows->is_base_window(window)) {
2556             state->set_cur_action_state(ACTION_STATE_BASE_INIT);
2557         } else {
2558             state->set_cur_action_state(ACTION_STATE_POPUP_INIT);
2559         }
2560
2561         /* Restore previously pressed button's context and redraw it */
2562         if (button_context && coordinate) {
2563             button_context->state = BUTTON_STATE_NORMAL;
2564             /* Commented below line to postpone some of the feedback for releasing */
2565             //windows->update_window(pressed_window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2566         }
2567
2568         /* If there is postponed update of button, update it now */
2569         sclwindow last_win = context->get_last_pressed_window();
2570         scl8 last_key = context->get_last_pressed_key();
2571         if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2572             const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2573             if (coords) {
2574                 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2575             }
2576         }
2577
2578         /* To postpone some of the feedback for releasing */
2579         context->set_last_pressed_key(context->get_cur_pressed_key(touch_id));
2580         context->set_last_pressed_window(context->get_cur_pressed_window(touch_id));
2581
2582         /* Do what has to be done when mouse gets released */
2583         sclboolean signaled = FALSE;
2584         if (coordinate) {
2585             switch (coordinate->popup_type) {
2586                 case POPUP_TYPE_BTN_RELEASE_POPUP:
2587                 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
2588                 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
2589                 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
2590                     {
2591                         /* Fix me : We should consider z-order */
2592                         skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2593                         handle_engine_signal(SCL_SIG_MOUSE_RELEASE, skip_window);
2594                         signaled = TRUE;
2595                     }
2596                     break;
2597                 case POPUP_TYPE_NONE: break;
2598                 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: break;
2599                 case POPUP_TYPE_AUTO_POPUP: break;
2600                 case MAX_POPUP_TYPE: break;
2601                 default: break;
2602             }
2603         }
2604         if (!signaled) {
2605             //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
2606             window_context = windows->get_window_context(window);
2607             if (window_context) {
2608                 if (window_context->popup_type == POPUP_TYPE_BTN_RELEASE_POPUP ||
2609                     window_context->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP) {
2610                     /* Don't close window if the clicked button is a child of ReleasePopup window */
2611                     skip_window = window;
2612                     handle_engine_signal(SCL_SIG_MOUSE_RELEASE, window);
2613                     signaled = TRUE;
2614                 }
2615             }
2616             if (!signaled) {
2617                 handle_engine_signal(SCL_SIG_MOUSE_RELEASE);
2618             }
2619         }
2620
2621         context->set_cur_pressed_key(touch_id, NOT_USED);
2622         context->set_cur_pressed_window(touch_id, SCLWINDOW_INVALID);
2623
2624         if (ret && button_index != NOT_USED) {
2625             const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, button_index);
2626             if (cur_coordinate) {
2627                 if (cur_coordinate->dont_close_popup) {
2628                     skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2629                 }
2630             }
2631         } else {
2632             if (pressed_window == windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP)) {
2633                 if (pressed_window_context) {
2634                     if (pressed_window_context->popup_type != POPUP_TYPE_BTN_RELEASE_POPUP_ONCE &&
2635                         pressed_window_context->popup_type != POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE &&
2636                         pressed_window_context->popup_type != POPUP_TYPE_AUTO_POPUP &&
2637                         pressed_window_context->popup_type != POPUP_TYPE_BTN_PRESS_POPUP_DRAG)
2638                     {
2639                         skip_window = pressed_window;
2640                     }
2641                 }
2642             }
2643         }
2644         windows->close_all_popups(skip_window);
2645
2646         /* Destroy key related timers */
2647         events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2648         events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2649         events->destroy_timer(SCL_TIMER_LONGKEY);
2650         events->destroy_timer(SCL_TIMER_REPEATKEY);
2651
2652         /* If there are more than 1 active multitouch ids, don't play button_delay trick */
2653         if (context->get_multi_touch_context_num() == 1) {
2654             /* To postpone some of the feedback for releasing */
2655             events->create_timer(SCL_TIMER_BUTTON_DELAY, m_button_delay_duration, 0);
2656         } else {
2657             last_win = context->get_last_pressed_window();
2658             last_key = context->get_last_pressed_key();
2659
2660             if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2661                 const SclLayoutKeyCoordinate* last_coordinate = cache->get_cur_layout_key_coordinate(last_win, last_key);
2662                 if (last_coordinate) {
2663                     windows->update_window(last_win,
2664                         last_coordinate->x, last_coordinate->y, last_coordinate->width, last_coordinate->height);
2665                 }
2666             }
2667
2668             windows->hide_window(windows->get_magnifier_window());
2669             context->set_last_pressed_window(SCLWINDOW_INVALID);
2670             context->set_last_pressed_key(NOT_USED);
2671         }
2672     }
2673
2674     if (context) {
2675         if (touch_id == context->get_last_touch_device_id()) {
2676             context->set_last_touch_device_id(SCLTOUCHDEVICE_INVALID);
2677         }
2678         context->destroy_multi_touch_context(touch_id);
2679     }
2680
2681     return ret;
2682 }
2683
2684 SCLDragState get_drag_state(sclint deltax, sclint deltay)
2685 {
2686     SCLDragState ret = SCL_DRAG_STATE_MAX;
2687
2688     sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
2689     /* If tan(theta) is smaller than our predefined value */
2690     if (ratio <= (1 / SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE)) {
2691         if (deltax > 0) {
2692             ret = SCL_DRAG_STATE_RIGHT;
2693         } else {
2694             ret = SCL_DRAG_STATE_LEFT;
2695         }
2696     } /* If tan(theta) is bigger than our predefined value */
2697     else if (ratio >= SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE) {
2698         if (deltay > 0) {
2699             ret = SCL_DRAG_STATE_DOWN;
2700         } else {
2701             ret = SCL_DRAG_STATE_UP;
2702         }
2703     } else {
2704         ret = SCL_DRAG_STATE_INVALID;
2705     }
2706
2707     return ret;
2708 }
2709
2710 sclboolean
2711 CSCLController::mouse_move(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2712 {
2713     SCL_DEBUG();
2714     sclboolean ret = FALSE;
2715
2716     if (m_input_events_disabled) return FALSE;
2717
2718     //utils->log("Controller::mouse_move : %d %d\n", x, y);
2719
2720     /* Adjust x,y coordinate by touch offset */
2721     CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2722
2723     CSCLContext *context = CSCLContext::get_instance();
2724     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2725     CSCLActionState *state = CSCLActionState::get_instance();
2726     CSCLWindows *windows = CSCLWindows::get_instance();
2727     CSCLEvents *events = CSCLEvents::get_instance();
2728     CSCLUtils *utils = CSCLUtils::get_instance();
2729     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2730     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2731     PSclModifierDecoration sclres_modifier_decoration = sclres_manager->get_modifier_decoration_table();
2732     assert(sclres_modifier_decoration != NULL);
2733
2734     if (cache && state && windows && context && utils && adjustment && sclres_manager) {
2735         const SclLayout *layout = cache->get_cur_layout(window);
2736         if (layout) {
2737             x += layout->mouse_manipulate_x;
2738             y += layout->mouse_manipulate_y;
2739         }
2740
2741         if (!(context->find_multi_touch_context(touch_id))) return FALSE;
2742
2743         PSclDefaultConfigure default_configure = sclres_manager->get_default_configure();
2744         if (default_configure) {
2745             SCLDisplayMode display_mode = context->get_display_mode();
2746             adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2747         }
2748
2749         //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
2750         SclWindowContext *window_context = windows->get_window_context(window);
2751         /* Adjust event x and y positions as relative position to the virtual window */
2752         if (window_context) {
2753             /*if (window_context->isVirtual) {
2754                 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2755                 if (base_window_context) {
2756                     x -= (window_context->x - base_window_context->x);
2757                     y -= (window_context->y - base_window_context->y);
2758                 }
2759             }*/
2760             /* If the dim window is virtual and currently active, let's just skip this event */
2761             if (windows->is_base_window(window)) {
2762                 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2763                 if (dim_window_context) {
2764                     if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2765                         return FALSE;
2766                     }
2767                 }
2768             }
2769             /* If the pressed event was occured in dim window, let's just skip this move event */
2770             if (context->get_last_pressed_window() == windows->get_dim_window()) {
2771                 return FALSE;
2772             }
2773         }
2774
2775         sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2776         scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2777         SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2778         const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2779
2780         /* If the multitouch type is SETTLE_PREVIOUS and is not the last touch device, let's ignore move events */
2781         if (coordinate) {
2782             if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
2783                 if (context->get_last_touch_device_id() != touch_id) {
2784                     return FALSE;
2785                 }
2786             }
2787         }
2788
2789         context->set_cur_moving_point(touch_id, x, y);
2790         context->set_cur_moving_window(touch_id, window);
2791
2792         /* If in longkey state, do not process, just return */
2793         if (state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
2794                 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
2795                 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
2796                 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY) {
2797             return FALSE;
2798         }
2799         /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2800         /* And if the event occured in popup window, don't come back to base window */
2801         if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2802                 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2803                 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2804                 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2805                 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2806                 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2807             if (windows->is_base_window(window)) {
2808                 return FALSE;
2809             }
2810         }
2811
2812         /* FIXME : Add a condition to skip this code if longkey timer is not active */
2813         /* If the mouse has moved out of threshold value of longkey keypress area, destroy longkey timer */
2814         if (m_long_key_cancel_distance > 0) {
2815             sclfloat dist = utils->get_distance(x, y,
2816                 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2817             if (m_long_key_cancel_distance < dist) {
2818                 events->destroy_timer(SCL_TIMER_LONGKEY);
2819             }
2820         }
2821
2822         if (windows->is_base_window(window)) {
2823             state->set_cur_action_state(ACTION_STATE_BASE_MOVING);
2824         } else {
2825             state->set_cur_action_state(ACTION_STATE_POPUP_MOVING);
2826         }
2827
2828         /* Iterate all the buttons and inform the event */
2829         sclboolean ended = FALSE;
2830
2831         /* Check farthest move point and update it */
2832         sclint originx = x;
2833         sclint originy = y;
2834         if (pressed_window != window) {
2835             //SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window, FALSE);
2836             SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window);
2837             if (window_context && pressed_window_context) {
2838                 originx = (window_context->geometry.x - pressed_window_context->geometry.x) + x;
2839                 originy = (window_context->geometry.y - pressed_window_context->geometry.y) + y;
2840             }
2841         }
2842         sclint startx = originx;
2843         sclint starty = originy;
2844
2845         /* Check if we should recognize drag curve */
2846         if (coordinate) {
2847             startx = context->get_cur_pressed_point(touch_id).x;
2848             starty = context->get_cur_pressed_point(touch_id).y;
2849             sclint deltax = originx - startx;
2850             sclint deltay = originy - starty;
2851             sclfloat approximate_dist = utils->get_approximate_distance(originx, originy, startx, starty);
2852
2853             sclboolean update_magnifier = FALSE;
2854             sclboolean drag_state_changed = FALSE;
2855             SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
2856             SCLDragState next_drag_state = SCL_DRAG_STATE_NONE;
2857             sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
2858             if (coordinate->is_side_button) {
2859                 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
2860             };
2861
2862             if (coordinate->button_type == BUTTON_TYPE_DIRECTION) {
2863                 /* Do not check farthest move point if current drag state is SCL_DRAG_STATE_RETURN */
2864                 if (context->get_cur_drag_state(touch_id) != SCL_DRAG_STATE_RETURN) {
2865                     if (approximate_dist > context->get_farthest_move_dist(touch_id)) {
2866                         context->set_farthest_move_point(touch_id, originx, originy);
2867                     }
2868                 }
2869
2870                 if (cur_drag_state == SCL_DRAG_STATE_RETURN) {
2871                     direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_RETURN;
2872                 } else if (cur_drag_state != SCL_DRAG_STATE_NONE) {
2873                     direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_OTHER;
2874                 }
2875                 if (approximate_dist > direction_recog_dist) {
2876                     next_drag_state = get_drag_state(deltax, deltay);
2877                     /* Disable longkey if dragging is recognized */
2878                     events->destroy_timer(SCL_TIMER_LONGKEY);
2879                 }
2880                 if (cur_drag_state != next_drag_state) {
2881                     drag_state_changed = TRUE;
2882                 }
2883                 if (cur_drag_state == SCL_DRAG_STATE_NONE) {
2884                     //if (nextDragState != SCL_DRAG_STATE_INVALID) {
2885                         cur_drag_state = next_drag_state;
2886                     //}
2887                 } else if (cur_drag_state != next_drag_state) {
2888                     if (next_drag_state == SCL_DRAG_STATE_NONE) {
2889                         cur_drag_state = SCL_DRAG_STATE_RETURN;
2890                     } else {
2891                         cur_drag_state = next_drag_state;
2892                     }
2893                 }
2894
2895                 context->set_cur_drag_state(touch_id, cur_drag_state);
2896                 sclboolean check_farthest = FALSE;
2897                 sclshort display = context->get_display_mode();
2898                 if (!scl_check_arrindex(display, DISPLAYMODE_MAX)) display = 0;
2899                 sclfloat dist = utils->get_distance(originx, originy,
2900                     context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2901                 if (dist < direction_recog_dist && context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
2902                     if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
2903                         coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
2904                         coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
2905                             deltax = context->get_farthest_move_point(touch_id).x -
2906                                 context->get_cur_pressed_point(touch_id).x;
2907                             deltay = context->get_farthest_move_point(touch_id).y -
2908                                 context->get_cur_pressed_point(touch_id).y;
2909                             dist = utils->get_distance(context->get_farthest_move_point(touch_id),
2910                                 context->get_cur_pressed_point(touch_id));
2911                             check_farthest = TRUE;
2912                     }
2913                 }
2914                 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist,
2915                     check_farthest, touch_id, coordinate->extra_option);
2916                 if (dist > direction_recog_dist) {
2917                     context->set_cur_key_modifier(touch_id, key_modifier);
2918                 }
2919                 /* If this button needs to be decorated when dragged */
2920                 if (coordinate->modifier_decorator) {
2921                     const SclModifierDecoration *decoration = NULL;
2922                     /* FIXME */
2923                     /*if (scl_check_arrindex(coordinate->modifier_decorator,
2924                         sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
2925                     scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
2926                     if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
2927                         if (sclres_modifier_decoration[decoration_id].valid) {
2928                             decoration = &(sclres_modifier_decoration[decoration_id]);
2929                         }
2930                     }
2931                     /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
2932                     if (decoration) {
2933                         if (decoration->bg_image_path[display][key_modifier]) {
2934                             windows->update_window(window,
2935                                 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2936                         }
2937                     }
2938                 }
2939                 if (dist > direction_recog_dist) {
2940                     SclUIEventDesc desc;
2941                     SCLShiftState shift_index = context->get_shift_state();
2942                     if (context->get_caps_lock_mode()) {
2943                         shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
2944                     }
2945                     desc.key_type = coordinate->key_type;
2946                     desc.key_value = coordinate->key_value[shift_index][0];
2947                     desc.key_event = coordinate->key_event[shift_index][0];
2948                     desc.event_type = EVENT_TYPE_MOVE;
2949                     desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2950                     desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2951                     desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2952                     desc.key_modifier = key_modifier;
2953
2954                     if (handler->on_event_drag_state_changed(desc) && context->get_magnifier_enabled()) {
2955                         update_magnifier = TRUE;
2956                     }
2957                 }
2958             } else if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2959                 if (cur_drag_state != SCL_DRAG_STATE_NONE) {
2960                     startx = context->get_prev_moving_point(touch_id).x;
2961                     starty = context->get_prev_moving_point(touch_id).y;
2962                     approximate_dist = utils->get_approximate_distance(originx, originy, startx, starty);
2963                     direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
2964                 }
2965                 deltax = originx - startx;
2966                 deltay = originy - starty;
2967                 //printf("DIST : %f, RECOG : %f\n", dist, direction_recog_dist);
2968                 if (approximate_dist > direction_recog_dist) {
2969                     next_drag_state = get_drag_state(deltax, deltay);
2970                     /* Disable longkey if dragging is recognized */
2971                     events->destroy_timer(SCL_TIMER_LONGKEY);
2972
2973                     if (cur_drag_state != next_drag_state) {
2974                         drag_state_changed = TRUE;
2975                     }
2976                     if (next_drag_state != SCL_DRAG_STATE_NONE) {
2977                         cur_drag_state = next_drag_state;
2978                     }
2979                     context->set_cur_drag_state(touch_id, cur_drag_state);
2980
2981                     startx = context->get_farthest_move_point(touch_id).x;
2982                     starty = context->get_farthest_move_point(touch_id).y;
2983                     deltax = originx - startx;
2984                     deltay = originy - starty;
2985                     sclfloat dist_farthest = utils->get_approximate_distance(originx, originy, startx, starty);
2986                     //printf("%d %d %d %d %f, %d %d\n", originx, originy, startx, starty, dist_farthest, cur_drag_state, next_drag_state);
2987                     /* Let's see how much we are away from the last farthest point */
2988                     sclfloat diffdir_recog_dist = SCL_DIRECTION_RELATIVE_DIFFDIR_RECOG_DIST * utils->get_smallest_scale_rate();
2989                     /* If we moved certain amount from the point where direction changed, process drag state change routine */
2990                     if (dist_farthest > diffdir_recog_dist || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_NONE) {
2991                         sclshort display = context->get_display_mode();
2992                         SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist_farthest,
2993                             FALSE, touch_id, coordinate->extra_option);
2994                         context->set_cur_key_modifier(touch_id, key_modifier);
2995                         /* If this button needs to be decorated when dragged */
2996                         if (coordinate->modifier_decorator) {
2997                             const SclModifierDecoration  *decoration = NULL;
2998                             /* FIXME */
2999                             /*if (scl_check_arrindex(coordinate->modifier_decorator,
3000                                 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
3001                             scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
3002                             if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
3003                                 if (sclres_modifier_decoration[decoration_id].valid) {
3004                                     decoration = &(sclres_modifier_decoration[decoration_id]);
3005                                 }
3006                             }
3007                             /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
3008                             if (decoration) {
3009                                 if (decoration->bg_image_path[display][key_modifier]) {
3010                                     windows->update_window(window,
3011                                         coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3012                                 }
3013                             }
3014                         }
3015
3016                         SclUIEventDesc desc;
3017                         SCLShiftState shift_index = context->get_shift_state();
3018                         if (context->get_caps_lock_mode()) {
3019                             shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
3020                         }
3021                         desc.key_type = coordinate->key_type;
3022                         desc.key_value = coordinate->key_value[shift_index][0];
3023                         desc.key_event = coordinate->key_event[shift_index][0];
3024                         desc.event_type = EVENT_TYPE_MOVE;
3025                         desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
3026                         desc.mouse_current_point = context->get_cur_moving_point(touch_id);
3027                         desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
3028                         desc.key_modifier = key_modifier;
3029
3030                         if (handler->on_event_drag_state_changed(desc) && context->get_magnifier_enabled()) {
3031                             update_magnifier = TRUE;
3032                         }
3033                     }
3034                     context->set_prev_moving_point(touch_id, originx, originy);
3035                 }
3036                 if (drag_state_changed) {
3037                     /* When the dragging direction changes, save the current position as farthest point for future comparison */
3038                     context->set_farthest_move_point(touch_id, originx, originy);
3039                     LOGD("SET_FARTHEST : %d %d %d", originx, originy, context->get_cur_drag_state(touch_id));
3040                 }
3041             }
3042
3043             if (update_magnifier) {
3044                 PSclMagnifierWndConfigure magnifier_configure = NULL;
3045                 if (sclres_manager) {
3046                     magnifier_configure = sclres_manager->get_magnifier_configure();
3047                 }
3048
3049                 const SclLayout *base_layout = cache->get_cur_layout(windows->get_base_window());
3050                 if (base_layout && magnifier_configure) {
3051                     SclPoint zoomwinpos = {0,0};
3052                     /* calculates x position to be set */
3053                     zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
3054                         (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
3055
3056                     /* calculates y position to be set */
3057                     sclint scnWidth, scnHeight;
3058                     utils->get_screen_resolution(&scnWidth, &scnHeight);
3059
3060                     zoomwinpos.y =  coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
3061                     if (window_context) {
3062                         zoomwinpos.x += window_context->geometry.x;
3063                         zoomwinpos.y += window_context->geometry.y;
3064                     }
3065                     if (zoomwinpos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
3066                         zoomwinpos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
3067                     }
3068                     if (zoomwinpos.x > scnWidth +
3069                         magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
3070                         magnifier_configure->width * utils->get_custom_scale_rate_x()) {
3071                         zoomwinpos.x = scnWidth +
3072                             magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
3073                             magnifier_configure->width * utils->get_custom_scale_rate_x();
3074                     }
3075                     zoomwinpos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
3076
3077                     zoomwinpos.x += coordinate->magnifier_offset_x;
3078                     zoomwinpos.y += coordinate->magnifier_offset_y;
3079                     windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y);
3080                     windows->show_window(windows->get_magnifier_window(), 0);
3081                 }
3082             }
3083         }
3084
3085         sclboolean grab_event = FALSE;
3086         if (layout) {
3087             if (layout->style == LAYOUT_STYLE_POPUP_GRAB) {
3088                 grab_event = TRUE;
3089             }
3090             /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
3091             if (grab_event && window_context) {
3092                 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
3093                 sclboolean in_grab_area = TRUE;
3094                 if (layout->add_grab_left != NOT_USED && x < -(layout->add_grab_left)) {
3095                     in_grab_area = FALSE;
3096                 }
3097                 if (layout->add_grab_right != NOT_USED && x >
3098                     (window_context->geometry.width + layout->add_grab_right)) {
3099                     in_grab_area = FALSE;
3100                 }
3101                 if (layout->add_grab_top != NOT_USED && y < -(layout->add_grab_top)) {
3102                     in_grab_area = FALSE;
3103                 }
3104                 if (layout->add_grab_bottom != NOT_USED && y >
3105                     (window_context->geometry.height + layout->add_grab_bottom)) {
3106                     in_grab_area = FALSE;
3107                 }
3108                 if (in_grab_area) {
3109                     float min_dist = (float)((unsigned int)(-1));
3110                     int min_dist_index = NOT_USED;
3111                     for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
3112                         button_context = cache->get_cur_button_context(window, loop);
3113                         const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3114                         if (button_context && cur_coordinate) {
3115                             if (!(button_context->used)) {
3116                                 ended = TRUE;
3117                             } else if (button_context->state != BUTTON_STATE_DISABLED &&
3118                                 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
3119                                 float dist = utils->get_approximate_distance(x, y,
3120                                         cur_coordinate->x + (cur_coordinate->width / 2),
3121                                         cur_coordinate->y + (cur_coordinate->height / 2));
3122                                 if (dist < min_dist) {
3123                                     min_dist_index = loop;
3124                                     min_dist = dist;
3125                                 }
3126                             }
3127                         }
3128                     }
3129                     /* When we found the nearest button, generate this event on the button */
3130                     if (min_dist_index != NOT_USED) {
3131                         const SclLayoutKeyCoordinate *min_coordinate =
3132                             cache->get_cur_layout_key_coordinate(window, min_dist_index);
3133                         if (min_coordinate) {
3134                             x = min_coordinate->x + (min_coordinate->width / 2);
3135                             y = min_coordinate->y + (min_coordinate->height / 2);
3136                             if (process_button_move_event(window, x, y, min_dist_index, touch_id, actual_event)) {
3137                                 ret = TRUE;
3138                             }
3139                         }
3140                     }
3141                 }
3142             } else {
3143                 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(touch_id);
3144                 if (multi_touch_context) {
3145                     sclint button_index = NOT_USED;
3146                     if (!(multi_touch_context->is_sub_event)) {
3147                         sclboolean process_finished = FALSE;
3148                         do {
3149                             /* First check if the event occured in pressed key's threshold area */
3150                             if (button_context && coordinate) {
3151                                 if (pressed_window == window) { // Check only when the window is the one initally pressed
3152                                     if (button_context->used && button_context->state != BUTTON_STATE_DISABLED) {
3153                                         if (process_button_move_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
3154                                             ret = TRUE;
3155                                             x = coordinate->x + (coordinate->width / 2);
3156                                             y = coordinate->y + (coordinate->height / 2);
3157                                             button_index = pressed_key;
3158                                         }
3159                                     }
3160                                 }
3161                             }
3162                             for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
3163                                 button_context = cache->get_cur_button_context(window, loop);
3164                                 const SclLayoutKeyCoordinate *cur_coordinate =
3165                                     cache->get_cur_layout_key_coordinate(window, loop);
3166                                 if (button_context && cur_coordinate) {
3167                                     if (!(button_context->used)) {
3168                                         ended = TRUE;
3169                                     } else if (button_context->state != BUTTON_STATE_DISABLED &&
3170                                                 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
3171                                         if (window != pressed_window || loop != pressed_key) {
3172                                             if (process_button_move_event(window, x, y, loop, touch_id, actual_event)) {
3173                                                 ret = TRUE;
3174                                                 button_index = loop;
3175                                             }
3176                                         }
3177                                     }
3178                                 }
3179                             }
3180
3181                             if (windows->is_base_window(window)) {
3182                                 process_finished = TRUE;
3183                             } else if (button_index != NOT_USED) {
3184                                 process_finished = TRUE;
3185                             } else {
3186                                 const SclLayout *cur_layout = cache->get_cur_layout(window);
3187                                 if (cur_layout && cur_layout->use_sw_background && cur_layout->bg_color.a == 0) {
3188                                     /* If we could not find appropriate button in this popup window and the popup is transparent */
3189                                     SclWindowContext *base_window_context =
3190                                         windows->get_window_context(windows->get_base_window());
3191                                     if (base_window_context && window_context) {
3192                                         x = (window_context->geometry.x + x - base_window_context->geometry.x);
3193                                         y = (window_context->geometry.y + y - base_window_context->geometry.y);
3194                                     }
3195                                     window = windows->get_base_window();
3196                                 } else {
3197                                     process_finished = TRUE;
3198                                 }
3199                             }
3200                         } while (!process_finished);
3201                     }
3202                 }
3203             }
3204         }
3205     }
3206
3207     return ret;
3208 }
3209
3210 sclboolean
3211 CSCLController::mouse_over(sclwindow window, sclint x, sclint y)
3212 {
3213     SCL_DEBUG();
3214     sclboolean ret = FALSE;
3215
3216     if(m_input_events_disabled)
3217         return FALSE;
3218
3219     /* Adjust x,y coordinate by touch offset */
3220     CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
3221     /* Iterate all the buttons and inform the event */
3222
3223     CSCLContext *context = CSCLContext::get_instance();
3224     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3225     CSCLActionState *state = CSCLActionState::get_instance();
3226     CSCLWindows *windows = CSCLWindows::get_instance();
3227     CSCLUtils *utils = CSCLUtils::get_instance();
3228     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3229
3230     if (cache && state && windows && context && utils && adjustment && sclres_manager) {
3231         const SclLayout *layout = cache->get_cur_layout(window);
3232         if (layout) {
3233             x += layout->mouse_manipulate_x;
3234             y += layout->mouse_manipulate_y;
3235         }
3236
3237         SCLDisplayMode cur_display_mode = context->get_display_mode();
3238
3239         const SclDefaultConfigure *default_configure = sclres_manager->get_default_configure();
3240         if (default_configure) {
3241             adjustment->apply_touch_offset(default_configure->touch_offset_level[cur_display_mode], &x, &y);
3242         }
3243
3244         /* Iterate all the buttons and inform the event */
3245         sclboolean ended = FALSE;
3246
3247         for (int loop = 0; loop < MAX_KEY && !ended && !ret; loop++) {
3248             SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
3249             const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3250             if (button_context && coordinate) {
3251                 if (!(button_context->used)) {
3252                     ended = TRUE;
3253                 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3254                             coordinate->button_type != BUTTON_TYPE_UIITEM) {
3255                     if (process_button_over_event(window, x, y, loop)) {
3256                         ret = TRUE;
3257                     }
3258                 }
3259             }
3260         }
3261     }
3262
3263     return ret;
3264 }
3265
3266
3267 /**
3268  * Processes a timer event
3269  * If return FALSE, the current timer will be stop
3270  * ID : SCL_LOWORD(data)
3271  * value : SCL_HIWORD(data)
3272  */
3273 sclboolean
3274 CSCLController::timer_event(const scl32 data)
3275 {
3276     SCL_DEBUG();
3277     CSCLWindows *windows = CSCLWindows::get_instance();
3278     CSCLContext *context = CSCLContext::get_instance();
3279     CSCLEvents* events = CSCLEvents::get_instance();
3280     CSCLActionState *state = CSCLActionState::get_instance();
3281     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3282     CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3283
3284     scl16 id = SCL_LOWORD(data); /* Timer ID */
3285     scl16 value = SCL_HIWORD(data); /* event unique ID */
3286
3287     if (!windows || !context || !events || !state || !cache || !handler)
3288         return FALSE;
3289
3290     switch (id) {
3291     case SCL_TIMER_AUTOPOPUP: {
3292         /* Checks whether my event id is availble */
3293         if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3294                 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3295                 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3296                 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3297                 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3298                 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3299                 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3300                 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3301                 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3302                 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3303                 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3304            ) {
3305             /* Ignores if the event id is different */
3306             events->destroy_timer(id);
3307             return FALSE;
3308         }
3309
3310         SclRectangle rect = {0,0,0,0};
3311         sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3312         sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3313
3314         if (configure_autopopup_window(window, key_index, &rect)) {
3315             /* Let's change out pressed button's state back to normal */
3316             SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
3317             const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3318
3319             if (button_context) {
3320                 if (button_context->state == BUTTON_STATE_PRESSED) {
3321                     button_context->state = BUTTON_STATE_NORMAL;
3322                     if (coordinate) {
3323                         windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3324                     }
3325                 }
3326             }
3327             /* Hide magnifier window when opening autopopup window */
3328             windows->hide_window(windows->get_magnifier_window());
3329
3330             sclwindow popup_window = SCLWINDOW_INVALID;
3331
3332             SclNotiPopupOpeningDesc desc;
3333             desc.ui_event_desc = NULL;
3334             desc.input_mode = SCL_LAYOUT_AUTOPOPUP_NAME;
3335             if (SCL_EVENT_PASS_ON ==
3336                 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
3337                     /* Currently, window does not support virtual window */
3338                     SclWindowOpener opener;
3339                     opener.window = window;
3340                     opener.key = key_index;
3341
3342                     popup_window = windows->open_popup(
3343                         opener,
3344                         rect,
3345                         NOT_USED,
3346                         SCL_LAYOUT_AUTOPOPUP, POPUP_TYPE_AUTO_POPUP,
3347                         FALSE,
3348                         FALSE
3349                         );
3350
3351                     SclNotiPopupOpenedDesc opened_desc;
3352                     opened_desc.ui_event_desc = NULL;
3353                     opened_desc.input_mode = desc.input_mode;
3354                     opened_desc.window = popup_window;
3355                     handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
3356             }
3357
3358             windows->hide_window(windows->get_magnifier_window());
3359             _play_tts_for_layout_autopopup_name();
3360
3361             sclwindow moving_window = context->get_cur_moving_window(context->get_last_touch_device_id());
3362             SclPoint moving_point = context->get_cur_moving_point(context->get_last_touch_device_id());
3363             SclWindowContext *moving_window_context = windows->get_window_context(moving_window);
3364             SclWindowContext *popup_window_context = windows->get_window_context(popup_window);
3365             if (moving_window_context && popup_window_context) {
3366                 moving_point.x = (moving_window_context->geometry.x - popup_window_context->geometry.x) + moving_point.x;
3367                 moving_point.y = (moving_window_context->geometry.y - popup_window_context->geometry.y) + moving_point.y;
3368             }
3369             //printf("AUTOPOPUP : %d %d\n", moving_point.x, moving_point.y);
3370
3371             if (coordinate) {
3372                 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3373             }
3374         }
3375         events->destroy_timer(id);
3376
3377         return FALSE;
3378     }
3379     break;
3380
3381     case SCL_TIMER_LONGKEY: {
3382         /* Checks whether my event id is availble */
3383         if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3384                 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3385                 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3386                 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3387                 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3388                 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3389                 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3390                 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3391                 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3392                 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3393                 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3394            ) {
3395             /* Ignores if the event id is different */
3396             events->destroy_timer(id);
3397             return FALSE;
3398         }
3399         /* Ignores if the event id is different */
3400         sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3401         sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3402         if (process_button_long_pressed_event(window, key_index, context->get_last_touch_device_id())) {
3403             /* The button processed long key event, now enter longkey mode not to fire any events before releasing */
3404             handle_engine_signal(SCL_SIG_MOUSE_LONG_PRESS, window);
3405             windows->update_window(windows->get_magnifier_window());
3406 /*
3407             SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
3408             if (button_context->state == BUTTON_STATE_PRESSED) {
3409                 button_context->state = BUTTON_STATE_NORMAL;
3410                 CSCLWindows *windows = CSCLWindows::get_instance();
3411                 if (windows) {
3412                     const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3413                     windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3414                 }
3415             }
3416             context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3417             context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3418 */
3419         } else {
3420             /* Start the repeat key timer for NORMAL or GRAB buttons if longkey is not supported */
3421             const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3422
3423             if (coordinate) {
3424                 /* This is for enabling backspace key in search layout*/
3425                 //if (coordinate->use_repeat_key) {
3426                 if (coordinate->use_repeat_key
3427                         || coordinate->key_event[0][0] == MVK_BackSpace) {
3428                     if (coordinate->button_type == BUTTON_TYPE_NORMAL ||
3429                             coordinate->button_type == BUTTON_TYPE_GRAB ||
3430                             coordinate->button_type == BUTTON_TYPE_SELFISH ||
3431                             coordinate->button_type == BUTTON_TYPE_DIRECTION ||
3432                             coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
3433                         m_key_repeated_num = 0;
3434                         events->create_timer(SCL_TIMER_REPEATKEY, m_repeat_key_duration, value);
3435                         if (windows->is_base_window(window)) {
3436                             state->set_cur_action_state(ACTION_STATE_BASE_REPEATKEY);
3437                         } else {
3438                             state->set_cur_action_state(ACTION_STATE_POPUP_REPEATKEY);
3439                         }
3440                     }
3441                 }
3442             }
3443         }
3444         events->destroy_timer(id);
3445         return FALSE;
3446     }
3447     break;
3448
3449     case SCL_TIMER_REPEATKEY: {
3450         /* Checks whether my event id is availble */
3451         if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3452                 (state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
3453                  state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY)
3454            ) {
3455             /* Ignores if the event id is different */
3456             events->destroy_timer(id);
3457             return FALSE;
3458         }
3459         sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3460         sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3461         scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
3462         if (interval < SCL_REPEATKEY_MIN_DURATION) {
3463             interval = SCL_REPEATKEY_MIN_DURATION;
3464         }
3465         process_button_repeat_pressed_event(window, key_index, context->get_last_touch_device_id());
3466         events->destroy_timer(id);
3467         events->create_timer(SCL_TIMER_REPEATKEY, interval, value);
3468         m_key_repeated_num++;
3469         return FALSE;
3470     }
3471     break;
3472     case SCL_TIMER_BUTTON_DELAY: {
3473         /* If there is postponed update of button, update it now */
3474         sclwindow last_window = context->get_last_pressed_window();
3475         scl8 last_key = context->get_last_pressed_key();
3476
3477         if (last_window != SCLWINDOW_INVALID && last_key != NOT_USED) {
3478             const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_window, last_key);
3479             if (coords) {
3480                 windows->update_window(last_window, coords->x, coords->y, coords->width, coords->height);
3481             }
3482         }
3483
3484         windows->hide_window(windows->get_magnifier_window());
3485         context->set_last_pressed_window(SCLWINDOW_INVALID);
3486         context->set_last_pressed_key(NOT_USED);
3487         events->destroy_timer(id);
3488         return FALSE;
3489     }
3490     break;
3491     case SCL_TIMER_POPUP_TIMEOUT: {
3492         SclNotiPopupClosingDesc desc;
3493         desc.ui_event_desc = NULL;
3494         desc.input_mode = NULL;
3495         desc.timed_out = TRUE;
3496
3497         SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3498         if (sclres_manager) {
3499             const PSclInputModeConfigure sclres_input_mode_configure =
3500                 sclres_manager->get_input_mode_configure_table();
3501             sclwindow window = windows->get_nth_popup_window(SCL_WINDOW_Z_TOP);
3502             SclWindowContext *window_context = windows->get_window_context(window);
3503             if (window_context && sclres_input_mode_configure) {
3504                 if (scl_check_arrindex(window_context->inputmode, MAX_SCL_INPUT_MODE)) {
3505                     desc.input_mode = sclres_input_mode_configure[window_context->inputmode].name;
3506                 }
3507             }
3508         }
3509
3510         if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_CLOSING, &desc)) {
3511             windows->close_all_popups();
3512
3513             SclNotiPopupClosedDesc closed_desc;
3514             closed_desc.ui_event_desc = desc.ui_event_desc;
3515             closed_desc.input_mode = desc.input_mode;
3516             closed_desc.timed_out = desc.timed_out;
3517             handler->on_event_notification(SCL_UINOTITYPE_POPUP_CLOSED, &desc);
3518         }
3519         events->destroy_timer(id);
3520         return FALSE;
3521     }
3522     break;
3523     case SCL_TIMER_AUTOTEST: {
3524         sclint rnd = rand() % 100;
3525
3526         if (cache->get_cur_layout(windows->get_base_window()) == NULL) {
3527             return FALSE;
3528         }
3529         sclint x = (rand() % (cache->get_cur_layout(windows->get_base_window())->width));
3530         sclint y = (rand() % (cache->get_cur_layout(windows->get_base_window())->height));
3531
3532         if (rnd < 80) {
3533             events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3534             events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3535         } else if (rnd < 90) {
3536             events->generate_mouse_event(SCL_MOUSE_EVENT_MOVE, x, y);
3537         } else if (rnd < 95) {
3538             events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3539         } else {
3540             events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3541         }
3542
3543         m_debug_variable++;
3544         if (m_debug_variable < SCL_AUTOTEST_NUM) events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INTERVAL, 0, FALSE);
3545         else m_debug_mode = DEBUGMODE_DISABLED;
3546         return FALSE;
3547     }
3548     break;
3549     case SCL_TIMER_ANIMATION: {
3550         CSCLAnimator *animator = CSCLAnimator::get_instance();
3551         if (animator) {
3552             return animator->animator_timer();
3553         }
3554         return TRUE;
3555     }
3556
3557     default: {
3558         events->destroy_timer(id);
3559     }
3560     break;
3561     }
3562
3563     return TRUE;
3564 }
3565
3566 /* Handles signals to manage contexts mainly focusing on resetting variables and cleaning up states */
3567 void CSCLController::handle_engine_signal( SclInternalSignal signal, sclwindow targetWindow )
3568 {
3569     SCL_DEBUG();
3570
3571     enum SIGACTIONS {
3572         SIGACTION_RESIZE_RESOURCES,
3573         SIGACTION_DESTROY_TIMERS,
3574         SIGACTION_CLEAR_PRIVATEKEYS,
3575         SIGACTION_RECOMPUTE_LAYOUT,
3576         SIGACTION_FREE_IMAGES,
3577         SIGACTION_CLOSE_POPUP,
3578         SIGACTION_CLOSE_MAGNIFIER,
3579         SIGACTION_UNSET_SHIFT,
3580         SIGACTION_UNPRESS_KEYS,
3581         SIGACTION_INIT_DISPLAY,
3582         SIGACTION_INIT_INPUTMODE,
3583
3584         SIGACTION_MAXNUM
3585     };
3586     const sclboolean SIGNAL_TABLE[SIGACTION_MAXNUM][SCL_SIG_MAXNUM] = {
3587         //      START,  SHOW,   HIDE,   INPCHNG,        DISPCHNG,       POPUPSHOW,      POPUPHIDE,      MOUSEPRES,      M-LONGPRES,     MOUSEREL,       KEYEVT, FOCUSCHNG
3588         // SIGACTION_RESIZE_RESOURCES
3589         {       TRUE,   0,              0,              0,                      0,                      0,                      0,                      0,                      0,                      0,                      0,              0               },
3590         // SIGACTION_DESTROY_TIMERS
3591         {       TRUE,   TRUE,   TRUE,   TRUE,           TRUE,           0,                      0,                      0,                      0,                      0,                      0,              TRUE    },
3592         // SIGACTION_CLEAR_PRIVATEKEYS
3593         {       TRUE,   0,              0,              0,                      0,                      0,                      0,                      0,                      0,                      0,                      0,              TRUE    },
3594         // SIGACTION_RECOMPUTE_LAYOUT
3595         {       0,              TRUE,   0,              TRUE,           TRUE,           TRUE,           0,                      0,                      0,                      0,                      0,              TRUE    },
3596         // SIGACTION_FREE_IMAGES
3597         {       TRUE,   0,              TRUE,   TRUE,           TRUE,           0,                      0,                      0,                      0,                      0,                      0,              0               },
3598         // SIGACTION_CLOSE_POPUP
3599         {       TRUE,   TRUE,   TRUE,   TRUE,           TRUE,           0,                      0,                      0,                      0,                      0,                      0,              TRUE    },
3600         // SIGACTION_CLOSE_MAGNIFIER
3601         {       TRUE,   TRUE,   TRUE,   TRUE,           TRUE,           0,                      0,                      0,                      0,                      0,                      0,              TRUE    },
3602         // SIGACTION_UNSET_SHIFT
3603         {       TRUE,   0       ,       0       ,       TRUE,           0,                      0,                      0,                      0,                      0,                      0,                      0,              TRUE    },
3604         // SIGACTION_UNPRESS_KEYS
3605         {       TRUE,   TRUE,   TRUE,   TRUE,           TRUE,           0,                      0,                      0,                      0,                      0,                      0,              TRUE    },
3606         // SIGACTION_INIT_DISPLAY
3607         {       TRUE,   0,              0,              0,                      0,                      0,                      0,                      0,                      0,                      0,                      0,              0               },
3608         // SIGACTION_INIT_INPUTMODE
3609         {       TRUE,   0,              0,              0,                      0,                      0,                      0,                      0,                      0,                      0,                      0,              TRUE    },
3610     };
3611
3612     scl_assert_return(signal >= 0 && signal < SCL_SIG_MAXNUM);
3613
3614     CSCLEvents* events = CSCLEvents::get_instance();
3615     CSCLWindows *windows = CSCLWindows::get_instance();
3616     CSCLContext *context = CSCLContext::get_instance();
3617     CSCLImageProxy *proxy = CSCLImageProxy::get_instance();
3618     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3619
3620     switch (signal) {
3621         case SCL_SIG_SHOW:
3622             {
3623                 context->set_hidden_state(FALSE);
3624             }
3625             break;
3626         case SCL_SIG_HIDE:
3627             {
3628                 context->set_hidden_state(TRUE);
3629                 windows->close_all_popups();
3630             }
3631             break;
3632         case SCL_SIG_START:
3633         case SCL_SIG_INPMODE_CHANGE:
3634         case SCL_SIG_DISP_CHANGE:
3635         case SCL_SIG_POPUP_SHOW:
3636         case SCL_SIG_POPUP_HIDE:
3637         case SCL_SIG_MOUSE_PRESS:
3638         case SCL_SIG_MOUSE_LONG_PRESS:
3639         case SCL_SIG_MOUSE_RELEASE:
3640         case SCL_SIG_KEYEVENT:
3641         default:
3642             break;
3643     }
3644
3645     int loop = 0;
3646     for (loop = 0;loop < SIGACTION_MAXNUM;loop++) {
3647         if (SIGNAL_TABLE[loop][signal] == TRUE) {
3648             switch (loop) {
3649             case SIGACTION_DESTROY_TIMERS:
3650                 events->destroy_all_timer();
3651                 break;
3652             case SIGACTION_RECOMPUTE_LAYOUT: {
3653                 if (targetWindow != SCLWINDOW_INVALID) {
3654                     cache->recompute_layout(targetWindow);
3655                     // EFL testing
3656                     windows->update_window(targetWindow);
3657                 }
3658             }
3659             break;
3660             case SIGACTION_FREE_IMAGES:
3661                 proxy->free_images();
3662                 break;
3663             case SIGACTION_CLOSE_POPUP: {
3664                 /* If there is a popup still opened, don't destroy POPUP_TIMEOUT timer */
3665                 if (!(windows->close_all_popups(targetWindow))) {
3666                     events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
3667                 }
3668             }
3669             break;
3670             case SIGACTION_CLOSE_MAGNIFIER: {
3671                 if (signal == SCL_SIG_HIDE) {
3672                     windows->hide_window(windows->get_magnifier_window(), TRUE);
3673                 } else {
3674                     windows->hide_window(windows->get_magnifier_window());
3675                 }
3676             }
3677             //events->create_timer(SCL_TIMER_BUTTON_DELAY, SCL_BUTTON_MIN_DURATION, 0);
3678             break;
3679             case SIGACTION_UNSET_SHIFT: {
3680                 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3681                 if (handler) {
3682
3683                     SclNotiShiftStateChangeDesc desc;
3684                     desc.ui_event_desc = NULL;
3685                     desc.shift_state = SCL_SHIFT_STATE_OFF;
3686
3687                     if (SCL_EVENT_PASS_ON ==
3688                         handler->on_event_notification(SCL_UINOTITYPE_SHIFT_STATE_CHANGE, &desc)) {
3689                         context->set_shift_state(SCL_SHIFT_STATE_OFF);
3690                     }
3691                 }
3692             }
3693             break;
3694             case SIGACTION_UNPRESS_KEYS:
3695                 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3696                 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3697             break;
3698             default:
3699             break;
3700             }
3701         }
3702     }
3703 }
3704
3705 /**
3706  * Sets the duration value for longkey
3707  * If not set, it will use default longkey duration. see sclconfig
3708  */
3709 sclboolean
3710 CSCLController::set_longkey_duration(scllong msc)
3711 {
3712     SCL_DEBUG();
3713     sclboolean ret = FALSE;
3714     if (msc > 0) {
3715         m_long_key_duration = msc;
3716         ret = TRUE;
3717     }
3718     return ret;
3719 }
3720
3721 /**
3722 * Sets the distance value for cancel longkey
3723 * If not set, it will use default longkey duration. see sclconfig
3724 */
3725 sclboolean
3726 CSCLController::set_longkey_cancel_dist(sclshort dist)
3727 {
3728     SCL_DEBUG();
3729     sclboolean ret = FALSE;
3730     if (dist > 0) {
3731         m_long_key_cancel_distance = dist;
3732         ret = TRUE;
3733     }
3734     return ret;
3735 }
3736
3737 /**
3738 * Sets the duration value for repeatkey
3739 * If not set, it will use default repeatkey duration. see sclconfig
3740 */
3741 sclboolean
3742 CSCLController::set_repeatkey_duration(scllong msc)
3743 {
3744     SCL_DEBUG();
3745     sclboolean ret = FALSE;
3746     if (msc > 0) {
3747         m_repeat_key_duration = msc;
3748         ret = TRUE;
3749     }
3750     return ret;
3751 }
3752
3753 /**
3754  * Sets the duration value for autopopup key
3755  * If not set, it will use default short longkey duration. see sclconfig
3756  */
3757 sclboolean
3758 CSCLController::set_autopopup_key_duration(scllong msc)
3759 {
3760     SCL_DEBUG();
3761     sclboolean ret = FALSE;
3762     if (msc > 0) {
3763         m_autopopup_key_duration = msc;
3764         ret = TRUE;
3765     }
3766     return ret;
3767 }
3768
3769 /**
3770  * Sets the amount value for button delay
3771  * If not set, it will use default button delay amount. see sclconfig
3772  */
3773 sclboolean
3774 CSCLController::set_button_delay_duration(scllong msc)
3775 {
3776     SCL_DEBUG();
3777     sclboolean ret = FALSE;
3778     if (msc > 0) {
3779         m_button_delay_duration = msc;
3780         ret = TRUE;
3781     }
3782     return ret;
3783 }
3784
3785 /**
3786  * Configures the variables for auto-popup window
3787  * It will return rectangle area
3788  * @return FALSE It's not avaiable popup key
3789  */
3790 sclboolean
3791 CSCLController::configure_autopopup_window(sclwindow window, sclbyte key_index, SclRectangle* rect)
3792 {
3793     SCL_DEBUG();
3794     scl_assert_return_false(window);
3795     scl_assert_return_false(key_index >= 0);
3796
3797     sclboolean ret = TRUE;
3798
3799     sclbyte num_keys, num_columns, num_rows;
3800
3801     CSCLUtils *utils = CSCLUtils::get_instance();
3802     CSCLContext *context = CSCLContext::get_instance();
3803     CSCLWindows *windows = CSCLWindows::get_instance();
3804     CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3805
3806     const SclLayoutKeyCoordinate *coordinate = NULL;
3807
3808     if (cache) {
3809         coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3810     }
3811
3812     SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3813     PSclAutoPopupConfigure autopopup_configure = NULL;
3814     if (sclres_manager) {
3815         autopopup_configure = sclres_manager->get_autopopup_configure();
3816     }
3817
3818     if (utils && context && windows && cache && coordinate && rect && autopopup_configure) {
3819         SCLShiftState shift_index = context->get_shift_state();
3820         if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
3821         if (context->get_caps_lock_mode()) {
3822             shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
3823         }
3824
3825         if (utils->get_autopopup_window_variables(coordinate->autopopup_key_labels[shift_index],
3826                 &num_keys, &num_columns, &num_rows, &rect->width, &rect->height)) {
3827
3828             /* There is no need for an autopopup window if number of keys are equal to or less than 0 */
3829             if (!(num_keys > 0)) {
3830                 ret = FALSE;
3831             }
3832             /* calculates y position to be set */
3833             SclRectangle baseWndRect;
3834             int scrwidth, scrheight;
3835             utils->get_screen_resolution(&scrwidth, &scrheight);
3836
3837             windows->get_window_rect(windows->get_base_window(), &baseWndRect);
3838             /* Let the autopopup have its position right above the pressed button, with center alignment) */
3839             rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) - (rect->width / 2);
3840             rect->y = baseWndRect.y + coordinate->y - rect->height +
3841                 autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate();
3842             /* First check the growing direction of this autopopup window */
3843             if (coordinate->x < baseWndRect.width / 2) {
3844                 /* We're growing left to right, calculate the left start point */
3845                 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) -
3846                     (autopopup_configure->button_width * utils->get_custom_scale_rate_x() / 2) -
3847                     autopopup_configure->bg_padding * utils->get_smallest_custom_scale_rate();
3848                 if (rect->x + rect->width > baseWndRect.x + baseWndRect.width) {
3849                     sclint relocate_unit = autopopup_configure->button_width * utils->get_custom_scale_rate_x() +
3850                         autopopup_configure->button_spacing * utils->get_smallest_custom_scale_rate();
3851                     rect->x -= (((rect->x + rect->width - (baseWndRect.x + baseWndRect.width)) /
3852                             relocate_unit) + 1) * relocate_unit;
3853                 }
3854             } else {
3855                 /* We're growing right to left, calculate the right end point */
3856                 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) +
3857                     (autopopup_configure->button_width * utils->get_custom_scale_rate_x() / 2) +
3858                     autopopup_configure->bg_padding * utils->get_smallest_custom_scale_rate();
3859                 rect->x -= rect->width;
3860                 if (rect->x < baseWndRect.x) {
3861                     sclint relocate_unit = autopopup_configure->button_width * utils->get_custom_scale_rate_x() +
3862                         autopopup_configure->button_spacing * utils->get_smallest_custom_scale_rate();
3863                     rect->x += (((baseWndRect.x - rect->x) /
3864                             relocate_unit) + 1) * relocate_unit;
3865                 }
3866             }
3867             //rect->y = (scrheight - layout->height) + coordinate->y - rect->height + autopopup_configure->decoration_size;
3868             /* Check if the window goes out of screen boundary */
3869             //if (rect->x + rect->width > scrwidth + utils->get_scale_x(scl_autopopup_configure.decoration_size)) rect->x = (scrwidth + utils->get_scale_x(scl_autopopup_configure.decoration_size)) - rect->width;
3870             if (rect->x + rect->width > scrwidth) rect->x = (scrwidth) - rect->width;
3871             if (rect->y + rect->height > scrheight) rect->y = scrheight - rect->height;
3872             if (rect->x < 0 - autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate())
3873                 rect->x = 0 - autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate();
3874             // restrict to 0
3875             if (rect->x < 0) rect->x = 0;
3876             if (rect->y < 0) rect->y = 0;
3877         } else {
3878             ret = FALSE;
3879         }
3880     }
3881     return ret;
3882 }
3883
3884 /**
3885  * If the mouse was pressed on the button A and moved to B without releasing,
3886  * this function decides whether we should allow event transition, meaning
3887  * button A gets restored to its initial state and B gets pressed instead.
3888  */
3889 sclboolean
3890 CSCLController::check_event_transition_enabled(const SclLayoutKeyCoordinate *btn_from, const SclLayoutKeyCoordinate *btn_to)
3891 {
3892     sclboolean ret = FALSE;
3893     sclbyte type_from = BUTTON_TYPE_NORMAL; /* To enable event transition even if no button is pressed currently */
3894     sclbyte type_to = MAX_BUTTON_TYPE;
3895
3896     const sclboolean TRANSITION_TABLE[MAX_BUTTON_TYPE][MAX_BUTTON_TYPE] = {
3897         //      NORMAL  GRAB    SELFISH DRAG    MULTITAP        ROTATION        DIRECTION       R_DIRECTION     TOGGLE  UIITEM
3898         //      From : NORMAL
3899         {       TRUE,   0,      0,              TRUE,   TRUE,           TRUE,           0,                      0,                      TRUE,           0},
3900         //      From : GRAB
3901         {       0,              0,      0,              0,              0,                      0,                      0,                      0,                      0,                      0},
3902         //      From : SELFISH
3903         {       0,              0,      0,              0,              0,                      0,                      0,                      0,                      0,                      0},
3904         //      From : DRAG
3905         {       TRUE,   0,      0,              TRUE,   TRUE,           TRUE,           0,                      0,                      TRUE,           0},
3906         //      From : MULTITAP
3907         {       TRUE,   0,      0,              TRUE,   TRUE,           TRUE,           0,                      0,                      TRUE,           0},
3908         //      From : ROTATION
3909         {       TRUE,   0,      0,              TRUE,   TRUE,           TRUE,           0,                      0,                      TRUE,           0},
3910         //      From : DIRECTION
3911         {       0,              0,      0,              0,              0,                      0,                      0,                      0,                      0,                      0},
3912         //      From : R_DIRECTION
3913         {       0,              0,      0,              0,              0,                      0,                      0,                      0,                      0,                      0},
3914         //      From : UIITEM
3915         {       0,              0,      0,              0,              0,                      0,                      0,                      0,                      0,                      0},
3916         //      From : TOGGLE
3917         {       TRUE,   0,      0,              TRUE,   TRUE,           TRUE,           0,                      0,                      TRUE,           0},
3918     };
3919
3920     if (btn_from) type_from = btn_from->button_type;
3921     if (btn_to) type_to = btn_to->button_type;
3922
3923     scl_assert_return_false(type_from >= 0 && type_from < MAX_BUTTON_TYPE);
3924     scl_assert_return_false(type_to >= 0 && type_to < MAX_BUTTON_TYPE);
3925
3926     if (type_from < MAX_BUTTON_TYPE && type_to < MAX_BUTTON_TYPE) {
3927         ret = TRANSITION_TABLE[type_from][type_to];
3928     }
3929
3930     return ret;
3931 }
3932
3933 SCLDebugMode
3934 CSCLController::get_debug_mode()
3935 {
3936 #ifdef SCL_DEBUG_ON
3937     return m_debug_mode;
3938 #else
3939     return m_debug_mode;
3940     return DEBUGMODE_DISABLED;
3941 #endif
3942 }
3943
3944 void
3945 CSCLController::set_debug_mode(SCLDebugMode mode)
3946 {
3947     CSCLEvents *events = CSCLEvents::get_instance();
3948     CSCLUtils *utils = CSCLUtils::get_instance();
3949
3950     m_debug_mode = mode;
3951     m_debug_variable = 0;
3952
3953     if (m_debug_mode == DEBUGMODE_AUTOTEST) {
3954         srand(time(NULL));
3955         if (events && utils) {
3956             events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INITIAL_INTERVAL, 0, FALSE);
3957             utils->log("mode : %d\n", mode);
3958         }
3959     }
3960 }
3961
3962 void
3963 CSCLController::disable_input_events(sclboolean disabled)
3964 {
3965     m_input_events_disabled = disabled;
3966 }