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