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