2 * Copyright (c) 2012 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
23 #include "sclcontroller.h"
25 #include "sclresourcecache.h"
26 #include "sclactionstate.h"
27 #include "scluibuilder.h"
28 #include "sclkeydefines.h"
29 #include "sclfeedback.h"
30 #include "sclerroradjustment.h"
31 #include "sclimageproxy.h"
32 #include "sclres_manager.h"
33 #include "scleventhandler.h"
34 #include "sclanimator.h"
37 //#define DIRECTLY_DRAW_ON_EVENTS
42 _play_tts_for_input_mode_name(int mode) {
45 CSCLContext *context = CSCLContext::get_instance();
46 if (context->get_tts_enabled() == FALSE) {
50 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
51 const SclInputModeConfigure *pinput_mode_table = sclres_manager->get_input_mode_configure_table();
52 if (NULL == pinput_mode_table) {
56 const char* name = pinput_mode_table[mode].name;
61 CSCLUtils *utils = CSCLUtils::get_instance();
62 utils->play_tts(name);
67 _play_tts_for_layout_autopopup_name() {
70 CSCLContext *context = CSCLContext::get_instance();
71 if (context->get_tts_enabled() == FALSE) {
75 CSCLUtils *utils = CSCLUtils::get_instance();
76 utils->play_tts(SCL_LAYOUT_AUTOPOPUP_NAME);
80 CSCLController::CSCLController()
84 m_long_key_duration = SCL_LONGKEY_DURATION;
85 m_long_key_cancel_distance = SCL_LONGKEY_CANCEL_DIST;
86 m_repeat_key_duration = SCL_REPEATKEY_DURATION;
87 m_autopopup_key_duration = SCL_AUTOPOPUP_KEY_DURATION;
89 m_button_delay_duration = SCL_BUTTON_MIN_DURATION;
91 m_key_repeated_num = 0;
93 m_debug_mode = DEBUGMODE_DISABLED;
96 m_input_events_disabled = FALSE;
99 CSCLController::~CSCLController()
105 CSCLController::get_instance()
107 static CSCLController instance;
112 CSCLController::init()
117 //#define TEST_NEWBACKEND
118 #ifdef TEST_NEWBACKEND
119 #include <Ecore_Evas.h>
125 EFLOBJECT_CLIPOBJECT,
131 SclRectangle position;
134 sclboolean extracted;
137 #include <Ecore_Evas.h>
143 Evas_Object *clipper;
146 sclchar image_path[_POSIX_PATH_MAX];
156 sclboolean extrace_image;
165 scl::SclFontInfo font_info;
167 sclchar str[_POSIX_PATH_MAX];;
173 SCLLabelAlignment align;
177 sclbyte inner_height;
180 extern std::vector<ImageCache> g_ImageCache;
181 extern std::vector<TextCache> g_TextCache;
186 * Sets the current input mode to the given mode
189 CSCLController::process_input_mode_change(const sclbyte mode)
193 sclboolean ret = FALSE;
195 CSCLUtils *utils = CSCLUtils::get_instance();
196 CSCLContext *context = CSCLContext::get_instance();
197 CSCLWindows *windows = CSCLWindows::get_instance();
198 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
199 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
200 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
201 assert(sclres_input_mode_configure != NULL);
203 if (context && windows && cache && utils) {
204 if (mode == context->get_input_mode() || mode == (sclbyte)NOT_USED) {
205 /* ButtonContext does not get initialized if we don't call here */
206 cache->recompute_layout(windows->get_base_window());
210 context->set_input_mode(mode);
211 /* FIXME : NEWXML temporary commenting out */
212 //context->set_base_layout(sclres_input_mode_configure[mode].layouts[context->get_display()]);
214 _play_tts_for_input_mode_name(mode);
216 sclwindow window = windows->get_base_window();
217 handle_engine_signal(SCL_SIG_INPMODE_CHANGE, window);
219 #ifdef TEST_NEWBACKEND
220 SclWindowContext *window_context= windows->get_window_context(window, FALSE);
221 if (window_context) {
222 if (window_context->etc_info) {
224 Eina_List *list = (Eina_List*)(window_context->etc_info);
225 Eina_List *iter = NULL;
226 Eina_List *iter_next = NULL;
230 EINA_LIST_FOREACH_SAFE(list, iter, iter_next, data) {
232 EFLObject *object = (EFLObject*)(data);
234 Evas_Object* eo = object->object;
235 if (object->extracted) {
236 void *data = evas_object_image_data_get(eo, 1);
243 for(loop = 0;loop < g_ImageCache.size();loop++) {
244 if (g_ImageCache[loop].image == object->object) {
245 g_ImageCache[loop].used = FALSE;
248 for(loop = 0;loop < g_TextCache.size();loop++) {
249 if (g_TextCache[loop].text == object->object) {
250 g_TextCache[loop].used = FALSE;
256 object->object = NULL;
260 list = eina_list_remove_list(list, iter);
264 window_context->etc_info= list;
274 * Sets the current display mode to the given mode
277 CSCLController::process_rotation_change(const SCLRotation rotation)
280 CSCLContext *context = CSCLContext::get_instance();
281 CSCLWindows *windows = CSCLWindows::get_instance();
282 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
283 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
284 assert(sclres_input_mode_configure != NULL);
286 if (context && windows) {
288 if (rotation == ROTATION_90_CW || rotation == ROTATION_90_CCW) {
289 mode = DISPLAYMODE_LANDSCAPE;
291 mode = DISPLAYMODE_PORTRAIT;
294 //if (mode == context->get_display()) return FALSE;
295 context->set_display_mode(mode);
296 context->set_rotation(rotation);
297 /* FIXME : NEWXML temporary commenting out */
298 //context->set_base_layout(sclres_input_mode_configure[context->get_input_mode()].layouts[context->get_display()]);
300 sclwindow window = windows->get_base_window();
301 handle_engine_signal(SCL_SIG_DISP_CHANGE, window);
302 windows->update_window(window);
304 /* Moved to here since the new WMSync requires the rotation call be invoked as the
305 last step of display change process */
306 /* Make sure to set window's rotation degree before sending engine signal, which adjusts the size of main window */
307 windows->set_window_rotation(NULL, rotation);
313 * Checks if the given button with given touch_id needs magnifier window
316 CSCLController::check_magnifier_available(sclwindow window, sclbyte key_index, scltouchdevice touch_id)
318 sclboolean ret = FALSE;
320 CSCLContext *context = CSCLContext::get_instance();
321 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
322 const SclLayout *layout = NULL;
323 SclButtonContext *button_context = NULL;
324 const SclLayoutKeyCoordinate *coordinate = NULL;
326 if (context && cache) {
327 layout = cache->get_cur_layout(window);
328 button_context = cache->get_cur_button_context(window, key_index);
329 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
331 SCLShiftState shift_index = context->get_shift_state();
332 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
333 if (context->get_caps_lock_mode()) {
334 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
337 if (layout && coordinate && button_context && context->get_magnifier_enabled() ) {
338 if (coordinate->key_type != KEY_TYPE_CONTROL &&
339 coordinate->key_type != KEY_TYPE_MODECHANGE &&
340 coordinate->key_type != KEY_TYPE_NONE) {
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");
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);
355 custom_label = temp_label;
359 //if (coordinate->key_value[shift_index][button_context->multikeyIdx] == NULL) {
360 if (coordinate->label[shift_index][button_context->multikeyIdx] == NULL) {
361 //utils->log("show_magnifier coordinate->key_value[shift][button_context->multikeyIdx] == NULL \n");
363 //} else if (strlen(coordinate->key_value[shift_index][button_context->multikeyIdx]) == 0) {
364 } else if (strlen(coordinate->label[shift_index][button_context->multikeyIdx]) == 0) {
365 //utils->log("show_magnifier coordinate->key_value[shift][button_context->multikeyIdx]) == 0 \n");
370 if (touch_id != context->get_last_touch_device_id()) {
381 CSCLController::process_button_pressed_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
382 scltouchdevice touch_id, sclboolean actual_event)
386 sclboolean ret = FALSE;
387 sclboolean redraw = FALSE;
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);
402 SclButtonContext *button_context = NULL;
403 const SclLayoutKeyCoordinate *coordinate = NULL;
405 if (context && cache) {
406 button_context = cache->get_cur_button_context(window, key_index);
407 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
410 if (context && cache && windows && events && utils && feedback && handler && button_context && coordinate) {
411 /* First check if this button is enabled in current active sublayout */
412 sclboolean sub_layout_match = TRUE;
413 if (coordinate->sub_layout && context->get_cur_sublayout()) {
414 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
415 sub_layout_match = FALSE;
418 /* If this button is pressed */
419 if ( x >= coordinate->x - coordinate->add_hit_left &&
420 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
421 y >= coordinate->y - coordinate->add_hit_top &&
422 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
423 /* Process the event only if the this item's sublayout id is active one */
425 //utils->log("process_button_pressed_event___TRUE\n");
427 /* If newly pressed key has type MULTI_TOUCH_TYPE_EXCLUSIVE, release all existing pressed events */
429 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_EXCLUSIVE) {
430 /* When calling mouse_release, the seq order of current multitouch events will be changed,
431 so we put all the multitouch events into a vector and use them afterwards forreleasing */
433 sclint multi_touch_context_num = context->get_multi_touch_context_num();
434 std::vector<SclUIEventDesc> multi_touch_events;
435 for(loop = 0;loop < multi_touch_context_num;loop++) {
437 context->get_multi_touch_event(loop, &desc);
438 multi_touch_events.push_back(desc);
440 for(loop = 0;loop < multi_touch_context_num;loop++) {
441 SclUIEventDesc desc = multi_touch_events[loop];
442 if (desc.touch_id != touch_id) {
443 mouse_release(context->get_cur_moving_window(desc.touch_id),
444 context->get_cur_moving_point(desc.touch_id).x,
445 context->get_cur_moving_point(desc.touch_id).y,
446 desc.touch_id, FALSE);
452 /* Make an unique ID for timer */
453 const scl16 uniqId = utils->get_unique_id();
455 context->set_cur_pressed_event_id(touch_id, uniqId);
456 context->set_cur_pressed_key(touch_id, key_index);
457 context->set_cur_pressed_window(touch_id, window);
459 button_context->state = BUTTON_STATE_PRESSED;
464 #ifndef DIRECTLY_DRAW_ON_EVENTS
465 /* If the window doesn't get exposed before corresponding release event,
466 * the inverted state of a button will never be drawn onto screen.
467 * To prevent such a case, we draw the inverted state of button forcefully and directly,
468 * without waiting for expose event */
469 /*CSCLGraphics *grps = CSCLGraphics::get_instance();
470 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
471 scldrawctx draw_ctx = grps->begin_paint(window, TRUE);
472 builder->draw_button(window, draw_ctx, key_index, button_context->state, TRUE);
473 grps->end_paint(window, draw_ctx);*/
477 feedback->button_pressed(window, key_index);
479 /* Special routine for autopopup */
480 if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
481 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
483 /* for long key & repeat key */
484 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
487 SCLShiftState shift_index = context->get_shift_state();
488 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
489 if (context->get_caps_lock_mode()) {
490 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
493 SclUIEventDesc key_event_desc;
494 key_event_desc.key_value = coordinate->key_value[shift_index][0];
495 key_event_desc.key_event = coordinate->key_event[shift_index][0];
496 key_event_desc.key_type = coordinate->key_type;
497 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
498 key_event_desc.event_type = EVENT_TYPE_PRESS;
500 SclPoint curpoint = {x, y};
501 key_event_desc.touch_id = touch_id;
502 key_event_desc.mouse_pressed_point = curpoint;
503 key_event_desc.mouse_current_point = curpoint;
504 key_event_desc.mouse_farthest_point = curpoint;
506 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
508 SCLEventReturnType processed = handler->on_event_drag_state_changed(key_event_desc);
510 /* Only if the handler didn't return SCL_EVENT_DONE */
511 if (processed == SCL_EVENT_PASS_ON) {
512 /* Now process normal behaviours of each button type */
513 switch (coordinate->button_type) {
514 case BUTTON_TYPE_NORMAL:
515 case BUTTON_TYPE_GRAB:
516 case BUTTON_TYPE_SELFISH:
517 case BUTTON_TYPE_DIRECTION:
518 case BUTTON_TYPE_RELATIVE_DIRECTION: {
519 /* Send click event right away if this button uses repeat key */
520 if (coordinate->use_repeat_key) {
521 handler->on_event_key_clicked(key_event_desc);
525 case BUTTON_TYPE_MULTITAP: {
528 case BUTTON_TYPE_ROTATION: {
531 case BUTTON_TYPE_DRAG: {
532 /* Drag buttons fires click event immediately when they are pressed */
533 handler->on_event_key_clicked(key_event_desc);
536 case BUTTON_TYPE_UIITEM: break;
537 case MAX_BUTTON_TYPE: break;
540 switch (coordinate->popup_type) {
541 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: {
542 SclNotiPopupOpeningDesc desc;
543 desc.ui_event_desc = &key_event_desc;
544 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
545 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
546 sclint popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
547 SCLDisplayMode display_mode = context->get_display_mode();
549 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
550 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
551 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
552 sclshort popupLayoutId =
553 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
554 SclRectangle popupRect;
555 SclRectangle baseWndRect;
556 SclLayout *layout = NULL;
558 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
559 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
560 layout = &sclres_layout[popupLayoutId];
563 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
564 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
565 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
566 //popupRect.width = utils->get_scale_x(layout->width);
567 //popupRect.height= utils->get_scale_y(layout->height);
568 popupRect.width = layout->width;
569 popupRect.height= layout->height;
570 windows->close_all_popups();
572 SclWindowOpener opener;
573 opener.window = window;
574 opener.key = key_index;
576 sclwindow popup_window = windows->open_popup(opener,
580 coordinate->popup_type,
581 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
582 sclres_input_mode_configure[popup_input_mode].use_dim_window,
583 coordinate->extract_offset_x,
584 coordinate->extract_offset_y,
585 sclres_input_mode_configure[popup_input_mode].timeout
588 SclNotiPopupOpenedDesc opened_desc;
589 opened_desc.ui_event_desc = &key_event_desc;
590 opened_desc.input_mode = desc.input_mode;
591 opened_desc.window = popup_window;
592 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
594 windows->hide_window(windows->get_magnifier_window());
595 /* FIXME : The parent key should be turned back to NORMAL state when RELEASED,
596 in case of POPUP_TYPE_BTN_PRESS_POPUP_DRAG type. Temporariliy setting NORMAL here. */
597 button_context->state = BUTTON_STATE_NORMAL;
598 _play_tts_for_input_mode_name(popup_input_mode);
604 case POPUP_TYPE_BTN_RELEASE_POPUP:
605 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
606 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
607 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
608 case POPUP_TYPE_AUTO_POPUP:
609 case POPUP_TYPE_NONE:
612 /* Nothing to do in here */
617 /* Shows the magnifier window(the magnifier window will display when a kind of button type is character) */
618 //if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
619 if (coordinate->use_magnifier) {
620 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
622 PSclMagnifierWndConfigure magnifier_configure = NULL;
623 if (sclres_manager) {
624 magnifier_configure = sclres_manager->get_magnifier_configure();
626 if (showMagnifier && magnifier_configure) {
627 SclPoint pos = {0,0};
628 /* calculates x position to be set */
629 pos.x = (coordinate->x + (coordinate->width / 2)) -
630 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
632 /* calculates y position to be set */
633 sclint scnWidth, scnHeight;
634 utils->get_screen_resolution(&scnWidth, &scnHeight);
636 pos.y = coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
638 /* FIXME : Temporary way of clearing magnifier window */
639 /*SclWindowContext *window_context = windows->get_window_context(windows->get_magnifier_window(), FALSE);
640 sclboolean clearmagwin = FALSE;
641 if (window_context) {
642 clearmagwin = !(window_context->hidden);
644 static int clearnum = 0;
645 if (key_index == prevkey && window == prevwin) {
649 if (++clearnum > 1) {
657 CSCLGraphics *graphics = CSCLGraphics::get_instance();
658 CSCLUtils *utils = CSCLUtils::get_instance();
659 sclchar composed_path[_POSIX_PATH_MAX] = {0,};
660 scldrawctx draw_ctx = graphics->begin_paint(windows->get_magnifier_window());
661 utils->get_composed_path(composed_path, scl_magnifier_configure.bg_image_path);
662 graphics->draw_image(windows->get_magnifier_window(), draw_ctx, composed_path, 0, 0);
663 graphics->end_paint(windows->get_magnifier_window(), draw_ctx);
666 windows->hide_window(windows->get_magnifier_window());
668 SclWindowContext *window_context = windows->get_window_context(window);
669 if (window_context) {
670 pos.x += window_context->geometry.x;
671 pos.y += window_context->geometry.y;
674 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
675 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
677 if (pos.x > scnWidth +
678 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
679 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
680 pos.x = scnWidth + magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
681 magnifier_configure->width * utils->get_custom_scale_rate_x();
683 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
684 pos.x += coordinate->magnifier_offset_x;
685 pos.y += coordinate->magnifier_offset_y;
686 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
687 //windows->resize_window(windows->get_magnifier_window(), utils->get_scale_x(scl_magnifier_configure.width), utils->get_scale_y(scl_magnifier_configure.height));
688 /*If we use transient_for them the ISE will occure some crash. It needs to check X11 */
689 /*windows->set_parent(windows->get_base_window(), windows->get_magnifier_window());*/
691 windows->show_window(windows->get_magnifier_window(), TRUE);
692 //windows->update_window(windows->get_magnifier_window());
695 static int fFirst = true;
697 windows->show_window(windows->get_magnifier_window());
700 windows->update_window(windows->get_magnifier_window());
703 /* We cannot use move_resize_window. It had occured some wrong behavior */
704 /*windows->move_resize_window(windows->get_magnifier_window(), pos.x, pos.y, scl_magnifier_configure.width, scl_magnifier_configure.height);*/
705 if (!showMagnifier) {
706 windows->hide_window(windows->get_magnifier_window());
710 /* COMMENTED OUT FOR TESTING MULTITOUCH!! */
711 ///* In case the current button is not the given key index */
712 //if (button_context->state == BUTTON_STATE_PRESSED) {
713 // /* Even if the press event occured outside of this button's physical area, reset its context */
714 // button_context->state = BUTTON_STATE_NORMAL;
717 /* BUTTON_TYPE_MULTITAP type button should restore its multikey index when another button is clicked */
718 if (coordinate->button_type & BUTTON_TYPE_MULTITAP) {
719 button_context->multikeyIdx = 0;
723 /* If there is any need for redrawing */
725 #ifdef DIRECTLY_DRAW_ON_EVENTS
726 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
728 builder->draw_button(window, NULL, key_index, button_context->state, TRUE);
732 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
742 CSCLController::process_button_long_pressed_event(sclwindow window, sclbyte key_index,
743 scltouchdevice touch_id, sclboolean actual_event)
747 sclboolean ret = FALSE;
749 CSCLContext *context = CSCLContext::get_instance();
750 CSCLWindows *windows = CSCLWindows::get_instance();
751 CSCLActionState *state = CSCLActionState::get_instance();
752 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
753 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
754 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
755 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
756 PSclLayout sclres_layout = sclres_manager->get_layout_table();
758 assert(sclres_input_mode_configure != NULL);
759 assert(sclres_layout != NULL);
760 if (context && cache && handler && windows && state) {
761 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
763 /* Should return FALSE if this key does not have any longkey related property */
766 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
767 /* When calling mouse_release, the seq order of current multitouch events will be ch anged,
768 so we put all the multitouch events into a vector and use them afterwards for rel easing */
769 sclboolean finished = FALSE;
771 sclint multi_touch_context_num = context->get_multi_touch_context_num();
772 std::vector<SclUIEventDesc> multitouch_events;
773 for (loop = 0;loop < multi_touch_context_num;loop++) {
775 context->get_multi_touch_event(loop, &desc);
776 multitouch_events.push_back(desc);
778 for (loop = 0;loop < multi_touch_context_num && !finished;loop++) {
779 SclUIEventDesc desc = multitouch_events[loop];
780 if (desc.touch_id != touch_id) {
781 sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
782 scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
783 const SclLayoutKeyCoordinate *cur_pressed_coordinate =
784 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
785 if (cur_pressed_coordinate) {
786 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
787 mouse_release(context->get_cur_moving_window(desc.touch_id),
788 context->get_cur_moving_point(desc.touch_id).x,
789 context->get_cur_moving_point(desc.touch_id).y,
790 desc.touch_id, FALSE);
801 /* Should return FALSE if this key does not have any longkey related property */
803 if (coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP ||
804 coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE ) {
806 SclUIEventDesc key_event_desc;
807 key_event_desc.key_type = coordinate->long_key_type;
808 if (coordinate->long_key_value == NULL && coordinate->long_key_event == 0) {
809 SCLShiftState shift_index = context->get_shift_state();
810 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
811 if (context->get_caps_lock_mode()) {
812 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
815 key_event_desc.key_value = coordinate->key_value[shift_index][0];
816 key_event_desc.key_event = coordinate->key_event[shift_index][0];
818 key_event_desc.key_value = coordinate->long_key_value;
819 key_event_desc.key_event = coordinate->long_key_event;
821 key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
823 key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
824 key_event_desc.touch_id = touch_id;
825 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
826 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
827 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
829 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
831 SCLEventReturnType processed = handler->on_event_drag_state_changed(key_event_desc);
833 /* Only if the handler didn't return SCL_EVENT_DONE */
834 if (processed == SCL_EVENT_PASS_ON) {
835 SclRectangle popupRect;
836 SclRectangle baseWndRect;
837 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
838 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
839 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
841 SclNotiPopupOpeningDesc desc;
842 desc.ui_event_desc = &key_event_desc;
843 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
844 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
845 sclint popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
846 SCLDisplayMode display_mode = context->get_display_mode();
848 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
849 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
850 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
851 SclLayout *layout = NULL;
852 sclshort popupLayoutId =
853 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
855 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
856 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
857 layout = &sclres_layout[popupLayoutId];
860 //popupRect.width = utils->get_scale_x(layout->width);
861 //popupRect.height= utils->get_scale_y(layout->height);
862 popupRect.width = layout->width;
863 popupRect.height= layout->height;
865 SclWindowOpener opener;
866 opener.window = window;
867 opener.key = key_index;
869 sclwindow popup_window = windows->open_popup(
874 coordinate->popup_type,
875 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
876 sclres_input_mode_configure[popup_input_mode].use_dim_window,
877 coordinate->extract_offset_x,
878 coordinate->extract_offset_y,
879 sclres_input_mode_configure[popup_input_mode].timeout
882 SclNotiPopupOpenedDesc opened_desc;
883 opened_desc.ui_event_desc = &key_event_desc;
884 opened_desc.input_mode = desc.input_mode;
885 opened_desc.window = popup_window;
886 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
888 windows->hide_window(windows->get_magnifier_window());
889 _play_tts_for_input_mode_name(popup_input_mode);
895 } else if (coordinate->long_key_value) {
896 if (strlen(coordinate->long_key_value) > 0) {
897 if (windows->is_base_window(window)) {
898 state->set_cur_action_state(ACTION_STATE_BASE_LONGKEY);
900 state->set_cur_action_state(ACTION_STATE_POPUP_LONGKEY);
904 PSclMagnifierWndConfigure magnifier_configure = NULL;
905 if (sclres_manager) {
906 magnifier_configure = sclres_manager->get_magnifier_configure();
908 if (coordinate->use_long_key_magnifier && magnifier_configure) {
909 CSCLUtils *utils = CSCLUtils::get_instance();
910 SclPoint pos = {0,0};
912 const SclLayout* layout = cache->get_cur_layout(window);
914 sclint scnWidth, scnHeight;
915 utils->get_screen_resolution(&scnWidth, &scnHeight);
917 //SclWindowContext *window_context = windows->get_window_context(window, TRUE);
918 SclWindowContext *window_context = windows->get_window_context(window);
919 if (window_context) {
920 pos.x = window_context->geometry.x + (coordinate->x + (coordinate->width / 2)) -
921 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
922 pos.y = window_context->geometry.y + coordinate->y -
923 magnifier_configure->height * utils->get_custom_scale_rate_y();
925 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
926 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
928 if (pos.x > scnWidth +
929 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
930 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
932 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
933 magnifier_configure->width * utils->get_custom_scale_rate_x();
935 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
936 pos.x += coordinate->magnifier_offset_x;
937 pos.y += coordinate->magnifier_offset_y;
938 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
939 windows->update_window(windows->get_magnifier_window());
940 windows->show_window(windows->get_magnifier_window(),TRUE);
944 SclUIEventDesc key_event_desc;
945 key_event_desc.key_type = coordinate->long_key_type;
946 key_event_desc.key_value = coordinate->long_key_value;
947 key_event_desc.key_event = coordinate->long_key_event;
948 key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
950 key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
951 key_event_desc.touch_id = touch_id;
952 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
953 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
954 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
956 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
958 handler->on_event_key_clicked(key_event_desc);
964 context->set_cur_key_modifier(touch_id, KEY_MODIFIER_LONGKEY);
967 /* Longkey processing in here */
972 CSCLController::process_button_repeat_pressed_event(sclwindow window, sclbyte key_index,
973 scltouchdevice touch_id, sclboolean actual_event)
976 CSCLContext *context = CSCLContext::get_instance();
977 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
978 CSCLWindows *windows = CSCLWindows::get_instance();
979 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
981 if (context && cache && windows && handler) {
982 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
984 SCLShiftState shift_index = context->get_shift_state();
985 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
986 if (context->get_caps_lock_mode()) {
987 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
991 switch (coordinate->button_type) {
992 case BUTTON_TYPE_NORMAL:
993 case BUTTON_TYPE_GRAB:
994 case BUTTON_TYPE_SELFISH:
995 case BUTTON_TYPE_DIRECTION:
996 case BUTTON_TYPE_RELATIVE_DIRECTION: {
997 /* This is for enabling backspace key in search layout*/
998 //if (coordinate->key_type != KEY_TYPE_MODECHANGE && coordinate->key_type != KEY_TYPE_COMPOSITION) {
999 //if (coordinate->key_type != KEY_TYPE_MODECHANGE || coordinate->key_event[0][0] == MVK_BackSpace) {
1000 if (coordinate->key_type != KEY_TYPE_MODECHANGE) {
1001 sclulong repeatKeyEvent = coordinate->key_event[shift_index][0];
1003 /* In case of Delete key, Change from Char deletion to Word deletion
1004 when the input acceleration speed is reached to Max */
1005 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1006 PSclDefaultConfigure default_configure = NULL;
1007 if (sclres_manager) {
1008 default_configure = sclres_manager->get_default_configure();
1010 if (default_configure) {
1011 if (default_configure->use_word_deletion) {
1012 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
1013 if (repeatKeyEvent == MVK_BackSpace &&
1014 interval <= SCL_REPEATKEY_WORD_DELETION_START_DURATION) {
1015 repeatKeyEvent = MVK_3270_DeleteWord;
1020 SclUIEventDesc key_event_desc;
1021 key_event_desc.key_value = coordinate->key_value[shift_index][0];
1022 key_event_desc.key_event = repeatKeyEvent;
1023 key_event_desc.key_type = coordinate->key_type;
1024 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1026 key_event_desc.event_type = EVENT_TYPE_REPEAT;
1027 key_event_desc.touch_id = touch_id;
1028 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1029 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1030 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1032 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1034 handler->on_event_key_clicked(key_event_desc);
1038 case BUTTON_TYPE_UIITEM: break;
1039 case MAX_BUTTON_TYPE: break;
1045 /* Longkey processing in here */
1050 CSCLController::process_button_move_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1051 scltouchdevice touch_id, sclboolean actual_event)
1055 sclboolean ret = FALSE;
1057 CSCLUtils *utils = CSCLUtils::get_instance();
1058 CSCLEvents *events = CSCLEvents::get_instance();
1059 CSCLContext *context = CSCLContext::get_instance();
1060 CSCLWindows *windows = CSCLWindows::get_instance();
1061 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1062 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1063 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1065 SclButtonContext *button_context = NULL;
1067 const SclLayoutKeyCoordinate *coordinate = NULL;
1070 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1071 button_context = cache->get_cur_button_context(window, key_index);
1074 if (button_context && coordinate && feedback && utils && context && handler && cache && events && windows) {
1075 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1076 sclint thresholdX = 0;
1077 sclint thresholdY = 0;
1078 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1079 thresholdX = utils->get_scaled_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1080 thresholdY = utils->get_scaled_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1083 /* First check if this button is enabled in current active sublayout */
1084 sclboolean subLayoutMatch = TRUE;
1085 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1086 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1087 subLayoutMatch = FALSE;
1090 if ( x >= coordinate->x - coordinate->add_hit_left - thresholdX &&
1091 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX&&
1092 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1093 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1097 SCLShiftState shift_index = context->get_shift_state();
1098 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1099 if (context->get_caps_lock_mode()) {
1100 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1103 const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1105 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1106 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1107 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1108 const SclLayoutKeyCoordinate *pressed_coordinate =
1109 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1111 if (pressed_context == NULL || pressed_coordinate == NULL) {
1115 if (key_index != pressed_key || window != pressed_window ) {
1116 /* When the focus has moved to another button, destroy all the timers */
1117 events->destroy_all_timer();
1119 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1121 const scl16 uniqId = utils->get_unique_id();
1122 context->set_cur_pressed_event_id(touch_id, uniqId);
1123 /* Special routine for autopopup */
1124 if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
1125 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
1127 /* for long key & repeat key */
1128 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
1131 context->set_cur_pressed_window(touch_id, window);
1132 context->set_cur_pressed_key(touch_id, key_index);
1134 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
1136 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1137 PSclMagnifierWndConfigure magnifier_configure = NULL;
1138 if (sclres_manager) {
1139 magnifier_configure = sclres_manager->get_magnifier_configure();
1141 if (showMagnifier && magnifier_configure) {
1142 SclPoint pos = {0,0};
1143 /* calculates x position to be set */
1144 pos.x = (coordinate->x + (coordinate->width / 2)) -
1145 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
1147 /* calculates y position to be set */
1148 sclint scnWidth, scnHeight;
1149 utils->get_screen_resolution(&scnWidth, &scnHeight);
1151 pos.y = (scnHeight - layout->height) + coordinate->y -
1152 magnifier_configure->height * utils->get_custom_scale_rate_y();
1154 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
1155 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
1157 if (pos.x > scnWidth +
1158 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1159 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
1161 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1162 magnifier_configure->width * utils->get_custom_scale_rate_x();
1164 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1165 if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
1166 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
1167 windows->update_window(windows->get_magnifier_window());
1172 feedback->button_moved(window, key_index);
1174 button_context->state = BUTTON_STATE_PRESSED;
1175 if (pressed_context) {
1176 /* But, if this button should be in pressed state in other multitouch id, do not initialize it */
1177 sclboolean found = FALSE;
1178 for(sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1179 SclUIEventDesc desc;
1180 context->get_multi_touch_event(loop, &desc);
1181 if (desc.touch_id != touch_id) {
1182 MultiTouchContext *multi_touch_context =
1183 context->find_multi_touch_context(desc.touch_id);
1184 if (multi_touch_context) {
1185 if (multi_touch_context->cur_pressed_window == pressed_window &&
1186 multi_touch_context->cur_pressed_key == pressed_key) {
1193 pressed_context->state = BUTTON_STATE_NORMAL;
1196 /* If the window doesn't get exposed before corresponding release event,
1197 * the inverted state of a button will never be drawn onto screen.
1198 * To prevent such a case, we draw the inverted state of button forcefully and directly,
1199 * without waiting for expose event */
1200 /* Redrawing pressed button does not work properly, commented out */
1202 CSCLGraphics *grps = CSCLGraphics::get_instance();
1203 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1204 scldrawctx draw_ctx;
1205 if (pressed_window != SCLWINDOW_INVALID && pressed_key != NOT_USED) {
1206 draw_ctx = grps->begin_paint(pressed_window, TRUE);
1207 builder->draw_button(pressed_window, draw_ctx, pressed_key, FALSE);
1208 grps->end_paint(pressed_window, draw_ctx);
1210 draw_ctx = grps->begin_paint(window, TRUE);
1211 builder->draw_button(window, draw_ctx, key_index, TRUE);
1212 grps->end_paint(window, draw_ctx);
1215 switch (coordinate->button_type) {
1216 case BUTTON_TYPE_DRAG: {
1217 SclUIEventDesc key_event_desc;
1218 key_event_desc.key_value = coordinate->key_value[shift_index][0];
1219 key_event_desc.key_event = coordinate->key_event[shift_index][0];
1220 key_event_desc.key_type = coordinate->key_type;
1221 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1223 key_event_desc.event_type = EVENT_TYPE_MOVE;
1224 key_event_desc.touch_id = touch_id;
1225 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1226 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1227 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1229 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1231 if (sclres_manager) {
1232 magnifier_configure = sclres_manager->get_magnifier_configure();
1234 sclboolean processed = handler->on_event_drag_state_changed(key_event_desc);
1235 if (processed && context->get_magnifier_enabled() && magnifier_configure) {
1236 SclPoint zoomwinpos = {0,0};
1237 /* calculates x position to be set */
1238 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
1239 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
1241 /* calculates y position to be set */
1242 sclint scnWidth, scnHeight;
1243 utils->get_screen_resolution(&scnWidth, &scnHeight);
1245 zoomwinpos.y = coordinate->y -
1246 magnifier_configure->height * utils->get_custom_scale_rate_y();
1247 SclWindowContext *window_context = windows->get_window_context(window);
1248 if (window_context) {
1249 zoomwinpos.x += window_context->geometry.x;
1250 zoomwinpos.y += window_context->geometry.y;
1252 if (zoomwinpos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
1253 zoomwinpos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
1255 if (zoomwinpos.x > scnWidth +
1256 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1257 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
1258 zoomwinpos.x = scnWidth +
1259 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1260 magnifier_configure->width * utils->get_custom_scale_rate_x();
1262 zoomwinpos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1263 zoomwinpos.x += coordinate->magnifier_offset_x;
1264 zoomwinpos.y += coordinate->magnifier_offset_y;
1265 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y);
1266 windows->show_window(windows->get_magnifier_window(), 0);
1269 handler->on_event_key_clicked(key_event_desc);
1270 if (!(windows->is_base_window(window))) {
1271 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
1272 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
1273 SclWindowContext *window_context = windows->get_window_context(window);
1274 if (window_context) {
1275 if (window_context->timeout > 0) {
1276 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
1277 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, window_context->timeout, 0, TRUE);
1283 case BUTTON_TYPE_NORMAL: break;
1284 case BUTTON_TYPE_GRAB: break;
1285 case BUTTON_TYPE_SELFISH: break;
1286 case BUTTON_TYPE_MULTITAP: break;
1287 case BUTTON_TYPE_ROTATION: break;
1288 case BUTTON_TYPE_DIRECTION: break;
1289 case BUTTON_TYPE_RELATIVE_DIRECTION: break;
1290 case BUTTON_TYPE_UIITEM: break;
1291 case MAX_BUTTON_TYPE: break;
1296 #ifdef DIRECTLY_DRAW_ON_EVENTS
1297 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1299 if (button_context) {
1300 builder->draw_button(window, NULL, key_index, button_context->state);
1302 if (pressedContext) {
1303 builder->draw_button(pressed_window, NULL, pressed_key, pressedContext->state, TRUE);
1307 windows->update_window(window,
1308 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1309 if (pressed_coordinate) {
1310 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1311 pressed_coordinate->width, pressed_coordinate->height);
1316 //utils->log("Now Moving : %d %d\n", pos.x, pos.y);
1318 /* If the focus went out from our SELFISH button */
1319 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH) {
1320 pressed_context->state = BUTTON_STATE_NORMAL;
1321 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1322 pressed_coordinate->width, pressed_coordinate->height);
1323 /* And if this SELFISH button was the last button pressed */
1324 if (touch_id == context->get_last_touch_device_id()) {
1325 windows->hide_window(windows->get_magnifier_window());
1330 /* If the focus came back into our SELFISH button */
1331 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH && pressed_context->state != BUTTON_STATE_PRESSED) {
1332 pressed_context->state = BUTTON_STATE_PRESSED;
1333 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1334 pressed_coordinate->width, pressed_coordinate->height);
1335 /* And if this SELFISH button was the last button pressed */
1336 if (touch_id == context->get_last_touch_device_id()) {
1337 sclboolean showMagnifier = check_magnifier_available(pressed_window, pressed_key, touch_id);
1339 if (showMagnifier) {
1340 windows->show_window(windows->get_magnifier_window());
1352 CSCLController::process_button_over_event(sclwindow window, sclint x, sclint y, sclbyte key_index)
1356 sclboolean ret = FALSE;
1358 CSCLUtils *utils = CSCLUtils::get_instance();
1359 CSCLEvents *events = CSCLEvents::get_instance();
1360 CSCLContext *context = CSCLContext::get_instance();
1361 CSCLWindows *windows = CSCLWindows::get_instance();
1362 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1363 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1365 SclButtonContext *button_context = NULL;
1367 const SclLayoutKeyCoordinate *coordinate = NULL;
1369 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1370 button_context = cache->get_cur_button_context(window, key_index);
1373 if(button_context && coordinate && feedback && utils && context && cache && events && windows) {
1374 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1375 sclboolean subLayoutMatch = TRUE;
1376 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1377 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1378 subLayoutMatch = FALSE;
1381 if ( x >= coordinate->x - coordinate->add_hit_left &&
1382 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
1383 y >= coordinate->y - coordinate->add_hit_top &&
1384 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
1388 SCLShiftState shift_index = context->get_shift_state();
1389 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1390 if (context->get_caps_lock_mode()) {
1391 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1394 const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1396 sclwindow highlighted_window = context->get_cur_highlighted_window();
1397 scl8 highlighted_key = context->get_cur_highlighted_key();
1398 SclButtonContext *cur_context = cache->get_cur_button_context(window, key_index);
1400 if(cur_context == NULL) {
1403 if (key_index != highlighted_key || window != highlighted_window ) {
1404 SECURE_LOGD("%d != %d || %p != %p", key_index, highlighted_key, window, highlighted_window);
1406 if (coordinate->key_type != KEY_TYPE_NONE) {
1407 if (context->get_tts_enabled()) {
1408 const sclchar *targetstr = coordinate->hint_string[shift_index][button_context->multikeyIdx];
1409 if (targetstr == NULL) {
1410 targetstr = coordinate->label[shift_index][0];
1412 if (targetstr == NULL) {
1413 targetstr = coordinate->key_value[shift_index][button_context->multikeyIdx];
1415 /*if(state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
1416 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ) {
1417 targetstr = coordinate->long_key_value;
1419 const sclchar *sayit = cache->find_substituted_string(targetstr);
1420 utils->play_tts(sayit);
1425 context->set_cur_highlighted_window(window);
1426 context->set_cur_highlighted_key(key_index);
1434 CSCLController::get_drag_key_modifier(sclint deltax, sclint deltay, sclfloat dist, sclboolean check_farthest,
1435 scltouchdevice touch_id, sclbyte extra_option) {
1439 SCLKeyModifier modifier;
1442 CSCLContext *context = CSCLContext::get_instance();
1443 SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1446 double theta = atan2(deltay , (deltax ? deltax : 1)); /* Avoid divide by 0 exception */
1447 sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
1448 SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
1449 if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS ||
1450 extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1451 extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN) { /* 8 directions */
1452 /* If the theta is below 0, the direction is upward since the y coordinate grows downward */
1453 /* The below angle values are customized for MoAKey, need to provide customizing API */
1454 DIRECTIONINFO info[] = {
1455 {-8 * (M_PI / 8), -7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1456 {-7 * (M_PI / 8), -5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_LEFT},
1457 {-5 * (M_PI / 8), -2.7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP},
1458 {-2.7 * (M_PI / 8), -1.5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_RIGHT},
1459 {-1.5 * (M_PI / 8), 1 * (M_PI / 8), KEY_MODIFIER_DIRECTION_RIGHT},
1460 { 1 * (M_PI / 8), 3 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_RIGHT},
1461 { 3 * (M_PI / 8), 5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN},
1462 { 5 * (M_PI / 8), 7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_LEFT},
1463 { 7 * (M_PI / 8), 8 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1465 for (size_t loop = 0; loop < sizeof(info) / sizeof(DIRECTIONINFO); loop++) {
1466 if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1467 key_modifier = info[loop].modifier;
1470 } else { /* 4 directions */
1471 /* If the state was dragging to one of 4 directions and the final release point is
1472 * far enough from inital press point, and the angle is in between out predefined angle value */
1473 if (extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE &&
1474 cur_drag_state != SCL_DRAG_STATE_NONE && cur_drag_state != SCL_DRAG_STATE_INVALID &&
1475 dist > SCL_DRAG_CURVE_RECOG_DIST &&
1476 ratio > (1 / SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) &&
1477 ratio < SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) {
1478 if (cur_drag_state == SCL_DRAG_STATE_DOWN) {
1479 if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_RIGHT;
1480 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_LEFT;
1482 if (cur_drag_state == SCL_DRAG_STATE_UP) {
1483 if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_RIGHT;
1484 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_LEFT;
1486 if (cur_drag_state == SCL_DRAG_STATE_LEFT) {
1487 if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_DOWN;
1488 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_UP;
1490 if (cur_drag_state == SCL_DRAG_STATE_RIGHT) {
1491 if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_DOWN;
1492 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_UP;
1495 DIRECTIONINFO info[] = {
1496 {-4 * (M_PI / 4), -3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1497 {-3 * (M_PI / 4), -1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_UP},
1498 {-1 * (M_PI / 4), 1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_RIGHT},
1499 { 1 * (M_PI / 4), 3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_DOWN},
1500 { 3 * (M_PI / 4), 4 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1502 for (size_t loop = 0; loop < sizeof(info) / sizeof(DIRECTIONINFO); loop++) {
1503 if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1504 key_modifier = info[loop].modifier;
1510 if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1511 extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_LONG) {
1512 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1513 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1514 key_modifier = (SCLKeyModifier)(key_modifier + 8); // Add LONG attribute;
1517 if (check_farthest || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
1518 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1519 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1520 key_modifier = (SCLKeyModifier)(key_modifier + 16); // Add RETURN attribute;
1525 return key_modifier;
1529 CSCLController::process_button_release_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1530 scltouchdevice touch_id, sclboolean actual_event)
1534 sclboolean ret = FALSE;
1535 sclboolean redraw = FALSE;
1536 sclboolean fireEvt = FALSE;
1537 SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1539 static sclwindow lastFiredWin = SCLWINDOW_INVALID;
1540 static sclbyte lastFiredKey = NOT_USED;
1542 CSCLUtils *utils = CSCLUtils::get_instance();
1543 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1544 CSCLWindows *windows = CSCLWindows::get_instance();
1545 CSCLContext *context = CSCLContext::get_instance();
1546 CSCLActionState *state = CSCLActionState::get_instance();
1547 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1548 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1550 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1551 PSclLayout sclres_layout = sclres_manager->get_layout_table();
1552 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
1553 assert(sclres_layout != NULL);
1554 assert(sclres_input_mode_configure != NULL);
1555 SclButtonContext *button_context = NULL;
1556 const SclLayoutKeyCoordinate *coordinate = NULL;
1559 button_context = cache->get_cur_button_context(window, key_index);
1560 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1563 const SclLayoutKeyCoordinate *targetCoordinate = NULL;
1565 if (utils && feedback && windows && context && state && handler && cache && button_context && coordinate) {
1566 scl8 savedInputMode = context->get_input_mode();
1568 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1569 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1572 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1573 /* When calling mouse_release, the seq order of current multitouch events will be changed,
1574 so we put all the multitouch events into a vector and use them afterwards for releasing */
1575 sclboolean finished = FALSE;
1577 sclint multi_touch_context_num = context->get_multi_touch_context_num();
1578 std::vector<SclUIEventDesc> multi_touch_events;
1579 for(loop = 0;loop < multi_touch_context_num;loop++) {
1580 SclUIEventDesc desc;
1581 context->get_multi_touch_event(loop, &desc);
1582 multi_touch_events.push_back(desc);
1584 for(loop = 0;loop < multi_touch_context_num && !finished;loop++) {
1585 SclUIEventDesc desc = multi_touch_events[loop];
1586 if (desc.touch_id != touch_id) {
1587 sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
1588 scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
1589 const SclLayoutKeyCoordinate *cur_pressed_coordinate =
1590 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
1591 if (cur_pressed_coordinate) {
1592 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1593 mouse_release(context->get_cur_moving_window(desc.touch_id),
1594 context->get_cur_moving_point(desc.touch_id).x,
1595 context->get_cur_moving_point(desc.touch_id).y,
1596 desc.touch_id, FALSE);
1606 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1607 sclint thresholdX = 0;
1608 sclint thresholdY = 0;
1610 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1611 thresholdX = utils->get_scaled_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1612 thresholdY = utils->get_scaled_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1616 /* Check if the pressed button's type is directional button */
1617 if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1619 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1621 sclboolean check_farthest = FALSE;
1626 /* If the buttontype is RELATIVE_DIRECTION, get the distance from last move point */
1627 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1628 startx = context->get_prev_moving_point(touch_id).x;
1629 starty = context->get_prev_moving_point(touch_id).y;
1631 startx = context->get_cur_pressed_point(touch_id).x;
1632 starty = context->get_cur_pressed_point(touch_id).y;
1635 sclint deltax = x - startx;
1636 sclint deltay = y - starty;
1638 sclfloat dist = utils->get_distance(x, y, startx, starty);
1639 sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
1640 if (coordinate->is_side_button) {
1641 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
1643 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1644 direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
1646 if (context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN &&
1647 coordinate->button_type != BUTTON_TYPE_RELATIVE_DIRECTION) {
1648 if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
1649 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
1650 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
1651 deltax = context->get_farthest_move_point(touch_id).x - context->get_cur_pressed_point(touch_id).x;
1652 deltay = context->get_farthest_move_point(touch_id).y - context->get_cur_pressed_point(touch_id).y;
1653 dist = utils->get_distance(context->get_farthest_move_point(touch_id), context->get_cur_pressed_point(touch_id));
1654 check_farthest = TRUE;
1657 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1658 key_modifier = context->get_cur_key_modifier(touch_id);
1659 } else if (dist > direction_recog_dist) {
1660 key_modifier = get_drag_key_modifier(deltax, deltay, dist, check_farthest, touch_id, coordinate->extra_option);
1666 /* First check if this button is enabled in current active sublayout */
1667 sclboolean subLayoutMatch = TRUE;
1668 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1669 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1670 subLayoutMatch = FALSE;
1673 /* Check if the event occured inside this button's rectangle */
1674 if ( x >= coordinate->x - coordinate->add_hit_left - thresholdX &&
1675 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX &&
1676 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1677 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1684 feedback->button_released(window, key_index);
1686 /* If this button's index is the same as the one initially pressed */
1687 if (pressed_window == window && pressed_key == key_index) {
1689 targetCoordinate = coordinate;
1691 const SclLayoutKeyCoordinate *pressed_coordinate =
1692 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1694 if (pressed_coordinate) {
1695 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1697 targetCoordinate = pressed_coordinate;
1705 /* In case of mode change buttons, event should be fired only when it was pressed lastly */
1707 if (coordinate->key_type == KEY_TYPE_MODECHANGE) {
1708 if (touch_id != context->get_last_touch_device_id()) {
1714 /* If this key's modifier is LONGKEY, this means the event is already fired so skip this one */
1715 if (context->get_cur_key_modifier(touch_id) == KEY_MODIFIER_LONGKEY) {
1719 /* Don't fire any events if we're in longkey state */
1720 if (state->get_cur_action_state() != ACTION_STATE_BASE_LONGKEY &&
1721 state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
1722 state->get_cur_action_state() != ACTION_STATE_POPUP_LONGKEY &&
1723 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY) {
1724 /* An event occured? */
1726 if (targetCoordinate) {
1727 SCLShiftState shift_index = context->get_shift_state();
1728 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1729 if (context->get_caps_lock_mode()) {
1730 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1733 SclUIEventDesc key_event_desc;
1734 key_event_desc.key_type = targetCoordinate->key_type;
1736 key_event_desc.event_type = EVENT_TYPE_RELEASE;
1737 key_event_desc.touch_id = touch_id;
1738 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1739 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1740 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1742 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1744 switch (targetCoordinate->button_type) {
1745 case BUTTON_TYPE_NORMAL:
1746 case BUTTON_TYPE_GRAB :
1747 case BUTTON_TYPE_SELFISH:
1748 case BUTTON_TYPE_DIRECTION :
1749 case BUTTON_TYPE_RELATIVE_DIRECTION: {
1750 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1751 if (pressed_context) {
1752 if (!(targetCoordinate->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1753 key_event_desc.key_value = targetCoordinate->key_value[shift_index][0];
1754 key_event_desc.key_event = targetCoordinate->key_event[shift_index][0];
1755 key_event_desc.key_modifier = key_modifier;
1756 handler->on_event_key_clicked(key_event_desc);
1761 case BUTTON_TYPE_MULTITAP:
1762 case BUTTON_TYPE_ROTATION: {
1763 if (targetCoordinate->button_type == BUTTON_TYPE_MULTITAP) {
1764 if (window == lastFiredWin && key_index == lastFiredKey) {
1765 key_modifier = KEY_MODIFIER_MULTITAP_REPEAT;
1767 key_modifier = KEY_MODIFIER_MULTITAP_START;
1770 key_modifier = KEY_MODIFIER_NONE;
1772 if (button_context->multikeyIdx < MAX_SIZE_OF_MULTITAP_CHAR) {
1773 key_event_desc.key_value = coordinate->key_value[shift_index][button_context->multikeyIdx];
1774 key_event_desc.key_event = coordinate->key_event[shift_index][button_context->multikeyIdx];
1775 key_event_desc.key_modifier = key_modifier;
1776 handler->on_event_key_clicked(key_event_desc);
1778 /* Check if the multikey index is in valid range, and increase by one */
1779 if (button_context->multikeyIdx >= MAX_SIZE_OF_MULTITAP_CHAR - 1) {
1780 button_context->multikeyIdx = 0;
1782 sclbyte orgindex = button_context->multikeyIdx;
1783 button_context->multikeyIdx = 0;
1784 if (targetCoordinate->key_value[shift_index][orgindex + 1]) {
1785 if (strlen(targetCoordinate->key_value[shift_index][orgindex + 1]) > 0) {
1786 button_context->multikeyIdx = orgindex + 1;
1792 case BUTTON_TYPE_DRAG : {
1795 case BUTTON_TYPE_TOGGLE : {
1796 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1797 if (pressed_context) {
1798 if (!(targetCoordinate->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1799 key_event_desc.key_value = targetCoordinate->key_value[shift_index][0];
1800 key_event_desc.key_event = targetCoordinate->key_event[shift_index][0];
1801 if (pressed_context->toggled) {
1802 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1804 key_event_desc.key_modifier = KEY_MODIFIER_TOGGLED;
1806 if (SCL_EVENT_PASS_ON == handler->on_event_key_clicked(key_event_desc)) {
1807 pressed_context->toggled = !(pressed_context->toggled);
1812 case BUTTON_TYPE_UIITEM: break;
1813 case MAX_BUTTON_TYPE: break;
1817 switch (coordinate->popup_type) {
1818 case POPUP_TYPE_BTN_RELEASE_POPUP:
1819 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE: {
1820 SCLDragState dragstate = context->get_cur_drag_state(touch_id);
1821 sclint popup_input_mode = NOT_USED;
1823 SclNotiPopupOpeningDesc desc;
1824 desc.ui_event_desc = &key_event_desc;
1826 if (scl_check_arrindex(dragstate, SCL_DRAG_STATE_MAX)) {
1827 desc.input_mode = coordinate->popup_input_mode[dragstate];
1828 popup_input_mode = sclres_manager->get_inputmode_id(coordinate->popup_input_mode[dragstate]);
1830 //if (!scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP)) {
1831 if (!scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE)) {
1832 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
1835 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
1836 popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
1837 SCLDisplayMode display_mode = context->get_display_mode();
1839 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
1840 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
1841 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
1842 sclshort popupLayoutId =
1843 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
1844 if (popupLayoutId == NOT_USED){
1845 // deal with NOT_USED
1846 LOGD("popupLayoutID is not used.");
1848 SclLayout *layout = NULL;
1850 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
1851 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
1852 layout = &sclres_layout[popupLayoutId];
1855 SclRectangle popupRect;
1856 SclRectangle baseWndRect;
1857 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
1858 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
1859 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
1861 //popupRect.width = utils->get_scale_x(layout->width);
1862 //popupRect.height= utils->get_scale_y(layout->height);
1863 popupRect.width = layout->width;
1864 popupRect.height= layout->height;
1866 /* Let's make sure this popup window does not go beyond the screen area */
1867 sclint scr_w, scr_h;
1868 utils->get_screen_resolution(&scr_w, &scr_h);
1870 if (popupRect.x + popupRect.width > scr_w) {
1871 popupRect.x = scr_w - popupRect.width;
1873 if (popupRect.y + popupRect.height > scr_h) {
1874 popupRect.y = scr_h - popupRect.height;
1877 SclWindowOpener opener;
1878 opener.window = window;
1879 opener.key = key_index;
1881 sclwindow popup_window = windows->open_popup(
1886 coordinate->popup_type,
1887 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
1888 sclres_input_mode_configure[popup_input_mode].use_dim_window,
1889 coordinate->extract_offset_x,
1890 coordinate->extract_offset_y,
1891 sclres_input_mode_configure[popup_input_mode].timeout
1894 SclNotiPopupOpenedDesc opened_desc;
1895 opened_desc.ui_event_desc = &key_event_desc;
1896 opened_desc.input_mode = desc.input_mode;
1897 opened_desc.window = popup_window;
1898 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
1900 windows->hide_window(windows->get_magnifier_window());
1901 _play_tts_for_input_mode_name(popup_input_mode);
1907 case POPUP_TYPE_AUTO_POPUP:
1908 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG:
1909 case POPUP_TYPE_NONE:
1910 /* Nothing to do in here */
1912 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE: break;
1913 case POPUP_TYPE_BTN_LONGPRESS_POPUP: break;
1914 case MAX_POPUP_TYPE: break;
1919 lastFiredWin = window;
1920 lastFiredKey = key_index;
1923 if (targetCoordinate) {
1924 SCLShiftState shift_index = context->get_shift_state();
1925 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1926 if (context->get_caps_lock_mode()) {
1927 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1930 SclUIEventDesc key_event_desc;
1931 key_event_desc.key_type = targetCoordinate->key_type;
1933 key_event_desc.key_value = targetCoordinate->key_value[shift_index][button_context->multikeyIdx];
1934 key_event_desc.key_event = targetCoordinate->key_event[shift_index][button_context->multikeyIdx];
1935 key_event_desc.key_modifier = key_modifier;
1937 key_event_desc.event_type = EVENT_TYPE_RELEASE;
1938 key_event_desc.touch_id = touch_id;
1939 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1940 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1941 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1943 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1945 SCLEventReturnType evt = handler->on_event_drag_state_changed(key_event_desc);
1949 /* If this button was pressed, initialize the button context regardless of event */
1950 if (button_context->state == BUTTON_STATE_PRESSED) {
1951 /* But, if this button should be in pressed state in other multitouch id, do not initialize */
1952 sclboolean found = FALSE;
1953 for(sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1954 SclUIEventDesc desc;
1955 context->get_multi_touch_event(loop, &desc);
1956 if (desc.touch_id != touch_id) {
1957 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(desc.touch_id);
1958 if (multi_touch_context) {
1959 if (multi_touch_context->cur_pressed_window == window &&
1960 multi_touch_context->cur_pressed_key == key_index) {
1967 button_context->state = BUTTON_STATE_NORMAL;
1972 /* If this button needs to be redrawn */
1974 #ifdef DIRECTLY_DRAW_ON_EVENTS
1975 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1977 builder->draw_button(window, NULL, key_index, button_context->state, TRUE);
1980 if (savedInputMode == context->get_input_mode()) {
1981 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1992 CSCLController::mouse_press(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
1995 sclboolean ret = FALSE;
1997 if (m_input_events_disabled) return FALSE;
1999 //utils->log("Controller::mouse_press : %d %d\n", x, y);
2001 /* Adjust x,y coordinate by touch offset */
2002 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2004 CSCLContext *context = CSCLContext::get_instance();
2005 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2006 CSCLActionState *state = CSCLActionState::get_instance();
2007 CSCLWindows *windows = CSCLWindows::get_instance();
2008 CSCLUtils *utils = CSCLUtils::get_instance();
2010 sclint button_index = NOT_USED;
2011 SclWindowContext *window_context = NULL;
2013 const SclLayout *layout = cache->get_cur_layout(window);
2015 x += layout->mouse_manipulate_x;
2016 y += layout->mouse_manipulate_y;
2018 window_context = windows->get_window_context(window);
2019 /* If the dim window is virtual and currently active, let's just skip this event */
2020 if (windows->is_base_window(window)) {
2021 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2022 if (dim_window_context) {
2023 LOGD ("dim window is_virtual:%d, hidden:%d", dim_window_context->is_virtual, dim_window_context->hidden);
2024 if (/*dim_window_context->is_virtual &&*/ !(dim_window_context->hidden)) {
2025 window = windows->get_dim_window();
2026 window_context = dim_window_context;
2032 if (cache && state && windows && context && window_context) {
2033 SCLDisplayMode display_mode = context->get_display_mode();
2034 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2035 PSclDefaultConfigure default_configure = NULL;
2036 if (sclres_manager) {
2037 default_configure = sclres_manager->get_default_configure();
2039 if (default_configure) {
2040 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2043 sclboolean isSubEvent = FALSE;
2044 if (context->get_multi_touch_context_num() > 0) {
2045 SclUIEventDesc desc;
2046 context->get_multi_touch_event(0, &desc);
2047 sclwindow pressed_window = context->get_cur_pressed_window(desc.touch_id);
2048 scl8 pressed_key = context->get_cur_pressed_key(desc.touch_id);
2049 SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2051 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_GRAB_SUB_EVENTS) {
2053 utils->play_vibration(DEFAULT_VIBRATION_STYLE, DEFAULT_VIBRATION_DURATION);
2057 context->create_multi_touch_context(touch_id, isSubEvent);
2058 context->set_cur_pressed_window(touch_id, window);
2059 context->set_cur_pressed_point(touch_id, x, y);
2060 context->set_cur_pressed_time(touch_id);
2061 context->set_cur_moving_window(touch_id, window);
2062 context->set_cur_moving_point(touch_id, x, y);
2063 context->set_last_touch_device_id(touch_id);
2064 context->set_cur_drag_state(touch_id, SCL_DRAG_STATE_NONE);
2065 context->set_cur_key_modifier(touch_id, KEY_MODIFIER_NONE);
2066 for(sclint labelidx = 0;labelidx < MAX_SIZE_OF_LABEL_FOR_ONE;labelidx++) {
2067 context->set_custom_magnifier_label(touch_id, labelidx, NULL);
2070 /* If there is postponed update of button, update it now */
2071 CSCLEvents *events = CSCLEvents::get_instance();
2072 sclwindow last_win = context->get_last_pressed_window();
2073 scl8 last_key = context->get_last_pressed_key();
2074 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2075 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2077 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2080 context->set_prev_pressed_window(touch_id, SCLWINDOW_INVALID);
2081 context->set_prev_pressed_key(touch_id, NOT_USED);
2082 context->set_prev_drag_state(touch_id, SCL_DRAG_STATE_NONE);
2083 context->set_prev_moving_point(touch_id, x, y);
2085 /* Destroy key related timers */
2086 events->destroy_timer(SCL_TIMER_BUTTON_DELAY);
2087 events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2088 events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2089 events->destroy_timer(SCL_TIMER_LONGKEY);
2090 events->destroy_timer(SCL_TIMER_REPEATKEY);
2092 /* Do what has to be done when mouse gets pressed */
2093 handle_engine_signal(SCL_SIG_MOUSE_PRESS, window);
2095 /* Adjust event x and y positions as relative position to the virtual window */
2096 if (window_context) {
2097 /*if (window_context->isVirtual) {
2098 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2099 if (base_window_context) {
2100 x -= (window_context->x - base_window_context->x);
2101 y -= (window_context->y - base_window_context->y);
2107 sclboolean process_finished = FALSE;
2109 /* Iterate all the buttons and inform the event */
2110 sclboolean ended = FALSE;
2111 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2112 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
2113 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2114 if (button_context && coordinate) {
2115 if (!(button_context->used)) {
2117 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2118 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2119 if (process_button_pressed_event(window, x, y, loop, touch_id, actual_event)) {
2120 if (windows->is_base_window(window)) {
2121 state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2123 state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2125 button_index = loop;
2132 /* For covering a missing area about 1 pixel */
2134 for (int loop = 0;loop < MAX_KEY;loop++) {
2135 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
2136 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2137 if (button_context && coordinate) {
2138 if (!(button_context->used)) {
2140 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2141 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2142 if (process_button_pressed_event(window, x+1, y+1, loop, touch_id, actual_event)) {
2143 if (windows->is_base_window(window)) {
2144 state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2146 state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2148 button_index = loop;
2158 if (windows->is_base_window(window)) {
2159 process_finished = TRUE;
2160 } else if (button_index != NOT_USED) {
2161 process_finished = TRUE;
2163 const SclLayout *layout = cache->get_cur_layout(window);
2165 if (layout->use_sw_background && layout->bg_color.a == 0) {
2166 /* If we could not find appropriate button in this popup window and the popup is transparent */
2167 SclWindowContext *base_window_context =
2168 windows->get_window_context(windows->get_base_window());
2169 if (base_window_context) {
2170 x = (window_context->geometry.x + x - base_window_context->geometry.x);
2171 y = (window_context->geometry.y + y - base_window_context->geometry.y);
2173 window = windows->get_base_window();
2175 process_finished = TRUE;
2178 process_finished = TRUE;
2181 } while (!process_finished);
2184 sclwindow skip_window = window;
2185 if (ret && button_index != NOT_USED) {
2186 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, button_index);
2188 sclboolean dont_close_popup = FALSE;
2189 if (coordinate->dont_close_popup) {
2190 dont_close_popup = TRUE;
2192 /* If the button's popup type is drag type, the opened popup could be the one opened by this press event */
2193 if (coordinate->popup_type == POPUP_TYPE_BTN_PRESS_POPUP_DRAG) {
2194 /* Check the opened popup was opened by this button */
2195 sclwindow popupwin = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2196 SclWindowContext *popup_window_context = windows->get_window_context(popupwin);
2197 if (popup_window_context) {
2198 SclWindowOpener opener = popup_window_context->opener;
2199 if (opener.window == window && opener.key == button_index) {
2200 dont_close_popup = TRUE;
2204 if (dont_close_popup) {
2205 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2209 windows->close_all_popups(skip_window);
2211 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
2212 if (!(windows->is_base_window(window))) {
2213 if (window_context->timeout > 0) {
2214 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2215 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, window_context->timeout, 0, TRUE);
2217 } else if (skip_window != window) { /* Or the pressed button has dont_close_popup property, reset POPUP_TIMEOUT timer */
2218 //SclWindowContext *skip_window_context = windows->get_window_context(skip_window, FALSE);
2219 SclWindowContext *skip_window_context = windows->get_window_context(skip_window);
2220 if (skip_window_context) {
2221 if (skip_window_context->timeout > 0) {
2222 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2223 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, skip_window_context->timeout, 0, TRUE);
2233 CSCLController::mouse_release(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2236 sclboolean ret = FALSE;
2238 //if (m_input_events_disabled) return FALSE;
2240 //utils->log("Controller::mouse_release : %d %d\n", x, y);
2241 /* Adjust x,y coordinate by touch offset */
2242 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2244 CSCLContext *context = CSCLContext::get_instance();
2245 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2246 CSCLActionState *state = CSCLActionState::get_instance();
2247 CSCLWindows *windows = CSCLWindows::get_instance();
2248 CSCLUtils *utils = CSCLUtils::get_instance();
2249 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2250 CSCLEvents *events = CSCLEvents::get_instance();
2252 sclint button_index = NOT_USED;
2254 if (cache && state && windows && context && utils && handler && events &&
2255 context->find_multi_touch_context(touch_id)) {
2256 const SclLayout *layout = cache->get_cur_layout(window);
2258 x += layout->mouse_manipulate_x;
2259 y += layout->mouse_manipulate_y;
2262 sclwindow skip_window = SCLWINDOW_INVALID;
2263 SCLDisplayMode display_mode = context->get_display_mode();
2265 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2266 PSclDefaultConfigure default_configure = NULL;
2267 if (sclres_manager) {
2268 default_configure = sclres_manager->get_default_configure();
2270 if (default_configure) {
2271 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2274 context->set_cur_moving_window(touch_id, SCLWINDOW_INVALID);
2276 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2277 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2278 //SclWindowContext *window_context = windows->get_window_context(window, TRUE);
2279 SclWindowContext *window_context = windows->get_window_context(window);
2280 /* Adjust event x and y positions as relative position to the virtual window */
2281 if (window_context) {
2282 /*if (window_context->isVirtual) {
2283 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2284 if (base_window_context) {
2285 x -= (window_context->x - base_window_context->x);
2286 y -= (window_context->y - base_window_context->y);
2289 /* If the dim window is virtual and currently active, consider base window's event is occured in dim window */
2290 if (windows->is_base_window(window)) {
2291 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2292 if (dim_window_context) {
2293 if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2294 window = windows->get_dim_window();
2295 window_context = dim_window_context;
2301 /* Iterate all the buttons and inform the event */
2302 sclboolean ended = FALSE;
2304 /* FIXME : The routine below seems to be removed, which was originally requested by Vodafone,
2305 * to slow down the speed of repeat key right before stopping repeatkey event */
2306 /* if (state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY) {
2307 if (m_key_repeated_num > 10) {
2309 process_button_repeat_pressed_event(pressed_window, pressed_key, touch_id);
2314 if (context->get_cur_pressed_window(touch_id) == window) {
2315 if (abs(context->get_cur_pressed_point(touch_id).x - x) > utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD) ||
2316 abs(context->get_cur_pressed_point(touch_id).y - y) > utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD) )
2318 struct timeval t0 = context->get_cur_pressed_time(touch_id);
2320 gettimeofday(&t1, NULL);
2322 etime = ((t1.tv_sec * 1000000 + t1.tv_usec) - (t0.tv_sec * 1000000 + t0.tv_usec))/1000.0;
2323 if (etime < SCL_FLICK_GESTURE_RECOG_TIME) {
2324 SCLDragType drag_type = DRAG_NONE;
2325 if (x > context->get_cur_pressed_point(touch_id).x + utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2326 drag_type = DRAG_RIGHT;
2328 if (x < context->get_cur_pressed_point(touch_id).x - utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2329 drag_type = DRAG_LEFT;
2331 if (y > context->get_cur_pressed_point(touch_id).y + utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2332 drag_type = DRAG_DOWN;
2334 if (y < context->get_cur_pressed_point(touch_id).y - utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2335 drag_type = DRAG_UP;
2337 SclNotiGestureFlickDesc desc;
2338 SclUIEventDesc ui_event_desc;
2339 ui_event_desc.key_value = NULL;
2340 ui_event_desc.key_event = NOT_USED;
2341 ui_event_desc.key_modifier = KEY_MODIFIER_NONE;
2342 ui_event_desc.event_type = EVENT_TYPE_RELEASE;
2343 ui_event_desc.touch_id = touch_id;
2344 ui_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2345 ui_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2346 ui_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2347 ui_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2348 desc.ui_event_desc = &ui_event_desc;
2349 desc.drag_type = drag_type;
2350 if (handler->on_event_notification(SCL_UINOTITYPE_GESTURE_FLICK, &desc)) {
2357 /* FIXME : We should consider this kind of action in general manner, not only specific to autopopup */
2358 /* And also, this kind of implementation only selects button that was highlighted at least once. */
2360 //SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window, FALSE);
2361 SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window);
2362 if (pressed_window_context) {
2363 utils->log("PRESSED CTX : %p %d %d\n", pressed_window,
2364 pressed_window_context->geometry.x, pressed_window_context->geometry.y);
2365 //if (pressedCtx->popuptype == POPUP_TYPE_AUTO_POPUP) {
2366 sclboolean grab_event = FALSE;
2367 const SclLayout *pressed_layout = cache->get_cur_layout(pressed_window);
2368 if (pressed_layout) {
2369 if (pressed_layout->style == LAYOUT_STYLE_POPUP_GRAB) {
2372 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
2374 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
2375 sclboolean in_grab_area = TRUE;
2376 if (pressed_layout->add_grab_left != NOT_USED &&
2377 x < (pressed_window_context->geometry.x - pressed_layout->add_grab_left)) {
2378 in_grab_area = FALSE;
2380 if (pressed_layout->add_grab_right != NOT_USED &&
2381 x > (pressed_window_context->geometry.x + pressed_window_context->geometry.width
2382 + pressed_layout->add_grab_right)) {
2383 in_grab_area = FALSE;
2385 if (pressed_layout->add_grab_top != NOT_USED &&
2386 y < (pressed_window_context->geometry.y - pressed_layout->add_grab_top)) {
2387 in_grab_area = FALSE;
2389 if (pressed_layout->add_grab_bottom != NOT_USED &&
2390 y > (pressed_window_context->geometry.y + pressed_window_context->geometry.height
2391 + pressed_layout->add_grab_bottom)) {
2392 in_grab_area = FALSE;
2395 SclLayoutKeyCoordinate *coord = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2397 x = coord->x + (coord->width / 2);
2398 y = coord->y + (coord->height / 2);
2400 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2401 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, loop);
2402 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2403 if (button_context && coordinate) {
2404 if (!(button_context->used)) {
2406 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2407 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2408 if (process_button_release_event(pressed_window, x, y, loop, touch_id, actual_event)) {
2422 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2423 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2425 /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2426 /* Ignore base window's release event if a popup window is opened */
2427 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2428 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2429 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2430 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2431 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2432 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2433 if (windows->is_base_window(window)) {
2435 /* In case of direction button, the release event on other window should be processed */
2436 if (coordinate && window_context && pressed_window_context) {
2437 if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2438 sclint relx = (window_context->geometry.x + x) - pressed_window_context->geometry.x;
2439 sclint rely = (window_context->geometry.y + y) - pressed_window_context->geometry.y;
2440 if (process_button_release_event(pressed_window, relx, rely, pressed_key, touch_id, actual_event)) {
2441 button_index = pressed_key;
2443 x = coordinate->x + (coordinate->width / 2);
2444 y = coordinate->y + (coordinate->height / 2);
2445 skip_window = pressed_window;
2452 sclboolean process_finished = FALSE;
2454 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(touch_id);
2455 if (multi_touch_context) {
2456 if (!(multi_touch_context->is_sub_event)) {
2457 /* First check if the event occured in pressed key's threshold area */
2458 if (button_context && coordinate && !ended) {
2459 if (button_context->used && button_context->state != BUTTON_STATE_DISABLED) {
2460 if (process_button_release_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
2461 button_index = pressed_key;
2463 x = coordinate->x + (coordinate->width / 2);
2464 y = coordinate->y + (coordinate->height / 2);
2468 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2469 SclButtonContext *cur_context = cache->get_cur_button_context(window, loop);
2470 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2471 if (cur_context && cur_coordinate) {
2472 if (!(cur_context->used)) {
2474 } else if (cur_context->state != BUTTON_STATE_DISABLED &&
2475 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
2476 if (window != pressed_window || loop != pressed_key) {
2477 if (process_button_release_event(window, x, y, loop, touch_id, actual_event)) {
2478 button_index = loop;
2486 process_finished = TRUE;
2488 SclUIEventDesc key_event_desc;
2489 key_event_desc.key_value = NULL;
2490 key_event_desc.key_event = NOT_USED;
2491 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
2492 key_event_desc.event_type = EVENT_TYPE_NONE;
2493 key_event_desc.touch_id = touch_id;
2494 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2495 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2496 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2498 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2500 handler->on_event_key_clicked(key_event_desc);
2504 /* For covering a missing area about 1 pixel */
2508 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2509 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2510 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2511 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2512 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2513 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2514 if (windows->is_base_window(window)) {
2519 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2520 SclButtonContext *cur_context = cache->get_cur_button_context(window, loop);
2521 if (cur_context && coordinate) {
2522 if (!(cur_context->used)) {
2525 } else if (cur_context->state != BUTTON_STATE_DISABLED &&
2526 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2527 if (process_button_release_event(window, x+1, y+1, loop, touch_id)) {
2528 button_index = loop;
2536 if (windows->is_base_window(window)) {
2537 process_finished = TRUE;
2538 } else if (button_index != NOT_USED) {
2539 process_finished = TRUE;
2541 if (layout && layout->use_sw_background && layout->bg_color.a == 0) {
2542 /* If we could not find appropriate button in this popup window and the popup is transparent */
2543 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2544 if (base_window_context && window_context) {
2545 x = (window_context->geometry.x + x - base_window_context->geometry.x);
2546 y = (window_context->geometry.y + y - base_window_context->geometry.y);
2548 window = windows->get_base_window();
2550 process_finished = TRUE;
2553 } while (!process_finished);
2555 if (windows->is_base_window(window)) {
2556 state->set_cur_action_state(ACTION_STATE_BASE_INIT);
2558 state->set_cur_action_state(ACTION_STATE_POPUP_INIT);
2561 /* Restore previously pressed button's context and redraw it */
2562 if (button_context && coordinate) {
2563 button_context->state = BUTTON_STATE_NORMAL;
2564 /* Commented below line to postpone some of the feedback for releasing */
2565 //windows->update_window(pressed_window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2568 /* If there is postponed update of button, update it now */
2569 sclwindow last_win = context->get_last_pressed_window();
2570 scl8 last_key = context->get_last_pressed_key();
2571 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2572 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2574 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2578 /* To postpone some of the feedback for releasing */
2579 context->set_last_pressed_key(context->get_cur_pressed_key(touch_id));
2580 context->set_last_pressed_window(context->get_cur_pressed_window(touch_id));
2582 /* Do what has to be done when mouse gets released */
2583 sclboolean signaled = FALSE;
2585 switch (coordinate->popup_type) {
2586 case POPUP_TYPE_BTN_RELEASE_POPUP:
2587 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
2588 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
2589 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
2591 /* Fix me : We should consider z-order */
2592 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2593 handle_engine_signal(SCL_SIG_MOUSE_RELEASE, skip_window);
2597 case POPUP_TYPE_NONE: break;
2598 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: break;
2599 case POPUP_TYPE_AUTO_POPUP: break;
2600 case MAX_POPUP_TYPE: break;
2605 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
2606 window_context = windows->get_window_context(window);
2607 if (window_context) {
2608 if (window_context->popup_type == POPUP_TYPE_BTN_RELEASE_POPUP ||
2609 window_context->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP) {
2610 /* Don't close window if the clicked button is a child of ReleasePopup window */
2611 skip_window = window;
2612 handle_engine_signal(SCL_SIG_MOUSE_RELEASE, window);
2617 handle_engine_signal(SCL_SIG_MOUSE_RELEASE);
2621 context->set_cur_pressed_key(touch_id, NOT_USED);
2622 context->set_cur_pressed_window(touch_id, SCLWINDOW_INVALID);
2624 if (ret && button_index != NOT_USED) {
2625 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, button_index);
2626 if (cur_coordinate) {
2627 if (cur_coordinate->dont_close_popup) {
2628 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2632 if (pressed_window == windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP)) {
2633 if (pressed_window_context) {
2634 if (pressed_window_context->popup_type != POPUP_TYPE_BTN_RELEASE_POPUP_ONCE &&
2635 pressed_window_context->popup_type != POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE &&
2636 pressed_window_context->popup_type != POPUP_TYPE_AUTO_POPUP &&
2637 pressed_window_context->popup_type != POPUP_TYPE_BTN_PRESS_POPUP_DRAG)
2639 skip_window = pressed_window;
2644 windows->close_all_popups(skip_window);
2646 /* Destroy key related timers */
2647 events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2648 events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2649 events->destroy_timer(SCL_TIMER_LONGKEY);
2650 events->destroy_timer(SCL_TIMER_REPEATKEY);
2652 /* If there are more than 1 active multitouch ids, don't play button_delay trick */
2653 if (context->get_multi_touch_context_num() == 1) {
2654 /* To postpone some of the feedback for releasing */
2655 events->create_timer(SCL_TIMER_BUTTON_DELAY, m_button_delay_duration, 0);
2657 last_win = context->get_last_pressed_window();
2658 last_key = context->get_last_pressed_key();
2660 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2661 const SclLayoutKeyCoordinate* last_coordinate = cache->get_cur_layout_key_coordinate(last_win, last_key);
2662 if (last_coordinate) {
2663 windows->update_window(last_win,
2664 last_coordinate->x, last_coordinate->y, last_coordinate->width, last_coordinate->height);
2668 windows->hide_window(windows->get_magnifier_window());
2669 context->set_last_pressed_window(SCLWINDOW_INVALID);
2670 context->set_last_pressed_key(NOT_USED);
2675 if (touch_id == context->get_last_touch_device_id()) {
2676 context->set_last_touch_device_id(SCLTOUCHDEVICE_INVALID);
2678 context->destroy_multi_touch_context(touch_id);
2684 SCLDragState get_drag_state(sclint deltax, sclint deltay)
2686 SCLDragState ret = SCL_DRAG_STATE_MAX;
2688 sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
2689 /* If tan(theta) is smaller than our predefined value */
2690 if (ratio <= (1 / SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE)) {
2692 ret = SCL_DRAG_STATE_RIGHT;
2694 ret = SCL_DRAG_STATE_LEFT;
2696 } /* If tan(theta) is bigger than our predefined value */
2697 else if (ratio >= SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE) {
2699 ret = SCL_DRAG_STATE_DOWN;
2701 ret = SCL_DRAG_STATE_UP;
2704 ret = SCL_DRAG_STATE_INVALID;
2711 CSCLController::mouse_move(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2714 sclboolean ret = FALSE;
2716 if (m_input_events_disabled) return FALSE;
2718 //utils->log("Controller::mouse_move : %d %d\n", x, y);
2720 /* Adjust x,y coordinate by touch offset */
2721 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2723 CSCLContext *context = CSCLContext::get_instance();
2724 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2725 CSCLActionState *state = CSCLActionState::get_instance();
2726 CSCLWindows *windows = CSCLWindows::get_instance();
2727 CSCLEvents *events = CSCLEvents::get_instance();
2728 CSCLUtils *utils = CSCLUtils::get_instance();
2729 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2730 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2731 PSclModifierDecoration sclres_modifier_decoration = sclres_manager->get_modifier_decoration_table();
2732 assert(sclres_modifier_decoration != NULL);
2734 if (cache && state && windows && context && utils && adjustment && sclres_manager) {
2735 const SclLayout *layout = cache->get_cur_layout(window);
2737 x += layout->mouse_manipulate_x;
2738 y += layout->mouse_manipulate_y;
2741 if (!(context->find_multi_touch_context(touch_id))) return FALSE;
2743 PSclDefaultConfigure default_configure = sclres_manager->get_default_configure();
2744 if (default_configure) {
2745 SCLDisplayMode display_mode = context->get_display_mode();
2746 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2749 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
2750 SclWindowContext *window_context = windows->get_window_context(window);
2751 /* Adjust event x and y positions as relative position to the virtual window */
2752 if (window_context) {
2753 /*if (window_context->isVirtual) {
2754 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2755 if (base_window_context) {
2756 x -= (window_context->x - base_window_context->x);
2757 y -= (window_context->y - base_window_context->y);
2760 /* If the dim window is virtual and currently active, let's just skip this event */
2761 if (windows->is_base_window(window)) {
2762 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2763 if (dim_window_context) {
2764 if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2769 /* If the pressed event was occured in dim window, let's just skip this move event */
2770 if (context->get_last_pressed_window() == windows->get_dim_window()) {
2775 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2776 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2777 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2778 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2780 /* If the multitouch type is SETTLE_PREVIOUS and is not the last touch device, let's ignore move events */
2782 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
2783 if (context->get_last_touch_device_id() != touch_id) {
2789 context->set_cur_moving_point(touch_id, x, y);
2790 context->set_cur_moving_window(touch_id, window);
2792 /* If in longkey state, do not process, just return */
2793 if (state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
2794 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
2795 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
2796 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY) {
2799 /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2800 /* And if the event occured in popup window, don't come back to base window */
2801 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2802 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2803 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2804 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2805 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2806 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2807 if (windows->is_base_window(window)) {
2812 /* FIXME : Add a condition to skip this code if longkey timer is not active */
2813 /* If the mouse has moved out of threshold value of longkey keypress area, destroy longkey timer */
2814 if (m_long_key_cancel_distance > 0) {
2815 sclfloat dist = utils->get_distance(x, y,
2816 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2817 if (m_long_key_cancel_distance < dist) {
2818 events->destroy_timer(SCL_TIMER_LONGKEY);
2822 if (windows->is_base_window(window)) {
2823 state->set_cur_action_state(ACTION_STATE_BASE_MOVING);
2825 state->set_cur_action_state(ACTION_STATE_POPUP_MOVING);
2828 /* Iterate all the buttons and inform the event */
2829 sclboolean ended = FALSE;
2831 /* Check farthest move point and update it */
2834 if (pressed_window != window) {
2835 //SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window, FALSE);
2836 SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window);
2837 if (window_context && pressed_window_context) {
2838 originx = (window_context->geometry.x - pressed_window_context->geometry.x) + x;
2839 originy = (window_context->geometry.y - pressed_window_context->geometry.y) + y;
2842 sclint startx = originx;
2843 sclint starty = originy;
2845 /* Check if we should recognize drag curve */
2847 startx = context->get_cur_pressed_point(touch_id).x;
2848 starty = context->get_cur_pressed_point(touch_id).y;
2849 sclint deltax = originx - startx;
2850 sclint deltay = originy - starty;
2851 sclfloat approximate_dist = utils->get_approximate_distance(originx, originy, startx, starty);
2853 sclboolean update_magnifier = FALSE;
2854 sclboolean drag_state_changed = FALSE;
2855 SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
2856 SCLDragState next_drag_state = SCL_DRAG_STATE_NONE;
2857 sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
2858 if (coordinate->is_side_button) {
2859 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
2862 if (coordinate->button_type == BUTTON_TYPE_DIRECTION) {
2863 /* Do not check farthest move point if current drag state is SCL_DRAG_STATE_RETURN */
2864 if (context->get_cur_drag_state(touch_id) != SCL_DRAG_STATE_RETURN) {
2865 if (approximate_dist > context->get_farthest_move_dist(touch_id)) {
2866 context->set_farthest_move_point(touch_id, originx, originy);
2870 if (cur_drag_state == SCL_DRAG_STATE_RETURN) {
2871 direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_RETURN;
2872 } else if (cur_drag_state != SCL_DRAG_STATE_NONE) {
2873 direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_OTHER;
2875 if (approximate_dist > direction_recog_dist) {
2876 next_drag_state = get_drag_state(deltax, deltay);
2877 /* Disable longkey if dragging is recognized */
2878 events->destroy_timer(SCL_TIMER_LONGKEY);
2880 if (cur_drag_state != next_drag_state) {
2881 drag_state_changed = TRUE;
2883 if (cur_drag_state == SCL_DRAG_STATE_NONE) {
2884 //if (nextDragState != SCL_DRAG_STATE_INVALID) {
2885 cur_drag_state = next_drag_state;
2887 } else if (cur_drag_state != next_drag_state) {
2888 if (next_drag_state == SCL_DRAG_STATE_NONE) {
2889 cur_drag_state = SCL_DRAG_STATE_RETURN;
2891 cur_drag_state = next_drag_state;
2895 context->set_cur_drag_state(touch_id, cur_drag_state);
2896 sclboolean check_farthest = FALSE;
2897 sclshort display = context->get_display_mode();
2898 if (!scl_check_arrindex(display, DISPLAYMODE_MAX)) display = 0;
2899 sclfloat dist = utils->get_distance(originx, originy,
2900 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2901 if (dist < direction_recog_dist && context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
2902 if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
2903 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
2904 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
2905 deltax = context->get_farthest_move_point(touch_id).x -
2906 context->get_cur_pressed_point(touch_id).x;
2907 deltay = context->get_farthest_move_point(touch_id).y -
2908 context->get_cur_pressed_point(touch_id).y;
2909 dist = utils->get_distance(context->get_farthest_move_point(touch_id),
2910 context->get_cur_pressed_point(touch_id));
2911 check_farthest = TRUE;
2914 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist,
2915 check_farthest, touch_id, coordinate->extra_option);
2916 if (dist > direction_recog_dist) {
2917 context->set_cur_key_modifier(touch_id, key_modifier);
2919 /* If this button needs to be decorated when dragged */
2920 if (coordinate->modifier_decorator) {
2921 const SclModifierDecoration *decoration = NULL;
2923 /*if (scl_check_arrindex(coordinate->modifier_decorator,
2924 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
2925 scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
2926 if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
2927 if (sclres_modifier_decoration[decoration_id].valid) {
2928 decoration = &(sclres_modifier_decoration[decoration_id]);
2931 /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
2933 if (decoration->bg_image_path[display][key_modifier]) {
2934 windows->update_window(window,
2935 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2939 if (dist > direction_recog_dist) {
2940 SclUIEventDesc desc;
2941 SCLShiftState shift_index = context->get_shift_state();
2942 if (context->get_caps_lock_mode()) {
2943 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
2945 desc.key_type = coordinate->key_type;
2946 desc.key_value = coordinate->key_value[shift_index][0];
2947 desc.key_event = coordinate->key_event[shift_index][0];
2948 desc.event_type = EVENT_TYPE_MOVE;
2949 desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2950 desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2951 desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2952 desc.key_modifier = key_modifier;
2954 if (handler->on_event_drag_state_changed(desc) && context->get_magnifier_enabled()) {
2955 update_magnifier = TRUE;
2958 } else if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2959 if (cur_drag_state != SCL_DRAG_STATE_NONE) {
2960 startx = context->get_prev_moving_point(touch_id).x;
2961 starty = context->get_prev_moving_point(touch_id).y;
2962 approximate_dist = utils->get_approximate_distance(originx, originy, startx, starty);
2963 direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
2965 deltax = originx - startx;
2966 deltay = originy - starty;
2967 //printf("DIST : %f, RECOG : %f\n", dist, direction_recog_dist);
2968 if (approximate_dist > direction_recog_dist) {
2969 next_drag_state = get_drag_state(deltax, deltay);
2970 /* Disable longkey if dragging is recognized */
2971 events->destroy_timer(SCL_TIMER_LONGKEY);
2973 if (cur_drag_state != next_drag_state) {
2974 drag_state_changed = TRUE;
2976 if (next_drag_state != SCL_DRAG_STATE_NONE) {
2977 cur_drag_state = next_drag_state;
2979 context->set_cur_drag_state(touch_id, cur_drag_state);
2981 startx = context->get_farthest_move_point(touch_id).x;
2982 starty = context->get_farthest_move_point(touch_id).y;
2983 deltax = originx - startx;
2984 deltay = originy - starty;
2985 sclfloat dist_farthest = utils->get_approximate_distance(originx, originy, startx, starty);
2986 //printf("%d %d %d %d %f, %d %d\n", originx, originy, startx, starty, dist_farthest, cur_drag_state, next_drag_state);
2987 /* Let's see how much we are away from the last farthest point */
2988 sclfloat diffdir_recog_dist = SCL_DIRECTION_RELATIVE_DIFFDIR_RECOG_DIST * utils->get_smallest_scale_rate();
2989 /* If we moved certain amount from the point where direction changed, process drag state change routine */
2990 if (dist_farthest > diffdir_recog_dist || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_NONE) {
2991 sclshort display = context->get_display_mode();
2992 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist_farthest,
2993 FALSE, touch_id, coordinate->extra_option);
2994 context->set_cur_key_modifier(touch_id, key_modifier);
2995 /* If this button needs to be decorated when dragged */
2996 if (coordinate->modifier_decorator) {
2997 const SclModifierDecoration *decoration = NULL;
2999 /*if (scl_check_arrindex(coordinate->modifier_decorator,
3000 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
3001 scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
3002 if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
3003 if (sclres_modifier_decoration[decoration_id].valid) {
3004 decoration = &(sclres_modifier_decoration[decoration_id]);
3007 /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
3009 if (decoration->bg_image_path[display][key_modifier]) {
3010 windows->update_window(window,
3011 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3016 SclUIEventDesc desc;
3017 SCLShiftState shift_index = context->get_shift_state();
3018 if (context->get_caps_lock_mode()) {
3019 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
3021 desc.key_type = coordinate->key_type;
3022 desc.key_value = coordinate->key_value[shift_index][0];
3023 desc.key_event = coordinate->key_event[shift_index][0];
3024 desc.event_type = EVENT_TYPE_MOVE;
3025 desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
3026 desc.mouse_current_point = context->get_cur_moving_point(touch_id);
3027 desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
3028 desc.key_modifier = key_modifier;
3030 if (handler->on_event_drag_state_changed(desc) && context->get_magnifier_enabled()) {
3031 update_magnifier = TRUE;
3034 context->set_prev_moving_point(touch_id, originx, originy);
3036 if (drag_state_changed) {
3037 /* When the dragging direction changes, save the current position as farthest point for future comparison */
3038 context->set_farthest_move_point(touch_id, originx, originy);
3039 LOGD("SET_FARTHEST : %d %d %d", originx, originy, context->get_cur_drag_state(touch_id));
3043 if (update_magnifier) {
3044 PSclMagnifierWndConfigure magnifier_configure = NULL;
3045 if (sclres_manager) {
3046 magnifier_configure = sclres_manager->get_magnifier_configure();
3049 const SclLayout *base_layout = cache->get_cur_layout(windows->get_base_window());
3050 if (base_layout && magnifier_configure) {
3051 SclPoint zoomwinpos = {0,0};
3052 /* calculates x position to be set */
3053 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
3054 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
3056 /* calculates y position to be set */
3057 sclint scnWidth, scnHeight;
3058 utils->get_screen_resolution(&scnWidth, &scnHeight);
3060 zoomwinpos.y = coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
3061 if (window_context) {
3062 zoomwinpos.x += window_context->geometry.x;
3063 zoomwinpos.y += window_context->geometry.y;
3065 if (zoomwinpos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
3066 zoomwinpos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
3068 if (zoomwinpos.x > scnWidth +
3069 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
3070 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
3071 zoomwinpos.x = scnWidth +
3072 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
3073 magnifier_configure->width * utils->get_custom_scale_rate_x();
3075 zoomwinpos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
3077 zoomwinpos.x += coordinate->magnifier_offset_x;
3078 zoomwinpos.y += coordinate->magnifier_offset_y;
3079 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y);
3080 windows->show_window(windows->get_magnifier_window(), 0);
3085 sclboolean grab_event = FALSE;
3087 if (layout->style == LAYOUT_STYLE_POPUP_GRAB) {
3090 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
3091 if (grab_event && window_context) {
3092 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
3093 sclboolean in_grab_area = TRUE;
3094 if (layout->add_grab_left != NOT_USED && x < -(layout->add_grab_left)) {
3095 in_grab_area = FALSE;
3097 if (layout->add_grab_right != NOT_USED && x >
3098 (window_context->geometry.width + layout->add_grab_right)) {
3099 in_grab_area = FALSE;
3101 if (layout->add_grab_top != NOT_USED && y < -(layout->add_grab_top)) {
3102 in_grab_area = FALSE;
3104 if (layout->add_grab_bottom != NOT_USED && y >
3105 (window_context->geometry.height + layout->add_grab_bottom)) {
3106 in_grab_area = FALSE;
3109 float min_dist = (float)((unsigned int)(-1));
3110 int min_dist_index = NOT_USED;
3111 for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
3112 button_context = cache->get_cur_button_context(window, loop);
3113 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3114 if (button_context && cur_coordinate) {
3115 if (!(button_context->used)) {
3117 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3118 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
3119 float dist = utils->get_approximate_distance(x, y,
3120 cur_coordinate->x + (cur_coordinate->width / 2),
3121 cur_coordinate->y + (cur_coordinate->height / 2));
3122 if (dist < min_dist) {
3123 min_dist_index = loop;
3129 /* When we found the nearest button, generate this event on the button */
3130 if (min_dist_index != NOT_USED) {
3131 const SclLayoutKeyCoordinate *min_coordinate =
3132 cache->get_cur_layout_key_coordinate(window, min_dist_index);
3133 if (min_coordinate) {
3134 x = min_coordinate->x + (min_coordinate->width / 2);
3135 y = min_coordinate->y + (min_coordinate->height / 2);
3136 if (process_button_move_event(window, x, y, min_dist_index, touch_id, actual_event)) {
3143 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(touch_id);
3144 if (multi_touch_context) {
3145 sclint button_index = NOT_USED;
3146 if (!(multi_touch_context->is_sub_event)) {
3147 sclboolean process_finished = FALSE;
3149 /* First check if the event occured in pressed key's threshold area */
3150 if (button_context && coordinate) {
3151 if (pressed_window == window) { // Check only when the window is the one initally pressed
3152 if (button_context->used && button_context->state != BUTTON_STATE_DISABLED) {
3153 if (process_button_move_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
3155 x = coordinate->x + (coordinate->width / 2);
3156 y = coordinate->y + (coordinate->height / 2);
3157 button_index = pressed_key;
3162 for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
3163 button_context = cache->get_cur_button_context(window, loop);
3164 const SclLayoutKeyCoordinate *cur_coordinate =
3165 cache->get_cur_layout_key_coordinate(window, loop);
3166 if (button_context && cur_coordinate) {
3167 if (!(button_context->used)) {
3169 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3170 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
3171 if (window != pressed_window || loop != pressed_key) {
3172 if (process_button_move_event(window, x, y, loop, touch_id, actual_event)) {
3174 button_index = loop;
3181 if (windows->is_base_window(window)) {
3182 process_finished = TRUE;
3183 } else if (button_index != NOT_USED) {
3184 process_finished = TRUE;
3186 const SclLayout *cur_layout = cache->get_cur_layout(window);
3187 if (cur_layout && cur_layout->use_sw_background && cur_layout->bg_color.a == 0) {
3188 /* If we could not find appropriate button in this popup window and the popup is transparent */
3189 SclWindowContext *base_window_context =
3190 windows->get_window_context(windows->get_base_window());
3191 if (base_window_context && window_context) {
3192 x = (window_context->geometry.x + x - base_window_context->geometry.x);
3193 y = (window_context->geometry.y + y - base_window_context->geometry.y);
3195 window = windows->get_base_window();
3197 process_finished = TRUE;
3200 } while (!process_finished);
3211 CSCLController::mouse_over(sclwindow window, sclint x, sclint y)
3214 sclboolean ret = FALSE;
3216 if(m_input_events_disabled)
3219 /* Adjust x,y coordinate by touch offset */
3220 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
3221 /* Iterate all the buttons and inform the event */
3223 CSCLContext *context = CSCLContext::get_instance();
3224 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3225 CSCLActionState *state = CSCLActionState::get_instance();
3226 CSCLWindows *windows = CSCLWindows::get_instance();
3227 CSCLUtils *utils = CSCLUtils::get_instance();
3228 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3230 if (cache && state && windows && context && utils && adjustment && sclres_manager) {
3231 const SclLayout *layout = cache->get_cur_layout(window);
3233 x += layout->mouse_manipulate_x;
3234 y += layout->mouse_manipulate_y;
3237 SCLDisplayMode cur_display_mode = context->get_display_mode();
3239 const SclDefaultConfigure *default_configure = sclres_manager->get_default_configure();
3240 if (default_configure) {
3241 adjustment->apply_touch_offset(default_configure->touch_offset_level[cur_display_mode], &x, &y);
3244 /* Iterate all the buttons and inform the event */
3245 sclboolean ended = FALSE;
3247 for (int loop = 0; loop < MAX_KEY && !ended && !ret; loop++) {
3248 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
3249 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3250 if (button_context && coordinate) {
3251 if (!(button_context->used)) {
3253 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3254 coordinate->button_type != BUTTON_TYPE_UIITEM) {
3255 if (process_button_over_event(window, x, y, loop)) {
3268 * Processes a timer event
3269 * If return FALSE, the current timer will be stop
3270 * ID : SCL_LOWORD(data)
3271 * value : SCL_HIWORD(data)
3274 CSCLController::timer_event(const scl32 data)
3277 CSCLWindows *windows = CSCLWindows::get_instance();
3278 CSCLContext *context = CSCLContext::get_instance();
3279 CSCLEvents* events = CSCLEvents::get_instance();
3280 CSCLActionState *state = CSCLActionState::get_instance();
3281 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3282 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3284 scl16 id = SCL_LOWORD(data); /* Timer ID */
3285 scl16 value = SCL_HIWORD(data); /* event unique ID */
3287 if (!windows || !context || !events || !state || !cache || !handler)
3291 case SCL_TIMER_AUTOPOPUP: {
3292 /* Checks whether my event id is availble */
3293 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3294 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3295 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3296 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3297 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3298 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3299 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3300 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3301 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3302 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3303 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3305 /* Ignores if the event id is different */
3306 events->destroy_timer(id);
3310 SclRectangle rect = {0,0,0,0};
3311 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3312 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3314 if (configure_autopopup_window(window, key_index, &rect)) {
3315 /* Let's change out pressed button's state back to normal */
3316 SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
3317 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3319 if (button_context) {
3320 if (button_context->state == BUTTON_STATE_PRESSED) {
3321 button_context->state = BUTTON_STATE_NORMAL;
3323 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3327 /* Hide magnifier window when opening autopopup window */
3328 windows->hide_window(windows->get_magnifier_window());
3330 sclwindow popup_window = SCLWINDOW_INVALID;
3332 SclNotiPopupOpeningDesc desc;
3333 desc.ui_event_desc = NULL;
3334 desc.input_mode = SCL_LAYOUT_AUTOPOPUP_NAME;
3335 if (SCL_EVENT_PASS_ON ==
3336 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
3337 /* Currently, window does not support virtual window */
3338 SclWindowOpener opener;
3339 opener.window = window;
3340 opener.key = key_index;
3342 popup_window = windows->open_popup(
3346 SCL_LAYOUT_AUTOPOPUP, POPUP_TYPE_AUTO_POPUP,
3351 SclNotiPopupOpenedDesc opened_desc;
3352 opened_desc.ui_event_desc = NULL;
3353 opened_desc.input_mode = desc.input_mode;
3354 opened_desc.window = popup_window;
3355 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
3358 windows->hide_window(windows->get_magnifier_window());
3359 _play_tts_for_layout_autopopup_name();
3361 sclwindow moving_window = context->get_cur_moving_window(context->get_last_touch_device_id());
3362 SclPoint moving_point = context->get_cur_moving_point(context->get_last_touch_device_id());
3363 SclWindowContext *moving_window_context = windows->get_window_context(moving_window);
3364 SclWindowContext *popup_window_context = windows->get_window_context(popup_window);
3365 if (moving_window_context && popup_window_context) {
3366 moving_point.x = (moving_window_context->geometry.x - popup_window_context->geometry.x) + moving_point.x;
3367 moving_point.y = (moving_window_context->geometry.y - popup_window_context->geometry.y) + moving_point.y;
3369 //printf("AUTOPOPUP : %d %d\n", moving_point.x, moving_point.y);
3372 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3375 events->destroy_timer(id);
3381 case SCL_TIMER_LONGKEY: {
3382 /* Checks whether my event id is availble */
3383 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3384 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3385 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3386 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3387 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3388 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3389 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3390 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3391 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3392 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3393 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3395 /* Ignores if the event id is different */
3396 events->destroy_timer(id);
3399 /* Ignores if the event id is different */
3400 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3401 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3402 if (process_button_long_pressed_event(window, key_index, context->get_last_touch_device_id())) {
3403 /* The button processed long key event, now enter longkey mode not to fire any events before releasing */
3404 handle_engine_signal(SCL_SIG_MOUSE_LONG_PRESS, window);
3405 windows->update_window(windows->get_magnifier_window());
3407 SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
3408 if (button_context->state == BUTTON_STATE_PRESSED) {
3409 button_context->state = BUTTON_STATE_NORMAL;
3410 CSCLWindows *windows = CSCLWindows::get_instance();
3412 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3413 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3416 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3417 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3420 /* Start the repeat key timer for NORMAL or GRAB buttons if longkey is not supported */
3421 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3424 /* This is for enabling backspace key in search layout*/
3425 //if (coordinate->use_repeat_key) {
3426 if (coordinate->use_repeat_key
3427 || coordinate->key_event[0][0] == MVK_BackSpace) {
3428 if (coordinate->button_type == BUTTON_TYPE_NORMAL ||
3429 coordinate->button_type == BUTTON_TYPE_GRAB ||
3430 coordinate->button_type == BUTTON_TYPE_SELFISH ||
3431 coordinate->button_type == BUTTON_TYPE_DIRECTION ||
3432 coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
3433 m_key_repeated_num = 0;
3434 events->create_timer(SCL_TIMER_REPEATKEY, m_repeat_key_duration, value);
3435 if (windows->is_base_window(window)) {
3436 state->set_cur_action_state(ACTION_STATE_BASE_REPEATKEY);
3438 state->set_cur_action_state(ACTION_STATE_POPUP_REPEATKEY);
3444 events->destroy_timer(id);
3449 case SCL_TIMER_REPEATKEY: {
3450 /* Checks whether my event id is availble */
3451 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3452 (state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
3453 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY)
3455 /* Ignores if the event id is different */
3456 events->destroy_timer(id);
3459 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3460 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3461 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
3462 if (interval < SCL_REPEATKEY_MIN_DURATION) {
3463 interval = SCL_REPEATKEY_MIN_DURATION;
3465 process_button_repeat_pressed_event(window, key_index, context->get_last_touch_device_id());
3466 events->destroy_timer(id);
3467 events->create_timer(SCL_TIMER_REPEATKEY, interval, value);
3468 m_key_repeated_num++;
3472 case SCL_TIMER_BUTTON_DELAY: {
3473 /* If there is postponed update of button, update it now */
3474 sclwindow last_window = context->get_last_pressed_window();
3475 scl8 last_key = context->get_last_pressed_key();
3477 if (last_window != SCLWINDOW_INVALID && last_key != NOT_USED) {
3478 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_window, last_key);
3480 windows->update_window(last_window, coords->x, coords->y, coords->width, coords->height);
3484 windows->hide_window(windows->get_magnifier_window());
3485 context->set_last_pressed_window(SCLWINDOW_INVALID);
3486 context->set_last_pressed_key(NOT_USED);
3487 events->destroy_timer(id);
3491 case SCL_TIMER_POPUP_TIMEOUT: {
3492 SclNotiPopupClosingDesc desc;
3493 desc.ui_event_desc = NULL;
3494 desc.input_mode = NULL;
3495 desc.timed_out = TRUE;
3497 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3498 if (sclres_manager) {
3499 const PSclInputModeConfigure sclres_input_mode_configure =
3500 sclres_manager->get_input_mode_configure_table();
3501 sclwindow window = windows->get_nth_popup_window(SCL_WINDOW_Z_TOP);
3502 SclWindowContext *window_context = windows->get_window_context(window);
3503 if (window_context && sclres_input_mode_configure) {
3504 if (scl_check_arrindex(window_context->inputmode, MAX_SCL_INPUT_MODE)) {
3505 desc.input_mode = sclres_input_mode_configure[window_context->inputmode].name;
3510 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_CLOSING, &desc)) {
3511 windows->close_all_popups();
3513 SclNotiPopupClosedDesc closed_desc;
3514 closed_desc.ui_event_desc = desc.ui_event_desc;
3515 closed_desc.input_mode = desc.input_mode;
3516 closed_desc.timed_out = desc.timed_out;
3517 handler->on_event_notification(SCL_UINOTITYPE_POPUP_CLOSED, &desc);
3519 events->destroy_timer(id);
3523 case SCL_TIMER_AUTOTEST: {
3524 sclint rnd = rand() % 100;
3526 if (cache->get_cur_layout(windows->get_base_window()) == NULL) {
3529 sclint x = (rand() % (cache->get_cur_layout(windows->get_base_window())->width));
3530 sclint y = (rand() % (cache->get_cur_layout(windows->get_base_window())->height));
3533 events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3534 events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3535 } else if (rnd < 90) {
3536 events->generate_mouse_event(SCL_MOUSE_EVENT_MOVE, x, y);
3537 } else if (rnd < 95) {
3538 events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3540 events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3544 if (m_debug_variable < SCL_AUTOTEST_NUM) events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INTERVAL, 0, FALSE);
3545 else m_debug_mode = DEBUGMODE_DISABLED;
3549 case SCL_TIMER_ANIMATION: {
3550 CSCLAnimator *animator = CSCLAnimator::get_instance();
3552 return animator->animator_timer();
3558 events->destroy_timer(id);
3566 /* Handles signals to manage contexts mainly focusing on resetting variables and cleaning up states */
3567 void CSCLController::handle_engine_signal( SclInternalSignal signal, sclwindow targetWindow )
3572 SIGACTION_RESIZE_RESOURCES,
3573 SIGACTION_DESTROY_TIMERS,
3574 SIGACTION_CLEAR_PRIVATEKEYS,
3575 SIGACTION_RECOMPUTE_LAYOUT,
3576 SIGACTION_FREE_IMAGES,
3577 SIGACTION_CLOSE_POPUP,
3578 SIGACTION_CLOSE_MAGNIFIER,
3579 SIGACTION_UNSET_SHIFT,
3580 SIGACTION_UNPRESS_KEYS,
3581 SIGACTION_INIT_DISPLAY,
3582 SIGACTION_INIT_INPUTMODE,
3586 const sclboolean SIGNAL_TABLE[SIGACTION_MAXNUM][SCL_SIG_MAXNUM] = {
3587 // START, SHOW, HIDE, INPCHNG, DISPCHNG, POPUPSHOW, POPUPHIDE, MOUSEPRES, M-LONGPRES, MOUSEREL, KEYEVT, FOCUSCHNG
3588 // SIGACTION_RESIZE_RESOURCES
3589 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3590 // SIGACTION_DESTROY_TIMERS
3591 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3592 // SIGACTION_CLEAR_PRIVATEKEYS
3593 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TRUE },
3594 // SIGACTION_RECOMPUTE_LAYOUT
3595 { 0, TRUE, 0, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
3596 // SIGACTION_FREE_IMAGES
3597 { TRUE, 0, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0 },
3598 // SIGACTION_CLOSE_POPUP
3599 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3600 // SIGACTION_CLOSE_MAGNIFIER
3601 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3602 // SIGACTION_UNSET_SHIFT
3603 { TRUE, 0 , 0 , TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE },
3604 // SIGACTION_UNPRESS_KEYS
3605 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3606 // SIGACTION_INIT_DISPLAY
3607 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3608 // SIGACTION_INIT_INPUTMODE
3609 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TRUE },
3612 scl_assert_return(signal >= 0 && signal < SCL_SIG_MAXNUM);
3614 CSCLEvents* events = CSCLEvents::get_instance();
3615 CSCLWindows *windows = CSCLWindows::get_instance();
3616 CSCLContext *context = CSCLContext::get_instance();
3617 CSCLImageProxy *proxy = CSCLImageProxy::get_instance();
3618 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3623 context->set_hidden_state(FALSE);
3628 context->set_hidden_state(TRUE);
3629 windows->close_all_popups();
3633 case SCL_SIG_INPMODE_CHANGE:
3634 case SCL_SIG_DISP_CHANGE:
3635 case SCL_SIG_POPUP_SHOW:
3636 case SCL_SIG_POPUP_HIDE:
3637 case SCL_SIG_MOUSE_PRESS:
3638 case SCL_SIG_MOUSE_LONG_PRESS:
3639 case SCL_SIG_MOUSE_RELEASE:
3640 case SCL_SIG_KEYEVENT:
3646 for (loop = 0;loop < SIGACTION_MAXNUM;loop++) {
3647 if (SIGNAL_TABLE[loop][signal] == TRUE) {
3649 case SIGACTION_DESTROY_TIMERS:
3650 events->destroy_all_timer();
3652 case SIGACTION_RECOMPUTE_LAYOUT: {
3653 if (targetWindow != SCLWINDOW_INVALID) {
3654 cache->recompute_layout(targetWindow);
3656 windows->update_window(targetWindow);
3660 case SIGACTION_FREE_IMAGES:
3661 proxy->free_images();
3663 case SIGACTION_CLOSE_POPUP: {
3664 /* If there is a popup still opened, don't destroy POPUP_TIMEOUT timer */
3665 if (!(windows->close_all_popups(targetWindow))) {
3666 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
3670 case SIGACTION_CLOSE_MAGNIFIER: {
3671 if (signal == SCL_SIG_HIDE) {
3672 windows->hide_window(windows->get_magnifier_window(), TRUE);
3674 windows->hide_window(windows->get_magnifier_window());
3677 //events->create_timer(SCL_TIMER_BUTTON_DELAY, SCL_BUTTON_MIN_DURATION, 0);
3679 case SIGACTION_UNSET_SHIFT: {
3680 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3683 SclNotiShiftStateChangeDesc desc;
3684 desc.ui_event_desc = NULL;
3685 desc.shift_state = SCL_SHIFT_STATE_OFF;
3687 if (SCL_EVENT_PASS_ON ==
3688 handler->on_event_notification(SCL_UINOTITYPE_SHIFT_STATE_CHANGE, &desc)) {
3689 context->set_shift_state(SCL_SHIFT_STATE_OFF);
3694 case SIGACTION_UNPRESS_KEYS:
3695 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3696 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3706 * Sets the duration value for longkey
3707 * If not set, it will use default longkey duration. see sclconfig
3710 CSCLController::set_longkey_duration(scllong msc)
3713 sclboolean ret = FALSE;
3715 m_long_key_duration = msc;
3722 * Sets the distance value for cancel longkey
3723 * If not set, it will use default longkey duration. see sclconfig
3726 CSCLController::set_longkey_cancel_dist(sclshort dist)
3729 sclboolean ret = FALSE;
3731 m_long_key_cancel_distance = dist;
3738 * Sets the duration value for repeatkey
3739 * If not set, it will use default repeatkey duration. see sclconfig
3742 CSCLController::set_repeatkey_duration(scllong msc)
3745 sclboolean ret = FALSE;
3747 m_repeat_key_duration = msc;
3754 * Sets the duration value for autopopup key
3755 * If not set, it will use default short longkey duration. see sclconfig
3758 CSCLController::set_autopopup_key_duration(scllong msc)
3761 sclboolean ret = FALSE;
3763 m_autopopup_key_duration = msc;
3770 * Sets the amount value for button delay
3771 * If not set, it will use default button delay amount. see sclconfig
3774 CSCLController::set_button_delay_duration(scllong msc)
3777 sclboolean ret = FALSE;
3779 m_button_delay_duration = msc;
3786 * Configures the variables for auto-popup window
3787 * It will return rectangle area
3788 * @return FALSE It's not avaiable popup key
3791 CSCLController::configure_autopopup_window(sclwindow window, sclbyte key_index, SclRectangle* rect)
3794 scl_assert_return_false(window);
3795 scl_assert_return_false(key_index >= 0);
3797 sclboolean ret = TRUE;
3799 sclbyte num_keys, num_columns, num_rows;
3801 CSCLUtils *utils = CSCLUtils::get_instance();
3802 CSCLContext *context = CSCLContext::get_instance();
3803 CSCLWindows *windows = CSCLWindows::get_instance();
3804 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3806 const SclLayoutKeyCoordinate *coordinate = NULL;
3809 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3812 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3813 PSclAutoPopupConfigure autopopup_configure = NULL;
3814 if (sclres_manager) {
3815 autopopup_configure = sclres_manager->get_autopopup_configure();
3818 if (utils && context && windows && cache && coordinate && rect && autopopup_configure) {
3819 SCLShiftState shift_index = context->get_shift_state();
3820 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
3821 if (context->get_caps_lock_mode()) {
3822 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
3825 if (utils->get_autopopup_window_variables(coordinate->autopopup_key_labels[shift_index],
3826 &num_keys, &num_columns, &num_rows, &rect->width, &rect->height)) {
3828 /* There is no need for an autopopup window if number of keys are equal to or less than 0 */
3829 if (!(num_keys > 0)) {
3832 /* calculates y position to be set */
3833 SclRectangle baseWndRect;
3834 int scrwidth, scrheight;
3835 utils->get_screen_resolution(&scrwidth, &scrheight);
3837 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
3838 /* Let the autopopup have its position right above the pressed button, with center alignment) */
3839 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) - (rect->width / 2);
3840 rect->y = baseWndRect.y + coordinate->y - rect->height +
3841 autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate();
3842 /* First check the growing direction of this autopopup window */
3843 if (coordinate->x < baseWndRect.width / 2) {
3844 /* We're growing left to right, calculate the left start point */
3845 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) -
3846 (autopopup_configure->button_width * utils->get_custom_scale_rate_x() / 2) -
3847 autopopup_configure->bg_padding * utils->get_smallest_custom_scale_rate();
3848 if (rect->x + rect->width > baseWndRect.x + baseWndRect.width) {
3849 sclint relocate_unit = autopopup_configure->button_width * utils->get_custom_scale_rate_x() +
3850 autopopup_configure->button_spacing * utils->get_smallest_custom_scale_rate();
3851 rect->x -= (((rect->x + rect->width - (baseWndRect.x + baseWndRect.width)) /
3852 relocate_unit) + 1) * relocate_unit;
3855 /* We're growing right to left, calculate the right end point */
3856 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) +
3857 (autopopup_configure->button_width * utils->get_custom_scale_rate_x() / 2) +
3858 autopopup_configure->bg_padding * utils->get_smallest_custom_scale_rate();
3859 rect->x -= rect->width;
3860 if (rect->x < baseWndRect.x) {
3861 sclint relocate_unit = autopopup_configure->button_width * utils->get_custom_scale_rate_x() +
3862 autopopup_configure->button_spacing * utils->get_smallest_custom_scale_rate();
3863 rect->x += (((baseWndRect.x - rect->x) /
3864 relocate_unit) + 1) * relocate_unit;
3867 //rect->y = (scrheight - layout->height) + coordinate->y - rect->height + autopopup_configure->decoration_size;
3868 /* Check if the window goes out of screen boundary */
3869 //if (rect->x + rect->width > scrwidth + utils->get_scale_x(scl_autopopup_configure.decoration_size)) rect->x = (scrwidth + utils->get_scale_x(scl_autopopup_configure.decoration_size)) - rect->width;
3870 if (rect->x + rect->width > scrwidth) rect->x = (scrwidth) - rect->width;
3871 if (rect->y + rect->height > scrheight) rect->y = scrheight - rect->height;
3872 if (rect->x < 0 - autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate())
3873 rect->x = 0 - autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate();
3875 if (rect->x < 0) rect->x = 0;
3876 if (rect->y < 0) rect->y = 0;
3885 * If the mouse was pressed on the button A and moved to B without releasing,
3886 * this function decides whether we should allow event transition, meaning
3887 * button A gets restored to its initial state and B gets pressed instead.
3890 CSCLController::check_event_transition_enabled(const SclLayoutKeyCoordinate *btn_from, const SclLayoutKeyCoordinate *btn_to)
3892 sclboolean ret = FALSE;
3893 sclbyte type_from = BUTTON_TYPE_NORMAL; /* To enable event transition even if no button is pressed currently */
3894 sclbyte type_to = MAX_BUTTON_TYPE;
3896 const sclboolean TRANSITION_TABLE[MAX_BUTTON_TYPE][MAX_BUTTON_TYPE] = {
3897 // NORMAL GRAB SELFISH DRAG MULTITAP ROTATION DIRECTION R_DIRECTION TOGGLE UIITEM
3899 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3901 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3903 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3905 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3907 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3909 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3911 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3912 // From : R_DIRECTION
3913 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3915 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3917 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3920 if (btn_from) type_from = btn_from->button_type;
3921 if (btn_to) type_to = btn_to->button_type;
3923 scl_assert_return_false(type_from >= 0 && type_from < MAX_BUTTON_TYPE);
3924 scl_assert_return_false(type_to >= 0 && type_to < MAX_BUTTON_TYPE);
3926 if (type_from < MAX_BUTTON_TYPE && type_to < MAX_BUTTON_TYPE) {
3927 ret = TRANSITION_TABLE[type_from][type_to];
3934 CSCLController::get_debug_mode()
3937 return m_debug_mode;
3939 return m_debug_mode;
3940 return DEBUGMODE_DISABLED;
3945 CSCLController::set_debug_mode(SCLDebugMode mode)
3947 CSCLEvents *events = CSCLEvents::get_instance();
3948 CSCLUtils *utils = CSCLUtils::get_instance();
3950 m_debug_mode = mode;
3951 m_debug_variable = 0;
3953 if (m_debug_mode == DEBUGMODE_AUTOTEST) {
3955 if (events && utils) {
3956 events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INITIAL_INTERVAL, 0, FALSE);
3957 utils->log("mode : %d\n", mode);
3963 CSCLController::disable_input_events(sclboolean disabled)
3965 m_input_events_disabled = disabled;