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