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"
36 //#define DIRECTLY_DRAW_ON_EVENTS
41 _play_tts_for_input_mode_name(int mode) {
44 CSCLContext *context = CSCLContext::get_instance();
45 if (context->get_tts_enabled() == FALSE) {
49 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
50 const SclInputModeConfigure *pinput_mode_table = sclres_manager->get_input_mode_configure_table();
51 if (NULL == pinput_mode_table) {
55 const char* name = pinput_mode_table[mode].name;
60 CSCLUtils *utils = CSCLUtils::get_instance();
61 utils->play_tts(name);
66 _play_tts_for_layout_autopopup_name() {
69 CSCLContext *context = CSCLContext::get_instance();
70 if (context->get_tts_enabled() == FALSE) {
74 CSCLUtils *utils = CSCLUtils::get_instance();
75 utils->play_tts(SCL_LAYOUT_AUTOPOPUP_NAME);
79 CSCLController::CSCLController()
83 m_long_key_duration = SCL_LONGKEY_DURATION;
84 m_long_key_cancel_distance = SCL_LONGKEY_CANCEL_DIST;
85 m_repeat_key_duration = SCL_REPEATKEY_DURATION;
86 m_autopopup_key_duration = SCL_AUTOPOPUP_KEY_DURATION;
88 m_button_delay_duration = SCL_BUTTON_MIN_DURATION;
90 m_key_repeated_num = 0;
92 m_debug_mode = DEBUGMODE_DISABLED;
95 m_input_events_disabled = FALSE;
98 CSCLController::~CSCLController()
104 CSCLController::get_instance()
106 static CSCLController instance;
111 CSCLController::init()
116 //#define TEST_NEWBACKEND
117 #ifdef TEST_NEWBACKEND
118 #include <Ecore_Evas.h>
124 EFLOBJECT_CLIPOBJECT,
130 SclRectangle position;
133 sclboolean extracted;
136 #include <Ecore_Evas.h>
142 Evas_Object *clipper;
145 sclchar image_path[_POSIX_PATH_MAX];
155 sclboolean extrace_image;
164 scl::SclFontInfo font_info;
166 sclchar str[_POSIX_PATH_MAX];;
172 SCLLabelAlignment align;
176 sclbyte inner_height;
179 extern std::vector<ImageCache> g_ImageCache;
180 extern std::vector<TextCache> g_TextCache;
185 * Sets the current input mode to the given mode
188 CSCLController::process_input_mode_change(const sclbyte mode)
192 sclboolean ret = FALSE;
194 CSCLUtils *utils = CSCLUtils::get_instance();
195 CSCLContext *context = CSCLContext::get_instance();
196 CSCLWindows *windows = CSCLWindows::get_instance();
197 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
198 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
199 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
200 assert(sclres_input_mode_configure != NULL);
202 if (context && windows && cache && utils) {
203 if (mode == context->get_input_mode() || mode == (sclbyte)NOT_USED) {
204 /* ButtonContext does not get initialized if we don't call here */
205 cache->recompute_layout(windows->get_base_window());
209 context->set_input_mode(mode);
210 /* FIXME : NEWXML temporary commenting out */
211 //context->set_base_layout(sclres_input_mode_configure[mode].layouts[context->get_display()]);
213 _play_tts_for_input_mode_name(mode);
215 sclwindow window = windows->get_base_window();
216 handle_engine_signal(SCL_SIG_INPMODE_CHANGE, window);
218 #ifdef TEST_NEWBACKEND
219 SclWindowContext *window_context= windows->get_window_context(window, FALSE);
220 if (window_context) {
221 if (window_context->etc_info) {
223 Eina_List *list = (Eina_List*)(window_context->etc_info);
224 Eina_List *iter = NULL;
225 Eina_List *iter_next = NULL;
229 EINA_LIST_FOREACH_SAFE(list, iter, iter_next, data) {
231 EFLObject *object = (EFLObject*)(data);
233 Evas_Object* eo = object->object;
234 if (object->extracted) {
235 void *data = evas_object_image_data_get(eo, 1);
242 for(loop = 0;loop < g_ImageCache.size();loop++) {
243 if (g_ImageCache[loop].image == object->object) {
244 g_ImageCache[loop].used = FALSE;
247 for(loop = 0;loop < g_TextCache.size();loop++) {
248 if (g_TextCache[loop].text == object->object) {
249 g_TextCache[loop].used = FALSE;
255 object->object = NULL;
259 list = eina_list_remove_list(list, iter);
263 window_context->etc_info= list;
273 * Sets the current display mode to the given mode
276 CSCLController::process_rotation_change(const SCLRotation rotation)
279 CSCLContext *context = CSCLContext::get_instance();
280 CSCLWindows *windows = CSCLWindows::get_instance();
281 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
282 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
283 assert(sclres_input_mode_configure != NULL);
285 if (context && windows) {
287 if (rotation == ROTATION_90_CW || rotation == ROTATION_90_CCW) {
288 mode = DISPLAYMODE_LANDSCAPE;
290 mode = DISPLAYMODE_PORTRAIT;
293 //if (mode == context->get_display()) return FALSE;
294 context->set_display_mode(mode);
295 context->set_rotation(rotation);
296 /* FIXME : NEWXML temporary commenting out */
297 //context->set_base_layout(sclres_input_mode_configure[context->get_input_mode()].layouts[context->get_display()]);
299 sclwindow window = windows->get_base_window();
300 handle_engine_signal(SCL_SIG_DISP_CHANGE, window);
301 windows->update_window(window);
303 /* Moved to here since the new WMSync requires the rotation call be invoked as the
304 last step of display change process */
305 /* Make sure to set window's rotation degree before sending engine signal, which adjusts the size of main window */
306 windows->set_window_rotation(NULL, rotation);
312 * Checks if the given button with given touch_id needs magnifier window
315 CSCLController::check_magnifier_available(sclwindow window, sclbyte key_index, scltouchdevice touch_id)
317 sclboolean ret = FALSE;
319 CSCLContext *context = CSCLContext::get_instance();
320 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
321 const SclLayout *layout = NULL;
322 SclButtonContext *button_context = NULL;
323 const SclLayoutKeyCoordinate *coordinate = NULL;
325 if (context && cache) {
326 layout = cache->get_cur_layout(window);
327 button_context = cache->get_cur_button_context(window, key_index);
328 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
330 SCLShiftState shift_index = context->get_shift_state();
331 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
332 if (context->get_caps_lock_mode()) {
333 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
336 if (layout && coordinate && button_context && context->get_magnifier_enabled() ) {
337 if (coordinate->key_type != KEY_TYPE_CONTROL &&
338 coordinate->key_type != KEY_TYPE_MODECHANGE &&
339 coordinate->key_type != KEY_TYPE_NONE) {
343 /* Do not show if current layout does not allow magnifier */
344 if (!(layout->use_magnifier_window)) {
345 //utils->log("show_magnifier !(layout->use_magnifier_window \n");
349 /* Do not show if there's nothing to show */
350 const sclchar* custom_label = NULL;
351 for(sclint label_index = 0;label_index < MAX_SIZE_OF_LABEL_FOR_ONE && !custom_label;label_index++) {
352 const sclchar *temp_label = context->get_custom_magnifier_label(touch_id, label_index);
354 custom_label = temp_label;
358 //if (coordinate->key_value[shift_index][button_context->multikeyIdx] == NULL) {
359 if (coordinate->label[shift_index][button_context->multikeyIdx] == NULL) {
360 //utils->log("show_magnifier coordinate->key_value[shift][button_context->multikeyIdx] == NULL \n");
362 //} else if (strlen(coordinate->key_value[shift_index][button_context->multikeyIdx]) == 0) {
363 } else if (strlen(coordinate->label[shift_index][button_context->multikeyIdx]) == 0) {
364 //utils->log("show_magnifier coordinate->key_value[shift][button_context->multikeyIdx]) == 0 \n");
369 if (touch_id != context->get_last_touch_device_id()) {
380 CSCLController::process_button_pressed_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
381 scltouchdevice touch_id, sclboolean actual_event)
385 sclboolean ret = FALSE;
386 sclboolean redraw = FALSE;
388 CSCLContext *context = CSCLContext::get_instance();
389 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
390 CSCLWindows *windows = CSCLWindows::get_instance();
391 CSCLEvents *events = CSCLEvents::get_instance();
392 CSCLUtils *utils = CSCLUtils::get_instance();
393 CSCLFeedback *feedback = CSCLFeedback::get_instance();
394 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
395 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
396 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
397 PSclLayout sclres_layout = sclres_manager->get_layout_table();
398 assert(sclres_input_mode_configure != NULL);
399 assert(sclres_layout != NULL);
401 SclButtonContext *button_context = NULL;
402 const SclLayoutKeyCoordinate *coordinate = NULL;
404 if (context && cache) {
405 button_context = cache->get_cur_button_context(window, key_index);
406 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
409 if (context && cache && windows && events && utils && feedback && handler && button_context && coordinate) {
410 /* First check if this button is enabled in current active sublayout */
411 sclboolean sub_layout_match = TRUE;
412 if (coordinate->sub_layout && context->get_cur_sublayout()) {
413 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
414 sub_layout_match = FALSE;
417 /* If this button is pressed */
418 if ( x >= coordinate->x - coordinate->add_hit_left &&
419 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
420 y >= coordinate->y - coordinate->add_hit_top &&
421 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
422 /* Process the event only if the this item's sublayout id is active one */
424 //utils->log("process_button_pressed_event___TRUE\n");
426 /* If newly pressed key has type MULTI_TOUCH_TYPE_EXCLUSIVE, release all existing pressed events */
428 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_EXCLUSIVE) {
429 /* When calling mouse_release, the seq order of current multitouch events will be changed,
430 so we put all the multitouch events into a vector and use them afterwards forreleasing */
432 sclint multi_touch_context_num = context->get_multi_touch_context_num();
433 std::vector<SclUIEventDesc> multi_touch_events;
434 for(loop = 0;loop < multi_touch_context_num;loop++) {
436 context->get_multi_touch_event(loop, &desc);
437 multi_touch_events.push_back(desc);
439 for(loop = 0;loop < multi_touch_context_num;loop++) {
440 SclUIEventDesc desc = multi_touch_events[loop];
441 if (desc.touch_id != touch_id) {
442 mouse_release(context->get_cur_moving_window(desc.touch_id),
443 context->get_cur_moving_point(desc.touch_id).x,
444 context->get_cur_moving_point(desc.touch_id).y,
445 desc.touch_id, FALSE);
451 /* Make an unique ID for timer */
452 const scl16 uniqId = utils->get_unique_id();
454 context->set_cur_pressed_event_id(touch_id, uniqId);
455 context->set_cur_pressed_key(touch_id, key_index);
456 context->set_cur_pressed_window(touch_id, window);
458 button_context->state = BUTTON_STATE_PRESSED;
463 #ifndef DIRECTLY_DRAW_ON_EVENTS
464 /* If the window doesn't get exposed before corresponding release event,
465 * the inverted state of a button will never be drawn onto screen.
466 * To prevent such a case, we draw the inverted state of button forcefully and directly,
467 * without waiting for expose event */
468 /*CSCLGraphics *grps = CSCLGraphics::get_instance();
469 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
470 scldrawctx draw_ctx = grps->begin_paint(window, TRUE);
471 builder->draw_button(window, draw_ctx, key_index, button_context->state, TRUE);
472 grps->end_paint(window, draw_ctx);*/
476 feedback->button_pressed(window, key_index);
478 /* Special routine for autopopup */
479 if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
480 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
482 /* for long key & repeat key */
483 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
486 SCLShiftState shift_index = context->get_shift_state();
487 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
488 if (context->get_caps_lock_mode()) {
489 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
492 SclUIEventDesc key_event_desc;
493 key_event_desc.key_value = coordinate->key_value[shift_index][0];
494 key_event_desc.key_event = coordinate->key_event[shift_index][0];
495 key_event_desc.key_type = coordinate->key_type;
496 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
497 key_event_desc.event_type = EVENT_TYPE_PRESS;
499 SclPoint curpoint = {x, y};
500 key_event_desc.touch_id = touch_id;
501 key_event_desc.mouse_pressed_point = curpoint;
502 key_event_desc.mouse_current_point = curpoint;
503 key_event_desc.mouse_farthest_point = curpoint;
505 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
507 SCLEventReturnType processed = handler->on_event_drag_state_changed(key_event_desc);
509 /* Only if the handler didn't return SCL_EVENT_DONE */
510 if (processed == SCL_EVENT_PASS_ON) {
511 /* Now process normal behaviours of each button type */
512 switch (coordinate->button_type) {
513 case BUTTON_TYPE_NORMAL:
514 case BUTTON_TYPE_GRAB:
515 case BUTTON_TYPE_SELFISH:
516 case BUTTON_TYPE_DIRECTION:
517 case BUTTON_TYPE_RELATIVE_DIRECTION: {
518 /* Send click event right away if this button uses repeat key */
519 if (coordinate->use_repeat_key) {
520 handler->on_event_key_clicked(key_event_desc);
524 case BUTTON_TYPE_MULTITAP: {
527 case BUTTON_TYPE_ROTATION: {
530 case BUTTON_TYPE_DRAG: {
531 /* Drag buttons fires click event immediately when they are pressed */
532 handler->on_event_key_clicked(key_event_desc);
535 case BUTTON_TYPE_UIITEM: break;
536 case MAX_BUTTON_TYPE: break;
539 switch (coordinate->popup_type) {
540 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: {
541 SclNotiPopupOpeningDesc desc;
542 desc.ui_event_desc = &key_event_desc;
543 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
544 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
545 sclint popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
546 SCLDisplayMode display_mode = context->get_display_mode();
548 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
549 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
550 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
551 sclshort popupLayoutId =
552 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
553 SclRectangle popupRect;
554 SclRectangle baseWndRect;
555 SclLayout *layout = NULL;
557 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
558 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
559 layout = &sclres_layout[popupLayoutId];
562 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
563 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
564 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
565 //popupRect.width = utils->get_scale_x(layout->width);
566 //popupRect.height= utils->get_scale_y(layout->height);
567 popupRect.width = layout->width;
568 popupRect.height= layout->height;
569 windows->close_all_popups();
571 SclWindowOpener opener;
572 opener.window = window;
573 opener.key = key_index;
575 sclwindow popup_window = windows->open_popup(opener,
579 coordinate->popup_type,
580 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
581 sclres_input_mode_configure[popup_input_mode].use_dim_window,
582 coordinate->extract_offset_x,
583 coordinate->extract_offset_y,
584 sclres_input_mode_configure[popup_input_mode].timeout
587 SclNotiPopupOpenedDesc opened_desc;
588 opened_desc.ui_event_desc = &key_event_desc;
589 opened_desc.input_mode = desc.input_mode;
590 opened_desc.window = popup_window;
591 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
593 windows->hide_window(windows->get_magnifier_window());
594 /* FIXME : The parent key should be turned back to NORMAL state when RELEASED,
595 in case of POPUP_TYPE_BTN_PRESS_POPUP_DRAG type. Temporariliy setting NORMAL here. */
596 button_context->state = BUTTON_STATE_NORMAL;
597 _play_tts_for_input_mode_name(popup_input_mode);
603 case POPUP_TYPE_BTN_RELEASE_POPUP:
604 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
605 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
606 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
607 case POPUP_TYPE_AUTO_POPUP:
608 case POPUP_TYPE_NONE:
611 /* Nothing to do in here */
616 /* Shows the magnifier window(the magnifier window will display when a kind of button type is character) */
617 //if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
618 if (coordinate->use_magnifier) {
619 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
621 PSclMagnifierWndConfigure magnifier_configure = NULL;
622 if (sclres_manager) {
623 magnifier_configure = sclres_manager->get_magnifier_configure();
625 if (showMagnifier && magnifier_configure) {
626 SclPoint pos = {0,0};
627 /* calculates x position to be set */
628 pos.x = (coordinate->x + (coordinate->width / 2)) -
629 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
631 /* calculates y position to be set */
632 sclint scnWidth, scnHeight;
633 utils->get_screen_resolution(&scnWidth, &scnHeight);
635 pos.y = coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
637 /* FIXME : Temporary way of clearing magnifier window */
638 /*SclWindowContext *window_context = windows->get_window_context(windows->get_magnifier_window(), FALSE);
639 sclboolean clearmagwin = FALSE;
640 if (window_context) {
641 clearmagwin = !(window_context->hidden);
643 static int clearnum = 0;
644 if (key_index == prevkey && window == prevwin) {
648 if (++clearnum > 1) {
656 CSCLGraphics *graphics = CSCLGraphics::get_instance();
657 CSCLUtils *utils = CSCLUtils::get_instance();
658 sclchar composed_path[_POSIX_PATH_MAX] = {0,};
659 scldrawctx draw_ctx = graphics->begin_paint(windows->get_magnifier_window());
660 utils->get_composed_path(composed_path, scl_magnifier_configure.bg_image_path);
661 graphics->draw_image(windows->get_magnifier_window(), draw_ctx, composed_path, 0, 0);
662 graphics->end_paint(windows->get_magnifier_window(), draw_ctx);
665 windows->hide_window(windows->get_magnifier_window());
667 SclWindowContext *window_context = windows->get_window_context(window);
668 if (window_context) {
669 pos.x += window_context->geometry.x;
670 pos.y += window_context->geometry.y;
673 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
674 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
676 if (pos.x > scnWidth +
677 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
678 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
679 pos.x = scnWidth + magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
680 magnifier_configure->width * utils->get_custom_scale_rate_x();
682 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
683 pos.x += coordinate->magnifier_offset_x;
684 pos.y += coordinate->magnifier_offset_y;
685 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
686 //windows->resize_window(windows->get_magnifier_window(), utils->get_scale_x(scl_magnifier_configure.width), utils->get_scale_y(scl_magnifier_configure.height));
687 /*If we use transient_for them the ISE will occure some crash. It needs to check X11 */
688 /*windows->set_parent(windows->get_base_window(), windows->get_magnifier_window());*/
690 windows->show_window(windows->get_magnifier_window(), TRUE);
691 //windows->update_window(windows->get_magnifier_window());
694 static int fFirst = true;
696 windows->show_window(windows->get_magnifier_window());
699 windows->update_window(windows->get_magnifier_window());
702 /* We cannot use move_resize_window. It had occured some wrong behavior */
703 /*windows->move_resize_window(windows->get_magnifier_window(), pos.x, pos.y, scl_magnifier_configure.width, scl_magnifier_configure.height);*/
704 if (!showMagnifier) {
705 windows->hide_window(windows->get_magnifier_window());
709 /* COMMENTED OUT FOR TESTING MULTITOUCH!! */
710 ///* In case the current button is not the given key index */
711 //if (button_context->state == BUTTON_STATE_PRESSED) {
712 // /* Even if the press event occured outside of this button's physical area, reset its context */
713 // button_context->state = BUTTON_STATE_NORMAL;
716 /* BUTTON_TYPE_MULTITAP type button should restore its multikey index when another button is clicked */
717 if (coordinate->button_type & BUTTON_TYPE_MULTITAP) {
718 button_context->multikeyIdx = 0;
722 /* If there is any need for redrawing */
724 #ifdef DIRECTLY_DRAW_ON_EVENTS
725 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
727 builder->draw_button(window, NULL, key_index, button_context->state, TRUE);
731 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
741 CSCLController::process_button_long_pressed_event(sclwindow window, sclbyte key_index,
742 scltouchdevice touch_id, sclboolean actual_event)
746 sclboolean ret = FALSE;
748 CSCLContext *context = CSCLContext::get_instance();
749 CSCLWindows *windows = CSCLWindows::get_instance();
750 CSCLActionState *state = CSCLActionState::get_instance();
751 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
752 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
753 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
754 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
755 PSclLayout sclres_layout = sclres_manager->get_layout_table();
757 assert(sclres_input_mode_configure != NULL);
758 assert(sclres_layout != NULL);
759 if (context && cache && handler && windows && state) {
760 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
762 /* Should return FALSE if this key does not have any longkey related property */
765 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
766 /* When calling mouse_release, the seq order of current multitouch events will be ch anged,
767 so we put all the multitouch events into a vector and use them afterwards for rel easing */
768 sclboolean finished = FALSE;
770 sclint multi_touch_context_num = context->get_multi_touch_context_num();
771 std::vector<SclUIEventDesc> multitouch_events;
772 for (loop = 0;loop < multi_touch_context_num;loop++) {
774 context->get_multi_touch_event(loop, &desc);
775 multitouch_events.push_back(desc);
777 for (loop = 0;loop < multi_touch_context_num && !finished;loop++) {
778 SclUIEventDesc desc = multitouch_events[loop];
779 if (desc.touch_id != touch_id) {
780 sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
781 scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
782 const SclLayoutKeyCoordinate *cur_pressed_coordinate =
783 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
784 if (cur_pressed_coordinate) {
785 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
786 mouse_release(context->get_cur_moving_window(desc.touch_id),
787 context->get_cur_moving_point(desc.touch_id).x,
788 context->get_cur_moving_point(desc.touch_id).y,
789 desc.touch_id, FALSE);
800 /* Should return FALSE if this key does not have any longkey related property */
802 if (coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP ||
803 coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE ) {
805 SclUIEventDesc key_event_desc;
806 key_event_desc.key_type = coordinate->long_key_type;
807 if (coordinate->long_key_value == NULL && coordinate->long_key_event == 0) {
808 SCLShiftState shift_index = context->get_shift_state();
809 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
810 if (context->get_caps_lock_mode()) {
811 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
814 key_event_desc.key_value = coordinate->key_value[shift_index][0];
815 key_event_desc.key_event = coordinate->key_event[shift_index][0];
817 key_event_desc.key_value = coordinate->long_key_value;
818 key_event_desc.key_event = coordinate->long_key_event;
820 key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
822 key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
823 key_event_desc.touch_id = touch_id;
824 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
825 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
826 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
828 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
830 SCLEventReturnType processed = handler->on_event_drag_state_changed(key_event_desc);
832 /* Only if the handler didn't return SCL_EVENT_DONE */
833 if (processed == SCL_EVENT_PASS_ON) {
834 SclRectangle popupRect;
835 SclRectangle baseWndRect;
836 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
837 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
838 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
840 SclNotiPopupOpeningDesc desc;
841 desc.ui_event_desc = &key_event_desc;
842 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
843 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
844 sclint popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
845 SCLDisplayMode display_mode = context->get_display_mode();
847 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
848 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
849 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
850 SclLayout *layout = NULL;
851 sclshort popupLayoutId =
852 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
854 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
855 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
856 layout = &sclres_layout[popupLayoutId];
859 //popupRect.width = utils->get_scale_x(layout->width);
860 //popupRect.height= utils->get_scale_y(layout->height);
861 popupRect.width = layout->width;
862 popupRect.height= layout->height;
864 SclWindowOpener opener;
865 opener.window = window;
866 opener.key = key_index;
868 sclwindow popup_window = windows->open_popup(
873 coordinate->popup_type,
874 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
875 sclres_input_mode_configure[popup_input_mode].use_dim_window,
876 coordinate->extract_offset_x,
877 coordinate->extract_offset_y,
878 sclres_input_mode_configure[popup_input_mode].timeout
881 SclNotiPopupOpenedDesc opened_desc;
882 opened_desc.ui_event_desc = &key_event_desc;
883 opened_desc.input_mode = desc.input_mode;
884 opened_desc.window = popup_window;
885 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
887 windows->hide_window(windows->get_magnifier_window());
888 _play_tts_for_input_mode_name(popup_input_mode);
894 } else if (coordinate->long_key_value) {
895 if (strlen(coordinate->long_key_value) > 0) {
896 if (windows->is_base_window(window)) {
897 state->set_cur_action_state(ACTION_STATE_BASE_LONGKEY);
899 state->set_cur_action_state(ACTION_STATE_POPUP_LONGKEY);
903 PSclMagnifierWndConfigure magnifier_configure = NULL;
904 if (sclres_manager) {
905 magnifier_configure = sclres_manager->get_magnifier_configure();
907 if (coordinate->use_long_key_magnifier && magnifier_configure) {
908 CSCLUtils *utils = CSCLUtils::get_instance();
909 SclPoint pos = {0,0};
911 const SclLayout* layout = cache->get_cur_layout(window);
913 sclint scnWidth, scnHeight;
914 utils->get_screen_resolution(&scnWidth, &scnHeight);
916 //SclWindowContext *window_context = windows->get_window_context(window, TRUE);
917 SclWindowContext *window_context = windows->get_window_context(window);
918 if (window_context) {
919 pos.x = window_context->geometry.x + (coordinate->x + (coordinate->width / 2)) -
920 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
921 pos.y = window_context->geometry.y + coordinate->y -
922 magnifier_configure->height * utils->get_custom_scale_rate_y();
924 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
925 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
927 if (pos.x > scnWidth +
928 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
929 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
931 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
932 magnifier_configure->width * utils->get_custom_scale_rate_x();
934 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
935 pos.x += coordinate->magnifier_offset_x;
936 pos.y += coordinate->magnifier_offset_y;
937 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
938 windows->update_window(windows->get_magnifier_window());
939 windows->show_window(windows->get_magnifier_window(),TRUE);
943 SclUIEventDesc key_event_desc;
944 key_event_desc.key_type = coordinate->long_key_type;
945 key_event_desc.key_value = coordinate->long_key_value;
946 key_event_desc.key_event = coordinate->long_key_event;
947 key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
949 key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
950 key_event_desc.touch_id = touch_id;
951 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
952 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
953 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
955 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
957 handler->on_event_key_clicked(key_event_desc);
963 context->set_cur_key_modifier(touch_id, KEY_MODIFIER_LONGKEY);
966 /* Longkey processing in here */
971 CSCLController::process_button_repeat_pressed_event(sclwindow window, sclbyte key_index,
972 scltouchdevice touch_id, sclboolean actual_event)
975 CSCLContext *context = CSCLContext::get_instance();
976 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
977 CSCLWindows *windows = CSCLWindows::get_instance();
978 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
980 if (context && cache && windows && handler) {
981 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
983 SCLShiftState shift_index = context->get_shift_state();
984 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
985 if (context->get_caps_lock_mode()) {
986 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
990 switch (coordinate->button_type) {
991 case BUTTON_TYPE_NORMAL:
992 case BUTTON_TYPE_GRAB:
993 case BUTTON_TYPE_SELFISH:
994 case BUTTON_TYPE_DIRECTION:
995 case BUTTON_TYPE_RELATIVE_DIRECTION: {
996 /* This is for enabling backspace key in search layout*/
997 //if (coordinate->key_type != KEY_TYPE_MODECHANGE && coordinate->key_type != KEY_TYPE_COMPOSITION) {
998 //if (coordinate->key_type != KEY_TYPE_MODECHANGE || coordinate->key_event[0][0] == MVK_BackSpace) {
999 if (coordinate->key_type != KEY_TYPE_MODECHANGE) {
1000 sclulong repeatKeyEvent = coordinate->key_event[shift_index][0];
1002 /* In case of Delete key, Change from Char deletion to Word deletion
1003 when the input accelation speed is reached to Max */
1004 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1005 PSclDefaultConfigure default_configure = NULL;
1006 if (sclres_manager) {
1007 default_configure = sclres_manager->get_default_configure();
1009 if (default_configure) {
1010 if (default_configure->use_word_deletion) {
1011 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
1012 if (repeatKeyEvent == MVK_BackSpace &&
1013 interval <= SCL_REPEATKEY_WORD_DELETION_START_DURATION) {
1014 repeatKeyEvent = MVK_3270_DeleteWord;
1019 SclUIEventDesc key_event_desc;
1020 key_event_desc.key_value = coordinate->key_value[shift_index][0];
1021 key_event_desc.key_event = repeatKeyEvent;
1022 key_event_desc.key_type = coordinate->key_type;
1023 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1025 key_event_desc.event_type = EVENT_TYPE_REPEAT;
1026 key_event_desc.touch_id = touch_id;
1027 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1028 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1029 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1031 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1033 handler->on_event_key_clicked(key_event_desc);
1037 case BUTTON_TYPE_UIITEM: break;
1038 case MAX_BUTTON_TYPE: break;
1044 /* Longkey processing in here */
1049 CSCLController::process_button_move_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1050 scltouchdevice touch_id, sclboolean actual_event)
1054 sclboolean ret = FALSE;
1056 CSCLUtils *utils = CSCLUtils::get_instance();
1057 CSCLEvents *events = CSCLEvents::get_instance();
1058 CSCLContext *context = CSCLContext::get_instance();
1059 CSCLWindows *windows = CSCLWindows::get_instance();
1060 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1061 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1062 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1064 SclButtonContext *button_context = NULL;
1066 const SclLayoutKeyCoordinate *coordinate = NULL;
1069 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1070 button_context = cache->get_cur_button_context(window, key_index);
1073 if (button_context && coordinate && feedback && utils && context && handler && cache && events && windows) {
1074 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1075 sclint thresholdX = 0;
1076 sclint thresholdY = 0;
1077 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1078 thresholdX = utils->get_scaled_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1079 thresholdY = utils->get_scaled_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1082 /* First check if this button is enabled in current active sublayout */
1083 sclboolean subLayoutMatch = TRUE;
1084 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1085 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1086 subLayoutMatch = FALSE;
1089 if ( x >= coordinate->x - coordinate->add_hit_left - thresholdX &&
1090 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX&&
1091 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1092 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1096 SCLShiftState shift_index = context->get_shift_state();
1097 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1098 if (context->get_caps_lock_mode()) {
1099 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1102 const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1104 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1105 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1106 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1107 const SclLayoutKeyCoordinate *pressed_coordinate =
1108 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1110 if (pressed_context == NULL || pressed_coordinate == NULL) {
1114 if (key_index != pressed_key || window != pressed_window ) {
1115 /* When the focus has moved to another button, destroy all the timers */
1116 events->destroy_all_timer();
1118 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1120 const scl16 uniqId = utils->get_unique_id();
1121 context->set_cur_pressed_event_id(touch_id, uniqId);
1122 /* Special routine for autopopup */
1123 if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
1124 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
1126 /* for long key & repeat key */
1127 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
1130 context->set_cur_pressed_window(touch_id, window);
1131 context->set_cur_pressed_key(touch_id, key_index);
1133 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
1135 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1136 PSclMagnifierWndConfigure magnifier_configure = NULL;
1137 if (sclres_manager) {
1138 magnifier_configure = sclres_manager->get_magnifier_configure();
1140 if (showMagnifier && magnifier_configure) {
1141 SclPoint pos = {0,0};
1142 /* calculates x position to be set */
1143 pos.x = (coordinate->x + (coordinate->width / 2)) -
1144 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
1146 /* calculates y position to be set */
1147 sclint scnWidth, scnHeight;
1148 utils->get_screen_resolution(&scnWidth, &scnHeight);
1150 pos.y = (scnHeight - layout->height) + coordinate->y -
1151 magnifier_configure->height * utils->get_custom_scale_rate_y();
1153 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
1154 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
1156 if (pos.x > scnWidth +
1157 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1158 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
1160 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1161 magnifier_configure->width * utils->get_custom_scale_rate_x();
1163 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1164 if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
1165 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
1166 windows->update_window(windows->get_magnifier_window());
1171 feedback->button_moved(window, key_index);
1173 button_context->state = BUTTON_STATE_PRESSED;
1174 if (pressed_context) {
1175 /* But, if this button should be in pressed state in other multitouch id, do not initialize it */
1176 sclboolean found = FALSE;
1177 for(sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1178 SclUIEventDesc desc;
1179 context->get_multi_touch_event(loop, &desc);
1180 if (desc.touch_id != touch_id) {
1181 MultiTouchContext *multi_touch_context =
1182 context->find_multi_touch_context(desc.touch_id);
1183 if (multi_touch_context) {
1184 if (multi_touch_context->cur_pressed_window == pressed_window &&
1185 multi_touch_context->cur_pressed_key == pressed_key) {
1192 pressed_context->state = BUTTON_STATE_NORMAL;
1195 /* If the window doesn't get exposed before corresponding release event,
1196 * the inverted state of a button will never be drawn onto screen.
1197 * To prevent such a case, we draw the inverted state of button forcefully and directly,
1198 * without waiting for expose event */
1199 /* Redrawing pressed button does not work properly, commented out */
1201 CSCLGraphics *grps = CSCLGraphics::get_instance();
1202 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1203 scldrawctx draw_ctx;
1204 if (pressed_window != SCLWINDOW_INVALID && pressed_key != NOT_USED) {
1205 draw_ctx = grps->begin_paint(pressed_window, TRUE);
1206 builder->draw_button(pressed_window, draw_ctx, pressed_key, FALSE);
1207 grps->end_paint(pressed_window, draw_ctx);
1209 draw_ctx = grps->begin_paint(window, TRUE);
1210 builder->draw_button(window, draw_ctx, key_index, TRUE);
1211 grps->end_paint(window, draw_ctx);
1214 switch (coordinate->button_type) {
1215 case BUTTON_TYPE_DRAG: {
1216 SclUIEventDesc key_event_desc;
1217 key_event_desc.key_value = coordinate->key_value[shift_index][0];
1218 key_event_desc.key_event = coordinate->key_event[shift_index][0];
1219 key_event_desc.key_type = coordinate->key_type;
1220 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1222 key_event_desc.event_type = EVENT_TYPE_MOVE;
1223 key_event_desc.touch_id = touch_id;
1224 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1225 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1226 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1228 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1230 if (sclres_manager) {
1231 magnifier_configure = sclres_manager->get_magnifier_configure();
1233 sclboolean processed = handler->on_event_drag_state_changed(key_event_desc);
1234 if (processed && context->get_magnifier_enabled() && magnifier_configure) {
1235 SclPoint zoomwinpos = {0,0};
1236 /* calculates x position to be set */
1237 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
1238 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
1240 /* calculates y position to be set */
1241 sclint scnWidth, scnHeight;
1242 utils->get_screen_resolution(&scnWidth, &scnHeight);
1244 zoomwinpos.y = coordinate->y -
1245 magnifier_configure->height * utils->get_custom_scale_rate_y();
1246 SclWindowContext *window_context = windows->get_window_context(window);
1247 if (window_context) {
1248 zoomwinpos.x += window_context->geometry.x;
1249 zoomwinpos.y += window_context->geometry.y;
1251 if (zoomwinpos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
1252 zoomwinpos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
1254 if (zoomwinpos.x > scnWidth +
1255 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1256 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
1257 zoomwinpos.x = scnWidth +
1258 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1259 magnifier_configure->width * utils->get_custom_scale_rate_x();
1261 zoomwinpos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1262 zoomwinpos.x += coordinate->magnifier_offset_x;
1263 zoomwinpos.y += coordinate->magnifier_offset_y;
1264 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y);
1265 windows->show_window(windows->get_magnifier_window(), 0);
1268 handler->on_event_key_clicked(key_event_desc);
1269 if (!(windows->is_base_window(window))) {
1270 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
1271 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
1272 SclWindowContext *window_context = windows->get_window_context(window);
1273 if (window_context) {
1274 if (window_context->timeout > 0) {
1275 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
1276 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, window_context->timeout, 0, TRUE);
1282 case BUTTON_TYPE_NORMAL: break;
1283 case BUTTON_TYPE_GRAB: break;
1284 case BUTTON_TYPE_SELFISH: break;
1285 case BUTTON_TYPE_MULTITAP: break;
1286 case BUTTON_TYPE_ROTATION: break;
1287 case BUTTON_TYPE_DIRECTION: break;
1288 case BUTTON_TYPE_RELATIVE_DIRECTION: break;
1289 case BUTTON_TYPE_UIITEM: break;
1290 case MAX_BUTTON_TYPE: break;
1295 #ifdef DIRECTLY_DRAW_ON_EVENTS
1296 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1298 if (button_context) {
1299 builder->draw_button(window, NULL, key_index, button_context->state);
1301 if (pressedContext) {
1302 builder->draw_button(pressed_window, NULL, pressed_key, pressedContext->state, TRUE);
1306 windows->update_window(window,
1307 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1308 if (pressed_coordinate) {
1309 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1310 pressed_coordinate->width, pressed_coordinate->height);
1315 //utils->log("Now Moving : %d %d\n", pos.x, pos.y);
1317 /* If the focus went out from our SELFISH button */
1318 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH) {
1319 pressed_context->state = BUTTON_STATE_NORMAL;
1320 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1321 pressed_coordinate->width, pressed_coordinate->height);
1322 /* And if this SELFISH button was the last button pressed */
1323 if (touch_id == context->get_last_touch_device_id()) {
1324 windows->hide_window(windows->get_magnifier_window());
1329 /* If the focus came back into our SELFISH button */
1330 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH && pressed_context->state != BUTTON_STATE_PRESSED) {
1331 pressed_context->state = BUTTON_STATE_PRESSED;
1332 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1333 pressed_coordinate->width, pressed_coordinate->height);
1334 /* And if this SELFISH button was the last button pressed */
1335 if (touch_id == context->get_last_touch_device_id()) {
1336 sclboolean showMagnifier = check_magnifier_available(pressed_window, pressed_key, touch_id);
1338 if (showMagnifier) {
1339 windows->show_window(windows->get_magnifier_window());
1351 CSCLController::process_button_over_event(sclwindow window, sclint x, sclint y, sclbyte key_index)
1355 sclboolean ret = FALSE;
1357 CSCLUtils *utils = CSCLUtils::get_instance();
1358 CSCLEvents *events = CSCLEvents::get_instance();
1359 CSCLContext *context = CSCLContext::get_instance();
1360 CSCLWindows *windows = CSCLWindows::get_instance();
1361 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1362 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1364 SclButtonContext *button_context = NULL;
1366 const SclLayoutKeyCoordinate *coordinate = NULL;
1368 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1369 button_context = cache->get_cur_button_context(window, key_index);
1372 if(button_context && coordinate && feedback && utils && context && cache && events && windows) {
1373 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1374 sclboolean subLayoutMatch = TRUE;
1375 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1376 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1377 subLayoutMatch = FALSE;
1380 if ( x >= coordinate->x - coordinate->add_hit_left &&
1381 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
1382 y >= coordinate->y - coordinate->add_hit_top &&
1383 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
1387 SCLShiftState shift_index = context->get_shift_state();
1388 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1389 if (context->get_caps_lock_mode()) {
1390 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1393 const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1395 sclwindow highlighted_window = context->get_cur_highlighted_window();
1396 scl8 highlighted_key = context->get_cur_highlighted_key();
1397 SclButtonContext *cur_context = cache->get_cur_button_context(window, key_index);
1399 if(cur_context == NULL) {
1402 if (key_index != highlighted_key || window != highlighted_window ) {
1403 printf("%d != %d || %p != %p\n", key_index, highlighted_key, window, highlighted_window);
1405 if (coordinate->key_type != KEY_TYPE_NONE) {
1406 if (context->get_tts_enabled()) {
1407 const sclchar *targetstr = coordinate->hint_string[shift_index][button_context->multikeyIdx];
1408 if (targetstr == NULL) {
1409 targetstr = coordinate->label[shift_index][0];
1411 if (targetstr == NULL) {
1412 targetstr = coordinate->key_value[shift_index][button_context->multikeyIdx];
1414 /*if(state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
1415 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ) {
1416 targetstr = coordinate->long_key_value;
1418 const sclchar *sayit = cache->find_substituted_string(targetstr);
1419 utils->play_tts(sayit);
1424 context->set_cur_highlighted_window(window);
1425 context->set_cur_highlighted_key(key_index);
1433 CSCLController::get_drag_key_modifier(sclint deltax, sclint deltay, sclfloat dist, sclboolean check_farthest,
1434 scltouchdevice touch_id, sclbyte extra_option) {
1438 SCLKeyModifier modifier;
1441 CSCLContext *context = CSCLContext::get_instance();
1442 SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1445 double theta = atan2(deltay , (deltax ? deltax : 1)); /* Avoid divide by 0 exception */
1446 sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
1447 SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
1448 if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS ||
1449 extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1450 extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN) { /* 8 directions */
1451 /* If the theta is below 0, the direction is upward since the y coordinate grows downward */
1452 /* The below angle values are customized for MoAKey, need to provide customizing API */
1453 DIRECTIONINFO info[] = {
1454 {-8 * (M_PI / 8), -7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1455 {-7 * (M_PI / 8), -5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_LEFT},
1456 {-5 * (M_PI / 8), -2.7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP},
1457 {-2.7 * (M_PI / 8), -1.5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_RIGHT},
1458 {-1.5 * (M_PI / 8), 1 * (M_PI / 8), KEY_MODIFIER_DIRECTION_RIGHT},
1459 { 1 * (M_PI / 8), 3 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_RIGHT},
1460 { 3 * (M_PI / 8), 5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN},
1461 { 5 * (M_PI / 8), 7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_LEFT},
1462 { 7 * (M_PI / 8), 8 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1464 for (size_t loop = 0; loop < sizeof(info) / sizeof(DIRECTIONINFO); loop++) {
1465 if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1466 key_modifier = info[loop].modifier;
1469 } else { /* 4 directions */
1470 /* If the state was dragging to one of 4 directions and the final release point is
1471 * far enough from inital press point, and the angle is in between out predefined angle value */
1472 if (extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE &&
1473 cur_drag_state != SCL_DRAG_STATE_NONE && cur_drag_state != SCL_DRAG_STATE_INVALID &&
1474 dist > SCL_DRAG_CURVE_RECOG_DIST &&
1475 ratio > (1 / SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) &&
1476 ratio < SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) {
1477 if (cur_drag_state == SCL_DRAG_STATE_DOWN) {
1478 if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_RIGHT;
1479 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_LEFT;
1481 if (cur_drag_state == SCL_DRAG_STATE_UP) {
1482 if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_RIGHT;
1483 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_LEFT;
1485 if (cur_drag_state == SCL_DRAG_STATE_LEFT) {
1486 if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_DOWN;
1487 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_UP;
1489 if (cur_drag_state == SCL_DRAG_STATE_RIGHT) {
1490 if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_DOWN;
1491 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_UP;
1494 DIRECTIONINFO info[] = {
1495 {-4 * (M_PI / 4), -3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1496 {-3 * (M_PI / 4), -1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_UP},
1497 {-1 * (M_PI / 4), 1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_RIGHT},
1498 { 1 * (M_PI / 4), 3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_DOWN},
1499 { 3 * (M_PI / 4), 4 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1501 for (size_t loop = 0; loop < sizeof(info) / sizeof(DIRECTIONINFO); loop++) {
1502 if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1503 key_modifier = info[loop].modifier;
1509 if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1510 extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_LONG) {
1511 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1512 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1513 key_modifier = (SCLKeyModifier)(key_modifier + 8); // Add LONG attribute;
1516 if (check_farthest || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
1517 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1518 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1519 key_modifier = (SCLKeyModifier)(key_modifier + 16); // Add RETURN attribute;
1524 return key_modifier;
1528 CSCLController::process_button_release_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1529 scltouchdevice touch_id, sclboolean actual_event)
1533 sclboolean ret = FALSE;
1534 sclboolean redraw = FALSE;
1535 sclboolean fireEvt = FALSE;
1536 SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1538 static sclwindow lastFiredWin = SCLWINDOW_INVALID;
1539 static sclbyte lastFiredKey = NOT_USED;
1541 CSCLUtils *utils = CSCLUtils::get_instance();
1542 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1543 CSCLWindows *windows = CSCLWindows::get_instance();
1544 CSCLContext *context = CSCLContext::get_instance();
1545 CSCLActionState *state = CSCLActionState::get_instance();
1546 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1547 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1549 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1550 PSclLayout sclres_layout = sclres_manager->get_layout_table();
1551 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
1552 assert(sclres_layout != NULL);
1553 assert(sclres_input_mode_configure != NULL);
1554 SclButtonContext *button_context = NULL;
1555 const SclLayoutKeyCoordinate *coordinate = NULL;
1558 button_context = cache->get_cur_button_context(window, key_index);
1559 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1562 const SclLayoutKeyCoordinate *targetCoordinate = NULL;
1564 if (utils && feedback && windows && context && state && handler && cache && button_context && coordinate) {
1565 scl8 savedInputMode = context->get_input_mode();
1567 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1568 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1571 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1572 /* When calling mouse_release, the seq order of current multitouch events will be changed,
1573 so we put all the multitouch events into a vector and use them afterwards for releasing */
1574 sclboolean finished = FALSE;
1576 sclint multi_touch_context_num = context->get_multi_touch_context_num();
1577 std::vector<SclUIEventDesc> multi_touch_events;
1578 for(loop = 0;loop < multi_touch_context_num;loop++) {
1579 SclUIEventDesc desc;
1580 context->get_multi_touch_event(loop, &desc);
1581 multi_touch_events.push_back(desc);
1583 for(loop = 0;loop < multi_touch_context_num && !finished;loop++) {
1584 SclUIEventDesc desc = multi_touch_events[loop];
1585 if (desc.touch_id != touch_id) {
1586 sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
1587 scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
1588 const SclLayoutKeyCoordinate *cur_pressed_coordinate =
1589 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
1590 if (cur_pressed_coordinate) {
1591 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1592 mouse_release(context->get_cur_moving_window(desc.touch_id),
1593 context->get_cur_moving_point(desc.touch_id).x,
1594 context->get_cur_moving_point(desc.touch_id).y,
1595 desc.touch_id, FALSE);
1605 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1606 sclint thresholdX = 0;
1607 sclint thresholdY = 0;
1609 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1610 thresholdX = utils->get_scaled_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1611 thresholdY = utils->get_scaled_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1615 /* Check if the pressed button's type is directional button */
1616 if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1618 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1620 sclboolean check_farthest = FALSE;
1625 /* If the buttontype is RELATIVE_DIRECTION, get the distance from last move point */
1626 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1627 startx = context->get_prev_moving_point(touch_id).x;
1628 starty = context->get_prev_moving_point(touch_id).y;
1630 startx = context->get_cur_pressed_point(touch_id).x;
1631 starty = context->get_cur_pressed_point(touch_id).y;
1634 sclint deltax = x - startx;
1635 sclint deltay = y - starty;
1637 sclfloat dist = utils->get_distance(x, y, startx, starty);
1638 sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
1639 if (coordinate->is_side_button) {
1640 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
1642 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1643 direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
1645 if (context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN &&
1646 coordinate->button_type != BUTTON_TYPE_RELATIVE_DIRECTION) {
1647 if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
1648 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
1649 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
1650 deltax = context->get_farthest_move_point(touch_id).x - context->get_cur_pressed_point(touch_id).x;
1651 deltay = context->get_farthest_move_point(touch_id).y - context->get_cur_pressed_point(touch_id).y;
1652 dist = utils->get_distance(context->get_farthest_move_point(touch_id), context->get_cur_pressed_point(touch_id));
1653 check_farthest = TRUE;
1656 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1657 key_modifier = context->get_cur_key_modifier(touch_id);
1658 } else if (dist > direction_recog_dist) {
1659 key_modifier = get_drag_key_modifier(deltax, deltay, dist, check_farthest, touch_id, coordinate->extra_option);
1665 /* First check if this button is enabled in current active sublayout */
1666 sclboolean subLayoutMatch = TRUE;
1667 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1668 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1669 subLayoutMatch = FALSE;
1672 /* Check if the event occured inside this button's rectangle */
1673 if ( x >= coordinate->x - coordinate->add_hit_left - thresholdX &&
1674 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX &&
1675 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1676 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1683 feedback->button_released(window, key_index);
1685 /* If this button's index is the same as the one initially pressed */
1686 if (pressed_window == window && pressed_key == key_index) {
1688 targetCoordinate = coordinate;
1690 const SclLayoutKeyCoordinate *pressed_coordinate =
1691 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1693 if (pressed_coordinate) {
1694 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1696 targetCoordinate = pressed_coordinate;
1704 /* In case of mode change buttons, event should be fired only when it was pressed lastly */
1706 if (coordinate->key_type == KEY_TYPE_MODECHANGE) {
1707 if (touch_id != context->get_last_touch_device_id()) {
1713 /* If this key's modifier is LONGKEY, this means the event is already fired so skip this one */
1714 if (context->get_cur_key_modifier(touch_id) == KEY_MODIFIER_LONGKEY) {
1718 /* Don't fire any events if we're in longkey state */
1719 if (state->get_cur_action_state() != ACTION_STATE_BASE_LONGKEY &&
1720 state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
1721 state->get_cur_action_state() != ACTION_STATE_POPUP_LONGKEY &&
1722 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY) {
1723 /* An event occured? */
1725 if (targetCoordinate) {
1726 SCLShiftState shift_index = context->get_shift_state();
1727 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1728 if (context->get_caps_lock_mode()) {
1729 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1732 SclUIEventDesc key_event_desc;
1733 key_event_desc.key_type = targetCoordinate->key_type;
1735 key_event_desc.event_type = EVENT_TYPE_RELEASE;
1736 key_event_desc.touch_id = touch_id;
1737 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1738 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1739 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1741 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1743 switch (targetCoordinate->button_type) {
1744 case BUTTON_TYPE_NORMAL:
1745 case BUTTON_TYPE_GRAB :
1746 case BUTTON_TYPE_SELFISH:
1747 case BUTTON_TYPE_DIRECTION :
1748 case BUTTON_TYPE_RELATIVE_DIRECTION: {
1749 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1750 if (pressed_context) {
1751 if (!(targetCoordinate->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1752 key_event_desc.key_value = targetCoordinate->key_value[shift_index][0];
1753 key_event_desc.key_event = targetCoordinate->key_event[shift_index][0];
1754 key_event_desc.key_modifier = key_modifier;
1755 handler->on_event_key_clicked(key_event_desc);
1760 case BUTTON_TYPE_MULTITAP:
1761 case BUTTON_TYPE_ROTATION: {
1762 if (targetCoordinate->button_type == BUTTON_TYPE_MULTITAP) {
1763 if (window == lastFiredWin && key_index == lastFiredKey) {
1764 key_modifier = KEY_MODIFIER_MULTITAP_REPEAT;
1766 key_modifier = KEY_MODIFIER_MULTITAP_START;
1769 key_modifier = KEY_MODIFIER_NONE;
1771 if (button_context->multikeyIdx < MAX_SIZE_OF_MULTITAP_CHAR) {
1772 key_event_desc.key_value = coordinate->key_value[shift_index][button_context->multikeyIdx];
1773 key_event_desc.key_event = coordinate->key_event[shift_index][button_context->multikeyIdx];
1774 key_event_desc.key_modifier = key_modifier;
1775 handler->on_event_key_clicked(key_event_desc);
1777 /* Check if the multikey index is in valid range, and increase by one */
1778 if (button_context->multikeyIdx >= MAX_SIZE_OF_MULTITAP_CHAR - 1) {
1779 button_context->multikeyIdx = 0;
1781 sclbyte orgindex = button_context->multikeyIdx;
1782 button_context->multikeyIdx = 0;
1783 if (targetCoordinate->key_value[shift_index][orgindex + 1]) {
1784 if (strlen(targetCoordinate->key_value[shift_index][orgindex + 1]) > 0) {
1785 button_context->multikeyIdx = orgindex + 1;
1791 case BUTTON_TYPE_DRAG : {
1794 case BUTTON_TYPE_TOGGLE : {
1795 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1796 if (pressed_context) {
1797 if (!(targetCoordinate->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1798 key_event_desc.key_value = targetCoordinate->key_value[shift_index][0];
1799 key_event_desc.key_event = targetCoordinate->key_event[shift_index][0];
1800 if (pressed_context->toggled) {
1801 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1803 key_event_desc.key_modifier = KEY_MODIFIER_TOGGLED;
1805 if (SCL_EVENT_PASS_ON == handler->on_event_key_clicked(key_event_desc)) {
1806 pressed_context->toggled = !(pressed_context->toggled);
1811 case BUTTON_TYPE_UIITEM: break;
1812 case MAX_BUTTON_TYPE: break;
1816 switch (coordinate->popup_type) {
1817 case POPUP_TYPE_BTN_RELEASE_POPUP:
1818 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE: {
1819 SCLDragState dragstate = context->get_cur_drag_state(touch_id);
1820 sclint popup_input_mode = NOT_USED;
1822 SclNotiPopupOpeningDesc desc;
1823 desc.ui_event_desc = &key_event_desc;
1825 if (scl_check_arrindex(dragstate, SCL_DRAG_STATE_MAX)) {
1826 desc.input_mode = coordinate->popup_input_mode[dragstate];
1827 popup_input_mode = sclres_manager->get_inputmode_id(coordinate->popup_input_mode[dragstate]);
1829 //if (!scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP)) {
1830 if (!scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE)) {
1831 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
1834 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
1835 popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
1836 SCLDisplayMode display_mode = context->get_display_mode();
1838 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
1839 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
1840 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
1841 sclshort popupLayoutId =
1842 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
1843 if (popupLayoutId == NOT_USED){
1844 // deal with NOT_USED
1845 printf("popupLayoutID is not used.\n");
1847 SclLayout *layout = NULL;
1849 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
1850 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
1851 layout = &sclres_layout[popupLayoutId];
1854 SclRectangle popupRect;
1855 SclRectangle baseWndRect;
1856 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
1857 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
1858 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
1860 //popupRect.width = utils->get_scale_x(layout->width);
1861 //popupRect.height= utils->get_scale_y(layout->height);
1862 popupRect.width = layout->width;
1863 popupRect.height= layout->height;
1865 /* Let's make sure this popup window does not go beyond the screen area */
1866 sclint scr_w, scr_h;
1867 utils->get_screen_resolution(&scr_w, &scr_h);
1869 if (popupRect.x + popupRect.width > scr_w) {
1870 popupRect.x = scr_w - popupRect.width;
1872 if (popupRect.y + popupRect.height > scr_h) {
1873 popupRect.y = scr_h - popupRect.height;
1876 SclWindowOpener opener;
1877 opener.window = window;
1878 opener.key = key_index;
1880 sclwindow popup_window = windows->open_popup(
1885 coordinate->popup_type,
1886 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
1887 sclres_input_mode_configure[popup_input_mode].use_dim_window,
1888 coordinate->extract_offset_x,
1889 coordinate->extract_offset_y,
1890 sclres_input_mode_configure[popup_input_mode].timeout
1893 SclNotiPopupOpenedDesc opened_desc;
1894 opened_desc.ui_event_desc = &key_event_desc;
1895 opened_desc.input_mode = desc.input_mode;
1896 opened_desc.window = popup_window;
1897 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
1899 windows->hide_window(windows->get_magnifier_window());
1900 _play_tts_for_input_mode_name(popup_input_mode);
1906 case POPUP_TYPE_AUTO_POPUP:
1907 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG:
1908 case POPUP_TYPE_NONE:
1909 /* Nothing to do in here */
1911 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE: break;
1912 case POPUP_TYPE_BTN_LONGPRESS_POPUP: break;
1913 case MAX_POPUP_TYPE: break;
1918 lastFiredWin = window;
1919 lastFiredKey = key_index;
1922 if (targetCoordinate) {
1923 SCLShiftState shift_index = context->get_shift_state();
1924 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1925 if (context->get_caps_lock_mode()) {
1926 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1929 SclUIEventDesc key_event_desc;
1930 key_event_desc.key_type = targetCoordinate->key_type;
1932 key_event_desc.key_value = targetCoordinate->key_value[shift_index][button_context->multikeyIdx];
1933 key_event_desc.key_event = targetCoordinate->key_event[shift_index][button_context->multikeyIdx];
1934 key_event_desc.key_modifier = key_modifier;
1936 key_event_desc.event_type = EVENT_TYPE_RELEASE;
1937 key_event_desc.touch_id = touch_id;
1938 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1939 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1940 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1942 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1944 handler->on_event_drag_state_changed(key_event_desc);
1948 /* If this button was pressed, initialize the button context regardless of event */
1949 if (button_context->state == BUTTON_STATE_PRESSED) {
1950 /* But, if this button should be in pressed state in other multitouch id, do not initialize */
1951 sclboolean found = FALSE;
1952 for(sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1953 SclUIEventDesc desc;
1954 context->get_multi_touch_event(loop, &desc);
1955 if (desc.touch_id != touch_id) {
1956 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(desc.touch_id);
1957 if (multi_touch_context) {
1958 if (multi_touch_context->cur_pressed_window == window &&
1959 multi_touch_context->cur_pressed_key == key_index) {
1966 button_context->state = BUTTON_STATE_NORMAL;
1971 /* If this button needs to be redrawn */
1973 #ifdef DIRECTLY_DRAW_ON_EVENTS
1974 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1976 builder->draw_button(window, NULL, key_index, button_context->state, TRUE);
1979 if (savedInputMode == context->get_input_mode()) {
1980 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1991 CSCLController::mouse_press(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
1994 sclboolean ret = FALSE;
1996 if (m_input_events_disabled) return FALSE;
1998 //utils->log("Controller::mouse_press : %d %d\n", x, y);
2000 /* Adjust x,y coordinate by touch offset */
2001 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2003 CSCLContext *context = CSCLContext::get_instance();
2004 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2005 CSCLActionState *state = CSCLActionState::get_instance();
2006 CSCLWindows *windows = CSCLWindows::get_instance();
2007 CSCLUtils *utils = CSCLUtils::get_instance();
2009 sclint button_index = NOT_USED;
2010 SclWindowContext *window_context = NULL;
2012 const SclLayout *layout = cache->get_cur_layout(window);
2014 x += layout->mouse_manipulate_x;
2015 y += layout->mouse_manipulate_y;
2017 window_context = windows->get_window_context(window);
2018 /* If the dim window is virtual and currently active, let's just skip this event */
2019 if (windows->is_base_window(window)) {
2020 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2021 if (dim_window_context) {
2022 if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2023 window = windows->get_dim_window();
2024 window_context = dim_window_context;
2030 if (cache && state && windows && context && window_context) {
2031 SCLDisplayMode display_mode = context->get_display_mode();
2032 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2033 PSclDefaultConfigure default_configure = NULL;
2034 if (sclres_manager) {
2035 default_configure = sclres_manager->get_default_configure();
2037 if (default_configure) {
2038 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2041 sclboolean isSubEvent = FALSE;
2042 if (context->get_multi_touch_context_num() > 0) {
2043 SclUIEventDesc desc;
2044 context->get_multi_touch_event(0, &desc);
2045 sclwindow pressed_window = context->get_cur_pressed_window(desc.touch_id);
2046 scl8 pressed_key = context->get_cur_pressed_key(desc.touch_id);
2047 SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2049 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_GRAB_SUB_EVENTS) {
2051 utils->play_vibration(DEFAULT_VIBRATION_STYLE, DEFAULT_VIBRATION_DURATION);
2055 context->create_multi_touch_context(touch_id, isSubEvent);
2056 context->set_cur_pressed_window(touch_id, window);
2057 context->set_cur_pressed_point(touch_id, x, y);
2058 context->set_cur_pressed_time(touch_id);
2059 context->set_cur_moving_window(touch_id, window);
2060 context->set_cur_moving_point(touch_id, x, y);
2061 context->set_last_touch_device_id(touch_id);
2062 context->set_cur_drag_state(touch_id, SCL_DRAG_STATE_NONE);
2063 context->set_cur_key_modifier(touch_id, KEY_MODIFIER_NONE);
2064 for(sclint labelidx = 0;labelidx < MAX_SIZE_OF_LABEL_FOR_ONE;labelidx++) {
2065 context->set_custom_magnifier_label(touch_id, labelidx, NULL);
2068 /* If there is postponed update of button, update it now */
2069 CSCLEvents *events = CSCLEvents::get_instance();
2070 sclwindow last_win = context->get_last_pressed_window();
2071 scl8 last_key = context->get_last_pressed_key();
2072 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2073 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2075 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2078 context->set_prev_pressed_window(touch_id, SCLWINDOW_INVALID);
2079 context->set_prev_pressed_key(touch_id, NOT_USED);
2080 context->set_prev_drag_state(touch_id, SCL_DRAG_STATE_NONE);
2081 context->set_prev_moving_point(touch_id, x, y);
2083 /* Destroy key related timers */
2084 events->destroy_timer(SCL_TIMER_BUTTON_DELAY);
2085 events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2086 events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2087 events->destroy_timer(SCL_TIMER_LONGKEY);
2088 events->destroy_timer(SCL_TIMER_REPEATKEY);
2090 /* Do what has to be done when mouse gets pressed */
2091 handle_engine_signal(SCL_SIG_MOUSE_PRESS, window);
2093 /* Adjust event x and y positions as relative position to the virtual window */
2094 if (window_context) {
2095 /*if (window_context->isVirtual) {
2096 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2097 if (base_window_context) {
2098 x -= (window_context->x - base_window_context->x);
2099 y -= (window_context->y - base_window_context->y);
2105 sclboolean process_finished = FALSE;
2107 /* Iterate all the buttons and inform the event */
2108 sclboolean ended = FALSE;
2109 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2110 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
2111 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2112 if (button_context && coordinate) {
2113 if (!(button_context->used)) {
2115 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2116 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2117 if (process_button_pressed_event(window, x, y, loop, touch_id, actual_event)) {
2118 if (windows->is_base_window(window)) {
2119 state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2121 state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2123 button_index = loop;
2130 /* For covering a missing area about 1 pixel */
2132 for (int loop = 0;loop < MAX_KEY;loop++) {
2133 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
2134 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2135 if (button_context && coordinate) {
2136 if (!(button_context->used)) {
2138 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2139 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2140 if (process_button_pressed_event(window, x+1, y+1, loop, touch_id, actual_event)) {
2141 if (windows->is_base_window(window)) {
2142 state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2144 state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2146 button_index = loop;
2156 if (windows->is_base_window(window)) {
2157 process_finished = TRUE;
2158 } else if (button_index != NOT_USED) {
2159 process_finished = TRUE;
2161 const SclLayout *layout = cache->get_cur_layout(window);
2163 if (layout->use_sw_background && layout->bg_color.a == 0) {
2164 /* If we could not find appropriate button in this popup window and the popup is transparent */
2165 SclWindowContext *base_window_context =
2166 windows->get_window_context(windows->get_base_window());
2167 if (base_window_context) {
2168 x = (window_context->geometry.x + x - base_window_context->geometry.x);
2169 y = (window_context->geometry.y + y - base_window_context->geometry.y);
2171 window = windows->get_base_window();
2173 process_finished = TRUE;
2176 process_finished = TRUE;
2179 } while (!process_finished);
2182 sclwindow skip_window = window;
2183 if (ret && button_index != NOT_USED) {
2184 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, button_index);
2186 sclboolean dont_close_popup = FALSE;
2187 if (coordinate->dont_close_popup) {
2188 dont_close_popup = TRUE;
2190 /* If the button's popup type is drag type, the opened popup could be the one opened by this press event */
2191 if (coordinate->popup_type == POPUP_TYPE_BTN_PRESS_POPUP_DRAG) {
2192 /* Check the opened popup was opened by this button */
2193 sclwindow popupwin = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2194 SclWindowContext *popup_window_context = windows->get_window_context(popupwin);
2195 if (popup_window_context) {
2196 SclWindowOpener opener = popup_window_context->opener;
2197 if (opener.window == window && opener.key == button_index) {
2198 dont_close_popup = TRUE;
2202 if (dont_close_popup) {
2203 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2207 windows->close_all_popups(skip_window);
2209 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
2210 if (!(windows->is_base_window(window))) {
2211 if (window_context->timeout > 0) {
2212 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2213 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, window_context->timeout, 0, TRUE);
2215 } else if (skip_window != window) { /* Or the pressed button has dont_close_popup property, reset POPUP_TIMEOUT timer */
2216 //SclWindowContext *skip_window_context = windows->get_window_context(skip_window, FALSE);
2217 SclWindowContext *skip_window_context = windows->get_window_context(skip_window);
2218 if (skip_window_context) {
2219 if (skip_window_context->timeout > 0) {
2220 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2221 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, skip_window_context->timeout, 0, TRUE);
2231 CSCLController::mouse_release(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2234 sclboolean ret = FALSE;
2236 //if (m_input_events_disabled) return FALSE;
2238 //utils->log("Controller::mouse_release : %d %d\n", x, y);
2239 /* Adjust x,y coordinate by touch offset */
2240 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2242 CSCLContext *context = CSCLContext::get_instance();
2243 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2244 CSCLActionState *state = CSCLActionState::get_instance();
2245 CSCLWindows *windows = CSCLWindows::get_instance();
2246 CSCLUtils *utils = CSCLUtils::get_instance();
2247 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2248 CSCLEvents *events = CSCLEvents::get_instance();
2250 sclint button_index = NOT_USED;
2252 if (cache && state && windows && context && utils && handler && events &&
2253 context->find_multi_touch_context(touch_id)) {
2254 const SclLayout *layout = cache->get_cur_layout(window);
2256 x += layout->mouse_manipulate_x;
2257 y += layout->mouse_manipulate_y;
2260 sclwindow skip_window = SCLWINDOW_INVALID;
2261 SCLDisplayMode display_mode = context->get_display_mode();
2263 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2264 PSclDefaultConfigure default_configure = NULL;
2265 if (sclres_manager) {
2266 default_configure = sclres_manager->get_default_configure();
2268 if (default_configure) {
2269 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2272 context->set_cur_moving_window(touch_id, SCLWINDOW_INVALID);
2274 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2275 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2276 //SclWindowContext *window_context = windows->get_window_context(window, TRUE);
2277 SclWindowContext *window_context = windows->get_window_context(window);
2278 /* Adjust event x and y positions as relative position to the virtual window */
2279 if (window_context) {
2280 /*if (window_context->isVirtual) {
2281 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2282 if (base_window_context) {
2283 x -= (window_context->x - base_window_context->x);
2284 y -= (window_context->y - base_window_context->y);
2287 /* If the dim window is virtual and currently active, consider base window's event is occured in dim window */
2288 if (windows->is_base_window(window)) {
2289 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2290 if (dim_window_context) {
2291 if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2292 window = windows->get_dim_window();
2293 window_context = dim_window_context;
2299 /* Iterate all the buttons and inform the event */
2300 sclboolean ended = FALSE;
2302 /* FIXME : The routine below seems to be removed, which was originally requested by Vodafone,
2303 * to slow down the speed of repeat key right before stopping repeatkey event */
2304 /* if (state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY) {
2305 if (m_key_repeated_num > 10) {
2307 process_button_repeat_pressed_event(pressed_window, pressed_key, touch_id);
2312 if (context->get_cur_pressed_window(touch_id) == window) {
2313 if (abs(context->get_cur_pressed_point(touch_id).x - x) > utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD) ||
2314 abs(context->get_cur_pressed_point(touch_id).y - y) > utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD) )
2316 struct timeval t0 = context->get_cur_pressed_time(touch_id);
2318 gettimeofday(&t1, NULL);
2320 etime = ((t1.tv_sec * 1000000 + t1.tv_usec) - (t0.tv_sec * 1000000 + t0.tv_usec))/1000.0;
2321 if (etime < SCL_FLICK_GESTURE_RECOG_TIME) {
2322 SCLDragType drag_type = DRAG_NONE;
2323 if (x > context->get_cur_pressed_point(touch_id).x + utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2324 drag_type = DRAG_RIGHT;
2326 if (x < context->get_cur_pressed_point(touch_id).x - utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2327 drag_type = DRAG_LEFT;
2329 if (y > context->get_cur_pressed_point(touch_id).y + utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2330 drag_type = DRAG_DOWN;
2332 if (y < context->get_cur_pressed_point(touch_id).y - utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2333 drag_type = DRAG_UP;
2335 SclNotiGestureFlickDesc desc;
2336 SclUIEventDesc ui_event_desc;
2337 ui_event_desc.key_value = NULL;
2338 ui_event_desc.key_event = NOT_USED;
2339 ui_event_desc.key_modifier = KEY_MODIFIER_NONE;
2340 ui_event_desc.event_type = EVENT_TYPE_RELEASE;
2341 ui_event_desc.touch_id = touch_id;
2342 ui_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2343 ui_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2344 ui_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2345 ui_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2346 desc.ui_event_desc = &ui_event_desc;
2347 desc.drag_type = drag_type;
2348 if (handler->on_event_notification(SCL_UINOTITYPE_GESTURE_FLICK, &desc)) {
2355 /* FIXME : We should consider this kind of action in general manner, not only specific to autopopup */
2356 /* And also, this kind of implementation only selects button that was highlighted at least once. */
2358 //SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window, FALSE);
2359 SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window);
2360 if (pressed_window_context) {
2361 utils->log("PRESSED CTX : %p %d %d\n", pressed_window,
2362 pressed_window_context->geometry.x, pressed_window_context->geometry.y);
2363 //if (pressedCtx->popuptype == POPUP_TYPE_AUTO_POPUP) {
2364 sclboolean grab_event = FALSE;
2365 const SclLayout *pressed_layout = cache->get_cur_layout(pressed_window);
2366 if (pressed_layout) {
2367 if (pressed_layout->style == LAYOUT_STYLE_POPUP_GRAB) {
2370 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
2372 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
2373 sclboolean in_grab_area = TRUE;
2374 if (pressed_layout->add_grab_left != NOT_USED &&
2375 x < (pressed_window_context->geometry.x - pressed_layout->add_grab_left)) {
2376 in_grab_area = FALSE;
2378 if (pressed_layout->add_grab_right != NOT_USED &&
2379 x > (pressed_window_context->geometry.x + pressed_window_context->geometry.width
2380 + pressed_layout->add_grab_right)) {
2381 in_grab_area = FALSE;
2383 if (pressed_layout->add_grab_top != NOT_USED &&
2384 y < (pressed_window_context->geometry.y - pressed_layout->add_grab_top)) {
2385 in_grab_area = FALSE;
2387 if (pressed_layout->add_grab_bottom != NOT_USED &&
2388 y > (pressed_window_context->geometry.y + pressed_window_context->geometry.height
2389 + pressed_layout->add_grab_bottom)) {
2390 in_grab_area = FALSE;
2393 SclLayoutKeyCoordinate *coord = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2395 x = coord->x + (coord->width / 2);
2396 y = coord->y + (coord->height / 2);
2398 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2399 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, loop);
2400 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2401 if (button_context && coordinate) {
2402 if (!(button_context->used)) {
2404 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2405 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2406 if (process_button_release_event(pressed_window, x, y, loop, touch_id, actual_event)) {
2420 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2421 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2423 /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2424 /* Ignore base window's release event if a popup window is opened */
2425 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2426 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2427 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2428 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2429 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2430 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2431 if (windows->is_base_window(window)) {
2433 /* In case of direction button, the release event on other window should be processed */
2434 if (coordinate && window_context && pressed_window_context) {
2435 if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2436 sclint relx = (window_context->geometry.x + x) - pressed_window_context->geometry.x;
2437 sclint rely = (window_context->geometry.y + y) - pressed_window_context->geometry.y;
2438 if (process_button_release_event(pressed_window, relx, rely, pressed_key, touch_id, actual_event)) {
2439 button_index = pressed_key;
2441 x = coordinate->x + (coordinate->width / 2);
2442 y = coordinate->y + (coordinate->height / 2);
2443 skip_window = pressed_window;
2450 sclboolean process_finished = FALSE;
2452 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(touch_id);
2453 if (multi_touch_context) {
2454 if (!(multi_touch_context->is_sub_event)) {
2455 /* First check if the event occured in pressed key's threshold area */
2456 if (button_context && coordinate && !ended) {
2457 if (button_context->used && button_context->state != BUTTON_STATE_DISABLED) {
2458 if (process_button_release_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
2459 button_index = pressed_key;
2461 x = coordinate->x + (coordinate->width / 2);
2462 y = coordinate->y + (coordinate->height / 2);
2466 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2467 SclButtonContext *cur_context = cache->get_cur_button_context(window, loop);
2468 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2469 if (cur_context && cur_coordinate) {
2470 if (!(cur_context->used)) {
2472 } else if (cur_context->state != BUTTON_STATE_DISABLED &&
2473 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
2474 if (window != pressed_window || loop != pressed_key) {
2475 if (process_button_release_event(window, x, y, loop, touch_id, actual_event)) {
2476 button_index = loop;
2484 process_finished = TRUE;
2486 SclUIEventDesc key_event_desc;
2487 key_event_desc.key_value = NULL;
2488 key_event_desc.key_event = NOT_USED;
2489 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
2490 key_event_desc.event_type = EVENT_TYPE_NONE;
2491 key_event_desc.touch_id = touch_id;
2492 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2493 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2494 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2496 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2498 handler->on_event_key_clicked(key_event_desc);
2502 /* For covering a missing area about 1 pixel */
2506 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2507 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2508 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2509 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2510 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2511 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2512 if (windows->is_base_window(window)) {
2517 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2518 SclButtonContext *cur_context = cache->get_cur_button_context(window, loop);
2519 if (cur_context && coordinate) {
2520 if (!(cur_context->used)) {
2523 } else if (cur_context->state != BUTTON_STATE_DISABLED &&
2524 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2525 if (process_button_release_event(window, x+1, y+1, loop, touch_id)) {
2526 button_index = loop;
2534 if (windows->is_base_window(window)) {
2535 process_finished = TRUE;
2536 } else if (button_index != NOT_USED) {
2537 process_finished = TRUE;
2539 if (layout && layout->use_sw_background && layout->bg_color.a == 0) {
2540 /* If we could not find appropriate button in this popup window and the popup is transparent */
2541 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2542 if (base_window_context) {
2543 x = (window_context->geometry.x + x - base_window_context->geometry.x);
2544 y = (window_context->geometry.y + y - base_window_context->geometry.y);
2546 window = windows->get_base_window();
2548 process_finished = TRUE;
2551 } while (!process_finished);
2553 if (windows->is_base_window(window)) {
2554 state->set_cur_action_state(ACTION_STATE_BASE_INIT);
2556 state->set_cur_action_state(ACTION_STATE_POPUP_INIT);
2559 /* Restore previously pressed button's context and redraw it */
2560 if (button_context && coordinate) {
2561 button_context->state = BUTTON_STATE_NORMAL;
2562 /* Commented below line to postpone some of the feedback for releasing */
2563 //windows->update_window(pressed_window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2566 /* If there is postponed update of button, update it now */
2567 sclwindow last_win = context->get_last_pressed_window();
2568 scl8 last_key = context->get_last_pressed_key();
2569 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2570 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2572 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2576 /* To postpone some of the feedback for releasing */
2577 context->set_last_pressed_key(context->get_cur_pressed_key(touch_id));
2578 context->set_last_pressed_window(context->get_cur_pressed_window(touch_id));
2580 /* Do what has to be done when mouse gets released */
2581 sclboolean signaled = FALSE;
2583 switch (coordinate->popup_type) {
2584 case POPUP_TYPE_BTN_RELEASE_POPUP:
2585 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
2586 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
2587 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
2589 /* Fix me : We should consider z-order */
2590 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2591 handle_engine_signal(SCL_SIG_MOUSE_RELEASE, skip_window);
2595 case POPUP_TYPE_NONE: break;
2596 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: break;
2597 case POPUP_TYPE_AUTO_POPUP: break;
2598 case MAX_POPUP_TYPE: break;
2603 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
2604 window_context = windows->get_window_context(window);
2605 if (window_context) {
2606 if (window_context->popup_type == POPUP_TYPE_BTN_RELEASE_POPUP ||
2607 window_context->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP) {
2608 /* Don't close window if the clicked button is a child of ReleasePopup window */
2609 skip_window = window;
2610 handle_engine_signal(SCL_SIG_MOUSE_RELEASE, window);
2615 handle_engine_signal(SCL_SIG_MOUSE_RELEASE);
2619 context->set_cur_pressed_key(touch_id, NOT_USED);
2620 context->set_cur_pressed_window(touch_id, SCLWINDOW_INVALID);
2622 if (ret && button_index != NOT_USED) {
2623 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, button_index);
2624 if (cur_coordinate) {
2625 if (cur_coordinate->dont_close_popup) {
2626 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2630 if (pressed_window == windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP)) {
2631 if (pressed_window_context) {
2632 if (pressed_window_context->popup_type != POPUP_TYPE_BTN_RELEASE_POPUP_ONCE &&
2633 pressed_window_context->popup_type != POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE &&
2634 pressed_window_context->popup_type != POPUP_TYPE_AUTO_POPUP &&
2635 pressed_window_context->popup_type != POPUP_TYPE_BTN_PRESS_POPUP_DRAG)
2637 skip_window = pressed_window;
2642 windows->close_all_popups(skip_window);
2644 /* Destroy key related timers */
2645 events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2646 events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2647 events->destroy_timer(SCL_TIMER_LONGKEY);
2648 events->destroy_timer(SCL_TIMER_REPEATKEY);
2650 /* If there are more than 1 active multitouch ids, don't play button_delay trick */
2651 if (context->get_multi_touch_context_num() == 1) {
2652 /* To postpone some of the feedback for releasing */
2653 events->create_timer(SCL_TIMER_BUTTON_DELAY, m_button_delay_duration, 0);
2655 last_win = context->get_last_pressed_window();
2656 last_key = context->get_last_pressed_key();
2658 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2659 const SclLayoutKeyCoordinate* last_coordinate = cache->get_cur_layout_key_coordinate(last_win, last_key);
2660 if (last_coordinate) {
2661 windows->update_window(last_win,
2662 last_coordinate->x, last_coordinate->y, last_coordinate->width, last_coordinate->height);
2666 windows->hide_window(windows->get_magnifier_window());
2667 context->set_last_pressed_window(SCLWINDOW_INVALID);
2668 context->set_last_pressed_key(NOT_USED);
2673 if (touch_id == context->get_last_touch_device_id()) {
2674 context->set_last_touch_device_id(SCLTOUCHDEVICE_INVALID);
2676 context->destroy_multi_touch_context(touch_id);
2682 SCLDragState get_drag_state(sclint deltax, sclint deltay)
2684 SCLDragState ret = SCL_DRAG_STATE_MAX;
2686 sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
2687 /* If tan(theta) is smaller than our predefined value */
2688 if (ratio <= (1 / SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE)) {
2690 ret = SCL_DRAG_STATE_RIGHT;
2692 ret = SCL_DRAG_STATE_LEFT;
2694 } /* If tan(theta) is bigger than our predefined value */
2695 else if (ratio >= SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE) {
2697 ret = SCL_DRAG_STATE_DOWN;
2699 ret = SCL_DRAG_STATE_UP;
2702 ret = SCL_DRAG_STATE_INVALID;
2709 CSCLController::mouse_move(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2712 sclboolean ret = FALSE;
2714 if (m_input_events_disabled) return FALSE;
2716 //utils->log("Controller::mouse_move : %d %d\n", x, y);
2718 /* Adjust x,y coordinate by touch offset */
2719 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2721 CSCLContext *context = CSCLContext::get_instance();
2722 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2723 CSCLActionState *state = CSCLActionState::get_instance();
2724 CSCLWindows *windows = CSCLWindows::get_instance();
2725 CSCLEvents *events = CSCLEvents::get_instance();
2726 CSCLUtils *utils = CSCLUtils::get_instance();
2727 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2728 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2729 PSclModifierDecoration sclres_modifier_decoration = sclres_manager->get_modifier_decoration_table();
2730 assert(sclres_modifier_decoration != NULL);
2732 if (cache && state && windows && context && utils && adjustment && sclres_manager) {
2733 const SclLayout *layout = cache->get_cur_layout(window);
2735 x += layout->mouse_manipulate_x;
2736 y += layout->mouse_manipulate_y;
2739 if (!(context->find_multi_touch_context(touch_id))) return FALSE;
2741 PSclDefaultConfigure default_configure = sclres_manager->get_default_configure();
2742 if (default_configure) {
2743 SCLDisplayMode display_mode = context->get_display_mode();
2744 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2747 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
2748 SclWindowContext *window_context = windows->get_window_context(window);
2749 /* Adjust event x and y positions as relative position to the virtual window */
2750 if (window_context) {
2751 /*if (window_context->isVirtual) {
2752 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2753 if (base_window_context) {
2754 x -= (window_context->x - base_window_context->x);
2755 y -= (window_context->y - base_window_context->y);
2758 /* If the dim window is virtual and currently active, let's just skip this event */
2759 if (windows->is_base_window(window)) {
2760 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2761 if (dim_window_context) {
2762 if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2767 /* If the pressed event was occured in dim window, let's just skip this move event */
2768 if (context->get_last_pressed_window() == windows->get_dim_window()) {
2773 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2774 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2775 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2776 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2778 /* If the multitouch type is SETTLE_PREVIOUS and is not the last touch device, let's ignore move events */
2780 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
2781 if (context->get_last_touch_device_id() != touch_id) {
2787 context->set_cur_moving_point(touch_id, x, y);
2788 context->set_cur_moving_window(touch_id, window);
2790 /* If in longkey state, do not process, just return */
2791 if (state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
2792 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
2793 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
2794 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY) {
2797 /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2798 /* And if the event occured in popup window, don't come back to base window */
2799 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2800 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2801 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2802 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2803 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2804 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2805 if (windows->is_base_window(window)) {
2810 /* FIXME : Add a condition to skip this code if longkey timer is not active */
2811 /* If the mouse has moved out of threshold value of longkey keypress area, destroy longkey timer */
2812 if (m_long_key_cancel_distance > 0) {
2813 sclfloat dist = utils->get_distance(x, y,
2814 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2815 if (m_long_key_cancel_distance < dist) {
2816 events->destroy_timer(SCL_TIMER_LONGKEY);
2820 if (windows->is_base_window(window)) {
2821 state->set_cur_action_state(ACTION_STATE_BASE_MOVING);
2823 state->set_cur_action_state(ACTION_STATE_POPUP_MOVING);
2826 /* Iterate all the buttons and inform the event */
2827 sclboolean ended = FALSE;
2829 /* Check farthest move point and update it */
2832 if (pressed_window != window) {
2833 //SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window, FALSE);
2834 SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window);
2835 if (window_context && pressed_window_context) {
2836 originx = (window_context->geometry.x - pressed_window_context->geometry.x) + x;
2837 originy = (window_context->geometry.y - pressed_window_context->geometry.y) + y;
2840 sclint startx = originx;
2841 sclint starty = originy;
2843 /* Check if we should recognize drag curve */
2845 startx = context->get_cur_pressed_point(touch_id).x;
2846 starty = context->get_cur_pressed_point(touch_id).y;
2847 sclint deltax = originx - startx;
2848 sclint deltay = originy - starty;
2849 sclfloat approximate_dist = utils->get_approximate_distance(originx, originy, startx, starty);
2851 sclboolean update_magnifier = FALSE;
2852 sclboolean drag_state_changed = FALSE;
2853 SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
2854 SCLDragState next_drag_state = SCL_DRAG_STATE_NONE;
2855 sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
2856 if (coordinate->is_side_button) {
2857 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
2860 if (coordinate->button_type == BUTTON_TYPE_DIRECTION) {
2861 /* Do not check farthest move point if current drag state is SCL_DRAG_STATE_RETURN */
2862 if (context->get_cur_drag_state(touch_id) != SCL_DRAG_STATE_RETURN) {
2863 if (approximate_dist > context->get_farthest_move_dist(touch_id)) {
2864 context->set_farthest_move_point(touch_id, originx, originy);
2868 if (cur_drag_state == SCL_DRAG_STATE_RETURN) {
2869 direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_RETURN;
2870 } else if (cur_drag_state != SCL_DRAG_STATE_NONE) {
2871 direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_OTHER;
2873 if (approximate_dist > direction_recog_dist) {
2874 next_drag_state = get_drag_state(deltax, deltay);
2875 /* Disable longkey if dragging is recognized */
2876 events->destroy_timer(SCL_TIMER_LONGKEY);
2878 if (cur_drag_state != next_drag_state) {
2879 drag_state_changed = TRUE;
2881 if (cur_drag_state == SCL_DRAG_STATE_NONE) {
2882 //if (nextDragState != SCL_DRAG_STATE_INVALID) {
2883 cur_drag_state = next_drag_state;
2885 } else if (cur_drag_state != next_drag_state) {
2886 if (next_drag_state == SCL_DRAG_STATE_NONE) {
2887 cur_drag_state = SCL_DRAG_STATE_RETURN;
2889 cur_drag_state = next_drag_state;
2893 context->set_cur_drag_state(touch_id, cur_drag_state);
2894 sclboolean check_farthest = FALSE;
2895 sclshort display = context->get_display_mode();
2896 if (!scl_check_arrindex(display, DISPLAYMODE_MAX)) display = 0;
2897 sclfloat dist = utils->get_distance(originx, originy,
2898 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2899 if (dist < direction_recog_dist && context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
2900 if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
2901 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
2902 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
2903 deltax = context->get_farthest_move_point(touch_id).x -
2904 context->get_cur_pressed_point(touch_id).x;
2905 deltay = context->get_farthest_move_point(touch_id).y -
2906 context->get_cur_pressed_point(touch_id).y;
2907 dist = utils->get_distance(context->get_farthest_move_point(touch_id),
2908 context->get_cur_pressed_point(touch_id));
2909 check_farthest = TRUE;
2912 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist,
2913 check_farthest, touch_id, coordinate->extra_option);
2914 if (dist > direction_recog_dist) {
2915 context->set_cur_key_modifier(touch_id, key_modifier);
2917 /* If this button needs to be decorated when dragged */
2918 if (coordinate->modifier_decorator) {
2919 const SclModifierDecoration *decoration = NULL;
2921 /*if (scl_check_arrindex(coordinate->modifier_decorator,
2922 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
2923 scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
2924 if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
2925 if (sclres_modifier_decoration[decoration_id].valid) {
2926 decoration = &(sclres_modifier_decoration[decoration_id]);
2929 /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
2931 if (decoration->bg_image_path[display][key_modifier]) {
2932 windows->update_window(window,
2933 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2937 if (dist > direction_recog_dist) {
2938 SclUIEventDesc desc;
2939 SCLShiftState shift_index = context->get_shift_state();
2940 if (context->get_caps_lock_mode()) {
2941 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
2943 desc.key_type = coordinate->key_type;
2944 desc.key_value = coordinate->key_value[shift_index][0];
2945 desc.key_event = coordinate->key_event[shift_index][0];
2946 desc.event_type = EVENT_TYPE_MOVE;
2947 desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2948 desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2949 desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2950 desc.key_modifier = key_modifier;
2952 if (handler->on_event_drag_state_changed(desc) && context->get_magnifier_enabled()) {
2953 update_magnifier = TRUE;
2956 } else if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2957 if (cur_drag_state != SCL_DRAG_STATE_NONE) {
2958 startx = context->get_prev_moving_point(touch_id).x;
2959 starty = context->get_prev_moving_point(touch_id).y;
2960 approximate_dist = utils->get_approximate_distance(originx, originy, startx, starty);
2961 direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
2963 deltax = originx - startx;
2964 deltay = originy - starty;
2965 //printf("DIST : %f, RECOG : %f\n", dist, direction_recog_dist);
2966 if (approximate_dist > direction_recog_dist) {
2967 next_drag_state = get_drag_state(deltax, deltay);
2968 /* Disable longkey if dragging is recognized */
2969 events->destroy_timer(SCL_TIMER_LONGKEY);
2971 if (cur_drag_state != next_drag_state) {
2972 drag_state_changed = TRUE;
2974 if (next_drag_state != SCL_DRAG_STATE_NONE) {
2975 cur_drag_state = next_drag_state;
2977 context->set_cur_drag_state(touch_id, cur_drag_state);
2979 startx = context->get_farthest_move_point(touch_id).x;
2980 starty = context->get_farthest_move_point(touch_id).y;
2981 deltax = originx - startx;
2982 deltay = originy - starty;
2983 sclfloat dist_farthest = utils->get_approximate_distance(originx, originy, startx, starty);
2984 printf("%d %d %d %d %f, %d %d\n", originx, originy, startx, starty, dist_farthest, cur_drag_state, next_drag_state);
2985 /* Let's see how much we are away from the last farthest point */
2986 sclfloat diffdir_recog_dist = SCL_DIRECTION_RELATIVE_DIFFDIR_RECOG_DIST * utils->get_smallest_scale_rate();
2987 /* If we moved certain amount from the point where direction changed, process drag state change routine */
2988 if (dist_farthest > diffdir_recog_dist || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_NONE) {
2989 sclshort display = context->get_display_mode();
2990 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist_farthest,
2991 FALSE, touch_id, coordinate->extra_option);
2992 context->set_cur_key_modifier(touch_id, key_modifier);
2993 /* If this button needs to be decorated when dragged */
2994 if (coordinate->modifier_decorator) {
2995 const SclModifierDecoration *decoration = NULL;
2997 /*if (scl_check_arrindex(coordinate->modifier_decorator,
2998 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
2999 scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
3000 if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
3001 if (sclres_modifier_decoration[decoration_id].valid) {
3002 decoration = &(sclres_modifier_decoration[decoration_id]);
3005 /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
3007 if (decoration->bg_image_path[display][key_modifier]) {
3008 windows->update_window(window,
3009 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3014 SclUIEventDesc desc;
3015 SCLShiftState shift_index = context->get_shift_state();
3016 if (context->get_caps_lock_mode()) {
3017 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
3019 desc.key_type = coordinate->key_type;
3020 desc.key_value = coordinate->key_value[shift_index][0];
3021 desc.key_event = coordinate->key_event[shift_index][0];
3022 desc.event_type = EVENT_TYPE_MOVE;
3023 desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
3024 desc.mouse_current_point = context->get_cur_moving_point(touch_id);
3025 desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
3026 desc.key_modifier = key_modifier;
3028 if (handler->on_event_drag_state_changed(desc) && context->get_magnifier_enabled()) {
3029 update_magnifier = TRUE;
3032 context->set_prev_moving_point(touch_id, originx, originy);
3034 if (drag_state_changed) {
3035 /* When the dragging direction changes, save the current position as farthest point for future comparison */
3036 context->set_farthest_move_point(touch_id, originx, originy);
3037 printf("SET_FARTHEST : %d %d %d\n", originx, originy, context->get_cur_drag_state(touch_id));
3041 if (update_magnifier) {
3042 PSclMagnifierWndConfigure magnifier_configure = NULL;
3043 if (sclres_manager) {
3044 magnifier_configure = sclres_manager->get_magnifier_configure();
3047 const SclLayout *base_layout = cache->get_cur_layout(windows->get_base_window());
3048 if (base_layout && magnifier_configure) {
3049 SclPoint zoomwinpos = {0,0};
3050 /* calculates x position to be set */
3051 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
3052 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
3054 /* calculates y position to be set */
3055 sclint scnWidth, scnHeight;
3056 utils->get_screen_resolution(&scnWidth, &scnHeight);
3058 zoomwinpos.y = coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
3059 if (window_context) {
3060 zoomwinpos.x += window_context->geometry.x;
3061 zoomwinpos.y += window_context->geometry.y;
3063 if (zoomwinpos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
3064 zoomwinpos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
3066 if (zoomwinpos.x > scnWidth +
3067 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
3068 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
3069 zoomwinpos.x = scnWidth +
3070 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
3071 magnifier_configure->width * utils->get_custom_scale_rate_x();
3073 zoomwinpos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
3075 zoomwinpos.x += coordinate->magnifier_offset_x;
3076 zoomwinpos.y += coordinate->magnifier_offset_y;
3077 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y);
3078 windows->show_window(windows->get_magnifier_window(), 0);
3083 sclboolean grab_event = FALSE;
3085 if (layout->style == LAYOUT_STYLE_POPUP_GRAB) {
3088 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
3089 if (grab_event && window_context) {
3090 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
3091 sclboolean in_grab_area = TRUE;
3092 if (layout->add_grab_left != NOT_USED && x < -(layout->add_grab_left)) {
3093 in_grab_area = FALSE;
3095 if (layout->add_grab_right != NOT_USED && x >
3096 (window_context->geometry.width + layout->add_grab_right)) {
3097 in_grab_area = FALSE;
3099 if (layout->add_grab_top != NOT_USED && y < -(layout->add_grab_top)) {
3100 in_grab_area = FALSE;
3102 if (layout->add_grab_bottom != NOT_USED && y >
3103 (window_context->geometry.height + layout->add_grab_bottom)) {
3104 in_grab_area = FALSE;
3107 float min_dist = (float)((unsigned int)(-1));
3108 int min_dist_index = NOT_USED;
3109 for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
3110 button_context = cache->get_cur_button_context(window, loop);
3111 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3112 if (button_context && cur_coordinate) {
3113 if (!(button_context->used)) {
3115 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3116 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
3117 float dist = utils->get_approximate_distance(x, y,
3118 cur_coordinate->x + (cur_coordinate->width / 2),
3119 cur_coordinate->y + (cur_coordinate->height / 2));
3120 if (dist < min_dist) {
3121 min_dist_index = loop;
3127 /* When we found the nearest button, generate this event on the button */
3128 if (min_dist_index != NOT_USED) {
3129 const SclLayoutKeyCoordinate *min_coordinate =
3130 cache->get_cur_layout_key_coordinate(window, min_dist_index);
3131 if (min_coordinate) {
3132 x = min_coordinate->x + (min_coordinate->width / 2);
3133 y = min_coordinate->y + (min_coordinate->height / 2);
3134 if (process_button_move_event(window, x, y, min_dist_index, touch_id, actual_event)) {
3141 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(touch_id);
3142 if (multi_touch_context) {
3143 sclint button_index = NOT_USED;
3144 if (!(multi_touch_context->is_sub_event)) {
3145 sclboolean process_finished = FALSE;
3147 /* First check if the event occured in pressed key's threshold area */
3148 if (button_context && coordinate) {
3149 if (pressed_window == window) { // Check only when the window is the one initally pressed
3150 if (button_context->used && button_context->state != BUTTON_STATE_DISABLED) {
3151 if (process_button_move_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
3153 x = coordinate->x + (coordinate->width / 2);
3154 y = coordinate->y + (coordinate->height / 2);
3155 button_index = pressed_key;
3160 for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
3161 button_context = cache->get_cur_button_context(window, loop);
3162 const SclLayoutKeyCoordinate *cur_coordinate =
3163 cache->get_cur_layout_key_coordinate(window, loop);
3164 if (button_context && cur_coordinate) {
3165 if (!(button_context->used)) {
3167 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3168 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
3169 if (window != pressed_window || loop != pressed_key) {
3170 if (process_button_move_event(window, x, y, loop, touch_id, actual_event)) {
3172 button_index = loop;
3179 if (windows->is_base_window(window)) {
3180 process_finished = TRUE;
3181 } else if (button_index != NOT_USED) {
3182 process_finished = TRUE;
3184 const SclLayout *cur_layout = cache->get_cur_layout(window);
3185 if (cur_layout && cur_layout->use_sw_background && cur_layout->bg_color.a == 0) {
3186 /* If we could not find appropriate button in this popup window and the popup is transparent */
3187 SclWindowContext *base_window_context =
3188 windows->get_window_context(windows->get_base_window());
3189 if (base_window_context) {
3190 x = (window_context->geometry.x + x - base_window_context->geometry.x);
3191 y = (window_context->geometry.y + y - base_window_context->geometry.y);
3193 window = windows->get_base_window();
3195 process_finished = TRUE;
3198 } while (!process_finished);
3209 CSCLController::mouse_over(sclwindow window, sclint x, sclint y)
3212 sclboolean ret = FALSE;
3214 if(m_input_events_disabled)
3217 /* Adjust x,y coordinate by touch offset */
3218 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
3219 /* Iterate all the buttons and inform the event */
3221 CSCLContext *context = CSCLContext::get_instance();
3222 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3223 CSCLActionState *state = CSCLActionState::get_instance();
3224 CSCLWindows *windows = CSCLWindows::get_instance();
3225 CSCLUtils *utils = CSCLUtils::get_instance();
3226 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3228 if (cache && state && windows && context && utils && adjustment && sclres_manager) {
3229 const SclLayout *layout = cache->get_cur_layout(window);
3231 x += layout->mouse_manipulate_x;
3232 y += layout->mouse_manipulate_y;
3235 SCLDisplayMode cur_display_mode = context->get_display_mode();
3237 const SclDefaultConfigure *default_configure = sclres_manager->get_default_configure();
3238 if (default_configure) {
3239 adjustment->apply_touch_offset(default_configure->touch_offset_level[cur_display_mode], &x, &y);
3242 /* Iterate all the buttons and inform the event */
3243 sclboolean ended = FALSE;
3245 for (int loop = 0; loop < MAX_KEY && !ended && !ret; loop++) {
3246 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
3247 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3248 if (button_context && coordinate) {
3249 if (!(button_context->used)) {
3251 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3252 coordinate->button_type != BUTTON_TYPE_UIITEM) {
3253 if (process_button_over_event(window, x, y, loop)) {
3266 * Processes a timer event
3267 * If return FALSE, the current timer will be stop
3268 * ID : SCL_LOWORD(data)
3269 * value : SCL_HIWORD(data)
3272 CSCLController::timer_event(const scl32 data)
3275 CSCLWindows *windows = CSCLWindows::get_instance();
3276 CSCLContext *context = CSCLContext::get_instance();
3277 CSCLEvents* events = CSCLEvents::get_instance();
3278 CSCLActionState *state = CSCLActionState::get_instance();
3279 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3280 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3282 scl16 id = SCL_LOWORD(data); /* Timer ID */
3283 scl16 value = SCL_HIWORD(data); /* event unique ID */
3285 if (!windows || !context || !events || !state || !cache || !handler)
3289 case SCL_TIMER_AUTOPOPUP: {
3290 /* Checks whether my event id is availble */
3291 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3292 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3293 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3294 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3295 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3296 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3297 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3298 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3299 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3300 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3301 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3303 /* Ignores if the event id is different */
3304 events->destroy_timer(id);
3308 SclRectangle rect = {0,0,0,0};
3309 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3310 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3312 if (configure_autopopup_window(window, key_index, &rect)) {
3313 /* Let's change out pressed button's state back to normal */
3314 SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
3315 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3317 if (button_context) {
3318 if (button_context->state == BUTTON_STATE_PRESSED) {
3319 button_context->state = BUTTON_STATE_NORMAL;
3321 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3325 /* Hide magnifier window when opening autopopup window */
3326 windows->hide_window(windows->get_magnifier_window());
3328 sclwindow popup_window = SCLWINDOW_INVALID;
3330 SclNotiPopupOpeningDesc desc;
3331 desc.ui_event_desc = NULL;
3332 desc.input_mode = SCL_LAYOUT_AUTOPOPUP_NAME;
3333 if (SCL_EVENT_PASS_ON ==
3334 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
3335 /* Currently, window does not support virtual window */
3336 SclWindowOpener opener;
3337 opener.window = window;
3338 opener.key = key_index;
3340 popup_window = windows->open_popup(
3344 SCL_LAYOUT_AUTOPOPUP, POPUP_TYPE_AUTO_POPUP,
3349 SclNotiPopupOpenedDesc opened_desc;
3350 opened_desc.ui_event_desc = NULL;
3351 opened_desc.input_mode = desc.input_mode;
3352 opened_desc.window = popup_window;
3353 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
3356 windows->hide_window(windows->get_magnifier_window());
3357 _play_tts_for_layout_autopopup_name();
3359 sclwindow moving_window = context->get_cur_moving_window(context->get_last_touch_device_id());
3360 SclPoint moving_point = context->get_cur_moving_point(context->get_last_touch_device_id());
3361 SclWindowContext *moving_window_context = windows->get_window_context(moving_window);
3362 SclWindowContext *popup_window_context = windows->get_window_context(popup_window);
3363 if (moving_window_context && popup_window_context) {
3364 moving_point.x = (moving_window_context->geometry.x - popup_window_context->geometry.x) + moving_point.x;
3365 moving_point.y = (moving_window_context->geometry.y - popup_window_context->geometry.y) + moving_point.y;
3367 //printf("AUTOPOPUP : %d %d\n", moving_point.x, moving_point.y);
3370 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3373 events->destroy_timer(id);
3379 case SCL_TIMER_LONGKEY: {
3380 /* Checks whether my event id is availble */
3381 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3382 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3383 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3384 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3385 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3386 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3387 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3388 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3389 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3390 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3391 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3393 /* Ignores if the event id is different */
3394 events->destroy_timer(id);
3397 /* Ignores if the event id is different */
3398 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3399 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3400 if (process_button_long_pressed_event(window, key_index, context->get_last_touch_device_id())) {
3401 /* The button processed long key event, now enter longkey mode not to fire any events before releasing */
3402 handle_engine_signal(SCL_SIG_MOUSE_LONG_PRESS, window);
3403 windows->update_window(windows->get_magnifier_window());
3405 SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
3406 if (button_context->state == BUTTON_STATE_PRESSED) {
3407 button_context->state = BUTTON_STATE_NORMAL;
3408 CSCLWindows *windows = CSCLWindows::get_instance();
3410 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3411 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3414 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3415 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3418 /* Start the repeat key timer for NORMAL or GRAB buttons if longkey is not supported */
3419 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3422 /* This is for enabling backspace key in search layout*/
3423 //if (coordinate->use_repeat_key) {
3424 if (coordinate->use_repeat_key
3425 || coordinate->key_event[0][0] == MVK_BackSpace) {
3426 if (coordinate->button_type == BUTTON_TYPE_NORMAL ||
3427 coordinate->button_type == BUTTON_TYPE_GRAB ||
3428 coordinate->button_type == BUTTON_TYPE_SELFISH ||
3429 coordinate->button_type == BUTTON_TYPE_DIRECTION ||
3430 coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
3431 m_key_repeated_num = 0;
3432 events->create_timer(SCL_TIMER_REPEATKEY, m_repeat_key_duration, value);
3433 if (windows->is_base_window(window)) {
3434 state->set_cur_action_state(ACTION_STATE_BASE_REPEATKEY);
3436 state->set_cur_action_state(ACTION_STATE_POPUP_REPEATKEY);
3442 events->destroy_timer(id);
3447 case SCL_TIMER_REPEATKEY: {
3448 /* Checks whether my event id is availble */
3449 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3450 (state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
3451 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY)
3453 /* Ignores if the event id is different */
3454 events->destroy_timer(id);
3457 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3458 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3459 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
3460 if (interval < SCL_REPEATKEY_MIN_DURATION) {
3461 interval = SCL_REPEATKEY_MIN_DURATION;
3463 process_button_repeat_pressed_event(window, key_index, context->get_last_touch_device_id());
3464 events->destroy_timer(id);
3465 events->create_timer(SCL_TIMER_REPEATKEY, interval, value);
3466 m_key_repeated_num++;
3470 case SCL_TIMER_BUTTON_DELAY: {
3471 /* If there is postponed update of button, update it now */
3472 sclwindow last_window = context->get_last_pressed_window();
3473 scl8 last_key = context->get_last_pressed_key();
3475 if (last_window != SCLWINDOW_INVALID && last_key != NOT_USED) {
3476 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_window, last_key);
3478 windows->update_window(last_window, coords->x, coords->y, coords->width, coords->height);
3482 windows->hide_window(windows->get_magnifier_window());
3483 context->set_last_pressed_window(SCLWINDOW_INVALID);
3484 context->set_last_pressed_key(NOT_USED);
3485 events->destroy_timer(id);
3489 case SCL_TIMER_POPUP_TIMEOUT: {
3490 SclNotiPopupClosingDesc desc;
3491 desc.ui_event_desc = NULL;
3492 desc.input_mode = NULL;
3493 desc.timed_out = TRUE;
3495 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3496 if (sclres_manager) {
3497 const PSclInputModeConfigure sclres_input_mode_configure =
3498 sclres_manager->get_input_mode_configure_table();
3499 sclwindow window = windows->get_nth_popup_window(SCL_WINDOW_Z_TOP);
3500 SclWindowContext *window_context = windows->get_window_context(window);
3501 if (window_context && sclres_input_mode_configure) {
3502 if (scl_check_arrindex(window_context->inputmode, MAX_SCL_INPUT_MODE)) {
3503 desc.input_mode = sclres_input_mode_configure[window_context->inputmode].name;
3508 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_CLOSING, &desc)) {
3509 windows->close_all_popups();
3511 SclNotiPopupClosedDesc closed_desc;
3512 closed_desc.ui_event_desc = desc.ui_event_desc;
3513 closed_desc.input_mode = desc.input_mode;
3514 closed_desc.timed_out = desc.timed_out;
3515 handler->on_event_notification(SCL_UINOTITYPE_POPUP_CLOSED, &desc);
3517 events->destroy_timer(id);
3521 case SCL_TIMER_AUTOTEST: {
3522 sclint rnd = rand() % 100;
3524 if (cache->get_cur_layout(windows->get_base_window()) == NULL) {
3527 sclint x = (rand() % (cache->get_cur_layout(windows->get_base_window())->width));
3528 sclint y = (rand() % (cache->get_cur_layout(windows->get_base_window())->height));
3531 events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3532 events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3533 } else if (rnd < 90) {
3534 events->generate_mouse_event(SCL_MOUSE_EVENT_MOVE, x, y);
3535 } else if (rnd < 95) {
3536 events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3538 events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3542 if (m_debug_variable < SCL_AUTOTEST_NUM) events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INTERVAL, 0, FALSE);
3543 else m_debug_mode = DEBUGMODE_DISABLED;
3547 case SCL_TIMER_ANIMATION: {
3548 CSCLAnimator *animator = CSCLAnimator::get_instance();
3550 return animator->animator_timer();
3556 events->destroy_timer(id);
3564 /* Handles signals to manage contexts mainly focusing on resetting variables and cleaning up states */
3565 void CSCLController::handle_engine_signal( SclInternalSignal signal, sclwindow targetWindow )
3570 SIGACTION_RESIZE_RESOURCES,
3571 SIGACTION_DESTROY_TIMERS,
3572 SIGACTION_CLEAR_PRIVATEKEYS,
3573 SIGACTION_RECOMPUTE_LAYOUT,
3574 SIGACTION_FREE_IMAGES,
3575 SIGACTION_CLOSE_POPUP,
3576 SIGACTION_CLOSE_MAGNIFIER,
3577 SIGACTION_UNSET_SHIFT,
3578 SIGACTION_UNPRESS_KEYS,
3579 SIGACTION_INIT_DISPLAY,
3580 SIGACTION_INIT_INPUTMODE,
3584 const sclboolean SIGNAL_TABLE[SIGACTION_MAXNUM][SCL_SIG_MAXNUM] = {
3585 // START, SHOW, HIDE, INPCHNG, DISPCHNG, POPUPSHOW, POPUPHIDE, MOUSEPRES, M-LONGPRES, MOUSEREL, KEYEVT, FOCUSCHNG
3586 // SIGACTION_RESIZE_RESOURCES
3587 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3588 // SIGACTION_DESTROY_TIMERS
3589 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3590 // SIGACTION_CLEAR_PRIVATEKEYS
3591 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TRUE },
3592 // SIGACTION_RECOMPUTE_LAYOUT
3593 { 0, TRUE, 0, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
3594 // SIGACTION_FREE_IMAGES
3595 { TRUE, 0, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0 },
3596 // SIGACTION_CLOSE_POPUP
3597 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3598 // SIGACTION_CLOSE_MAGNIFIER
3599 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3600 // SIGACTION_UNSET_SHIFT
3601 { TRUE, 0 , 0 , TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE },
3602 // SIGACTION_UNPRESS_KEYS
3603 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3604 // SIGACTION_INIT_DISPLAY
3605 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3606 // SIGACTION_INIT_INPUTMODE
3607 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TRUE },
3610 scl_assert_return(signal >= 0 && signal < SCL_SIG_MAXNUM);
3612 CSCLEvents* events = CSCLEvents::get_instance();
3613 CSCLWindows *windows = CSCLWindows::get_instance();
3614 CSCLContext *context = CSCLContext::get_instance();
3615 CSCLImageProxy *proxy = CSCLImageProxy::get_instance();
3616 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3621 context->set_hidden_state(FALSE);
3626 context->set_hidden_state(TRUE);
3627 windows->close_all_popups();
3631 case SCL_SIG_INPMODE_CHANGE:
3632 case SCL_SIG_DISP_CHANGE:
3633 case SCL_SIG_POPUP_SHOW:
3634 case SCL_SIG_POPUP_HIDE:
3635 case SCL_SIG_MOUSE_PRESS:
3636 case SCL_SIG_MOUSE_LONG_PRESS:
3637 case SCL_SIG_MOUSE_RELEASE:
3638 case SCL_SIG_KEYEVENT:
3644 for (loop = 0;loop < SIGACTION_MAXNUM;loop++) {
3645 if (SIGNAL_TABLE[loop][signal] == TRUE) {
3647 case SIGACTION_RESIZE_RESOURCES:
3649 case SIGACTION_DESTROY_TIMERS:
3650 events->destroy_all_timer();
3652 case SIGACTION_CLEAR_PRIVATEKEYS:
3654 case SIGACTION_RECOMPUTE_LAYOUT: {
3655 if (targetWindow != SCLWINDOW_INVALID) {
3656 cache->recompute_layout(targetWindow);
3658 windows->update_window(targetWindow);
3662 case SIGACTION_FREE_IMAGES:
3663 proxy->free_images();
3665 case SIGACTION_CLOSE_POPUP: {
3666 /* If there is a popup still opened, don't destroy POPUP_TIMEOUT timer */
3667 if (!(windows->close_all_popups(targetWindow))) {
3668 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
3672 case SIGACTION_CLOSE_MAGNIFIER: {
3673 if (signal == SCL_SIG_HIDE) {
3674 windows->hide_window(windows->get_magnifier_window(), TRUE);
3676 windows->hide_window(windows->get_magnifier_window());
3679 //events->create_timer(SCL_TIMER_BUTTON_DELAY, SCL_BUTTON_MIN_DURATION, 0);
3681 case SIGACTION_UNSET_SHIFT: {
3682 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3685 SclNotiShiftStateChangeDesc desc;
3686 desc.ui_event_desc = NULL;
3687 desc.shift_state = SCL_SHIFT_STATE_OFF;
3689 if (SCL_EVENT_PASS_ON ==
3690 handler->on_event_notification(SCL_UINOTITYPE_SHIFT_STATE_CHANGE, &desc)) {
3691 context->set_shift_state(SCL_SHIFT_STATE_OFF);
3696 case SIGACTION_UNPRESS_KEYS:
3697 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3698 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3700 case SIGACTION_INIT_DISPLAY:
3702 case SIGACTION_INIT_INPUTMODE:
3712 * Sets the duration value for longkey
3713 * If not set, it will use default longkey duration. see sclconfig
3716 CSCLController::set_longkey_duration(scllong msc)
3719 sclboolean ret = FALSE;
3721 m_long_key_duration = msc;
3728 * Sets the distance value for cancel longkey
3729 * If not set, it will use default longkey duration. see sclconfig
3732 CSCLController::set_longkey_cancel_dist(sclshort dist)
3735 sclboolean ret = FALSE;
3737 m_long_key_cancel_distance = dist;
3744 * Sets the duration value for repeatkey
3745 * If not set, it will use default repeatkey duration. see sclconfig
3748 CSCLController::set_repeatkey_duration(scllong msc)
3751 sclboolean ret = FALSE;
3753 m_repeat_key_duration = msc;
3760 * Sets the duration value for autopopup key
3761 * If not set, it will use default short longkey duration. see sclconfig
3764 CSCLController::set_autopopup_key_duration(scllong msc)
3767 sclboolean ret = FALSE;
3769 m_autopopup_key_duration = msc;
3776 * Sets the amount value for button delay
3777 * If not set, it will use default button delay amount. see sclconfig
3780 CSCLController::set_button_delay_duration(scllong msc)
3783 sclboolean ret = FALSE;
3785 m_button_delay_duration = msc;
3792 * Configures the variables for auto-popup window
3793 * It will return rectangle area
3794 * @return FALSE It's not avaiable popup key
3797 CSCLController::configure_autopopup_window(sclwindow window, sclbyte key_index, SclRectangle* rect)
3800 scl_assert_return_false(window);
3801 scl_assert_return_false(key_index >= 0);
3803 sclboolean ret = TRUE;
3805 sclbyte num_keys, num_columns, num_rows;
3807 CSCLUtils *utils = CSCLUtils::get_instance();
3808 CSCLContext *context = CSCLContext::get_instance();
3809 CSCLWindows *windows = CSCLWindows::get_instance();
3810 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3812 const SclLayoutKeyCoordinate *coordinate = NULL;
3815 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3818 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3819 PSclAutoPopupConfigure autopopup_configure = NULL;
3820 if (sclres_manager) {
3821 autopopup_configure = sclres_manager->get_autopopup_configure();
3824 if (utils && context && windows && cache && coordinate && rect && autopopup_configure) {
3825 SCLShiftState shift_index = context->get_shift_state();
3826 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
3827 if (context->get_caps_lock_mode()) {
3828 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
3831 if (utils->get_autopopup_window_variables(coordinate->autopopup_key_labels[shift_index],
3832 &num_keys, &num_columns, &num_rows, &rect->width, &rect->height)) {
3834 /* There is no need for an autopopup window if number of keys are equal to or less than 0 */
3835 if (!(num_keys > 0)) {
3838 /* calculates y position to be set */
3839 SclRectangle baseWndRect;
3840 int scrwidth, scrheight;
3841 utils->get_screen_resolution(&scrwidth, &scrheight);
3843 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
3844 /* Let the autopopup have its position right above the pressed button, with center alignment) */
3845 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) - (rect->width / 2);
3846 rect->y = baseWndRect.y + coordinate->y - rect->height +
3847 autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate();
3848 /* First check the growing direction of this autopopup window */
3849 if (coordinate->x < baseWndRect.width / 2) {
3850 /* We're growing left to right, caculate the left start point */
3851 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) -
3852 (autopopup_configure->button_width * utils->get_custom_scale_rate_x() / 2) -
3853 autopopup_configure->bg_padding * utils->get_smallest_custom_scale_rate();
3854 if (rect->x + rect->width > baseWndRect.x + baseWndRect.width) {
3855 sclint relocate_unit = autopopup_configure->button_width * utils->get_custom_scale_rate_x() +
3856 autopopup_configure->button_spacing * utils->get_smallest_custom_scale_rate();
3857 rect->x -= (((rect->x + rect->width - (baseWndRect.x + baseWndRect.width)) /
3858 relocate_unit) + 1) * relocate_unit;
3861 /* We're growing right to left, caculate the right end point */
3862 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) +
3863 (autopopup_configure->button_width * utils->get_custom_scale_rate_x() / 2) +
3864 autopopup_configure->bg_padding * utils->get_smallest_custom_scale_rate();
3865 rect->x -= rect->width;
3866 if (rect->x < baseWndRect.x) {
3867 sclint relocate_unit = autopopup_configure->button_width * utils->get_custom_scale_rate_x() +
3868 autopopup_configure->button_spacing * utils->get_smallest_custom_scale_rate();
3869 rect->x += (((baseWndRect.x - rect->x) /
3870 relocate_unit) + 1) * relocate_unit;
3873 //rect->y = (scrheight - layout->height) + coordinate->y - rect->height + autopopup_configure->decoration_size;
3874 /* Check if the window goes out of screen boundary */
3875 //if (rect->x + rect->width > scrwidth + utils->get_scale_x(scl_autopopup_configure.decoration_size)) rect->x = (scrwidth + utils->get_scale_x(scl_autopopup_configure.decoration_size)) - rect->width;
3876 if (rect->x + rect->width > scrwidth) rect->x = (scrwidth) - rect->width;
3877 if (rect->y + rect->height > scrheight) rect->y = scrheight - rect->height;
3878 if (rect->x < 0 - autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate())
3879 rect->x = 0 - autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate();
3881 if (rect->x < 0) rect->x = 0;
3882 if (rect->y < 0) rect->y = 0;
3891 * If the mouse was pressed on the button A and moved to B without releasing,
3892 * this function decides whether we should allow event transition, meaning
3893 * button A gets restored to its initial state and B gets pressed instead.
3896 CSCLController::check_event_transition_enabled(const SclLayoutKeyCoordinate *btn_from, const SclLayoutKeyCoordinate *btn_to)
3898 sclboolean ret = FALSE;
3899 sclbyte type_from = BUTTON_TYPE_NORMAL; /* To enable event transition even if no button is pressed currently */
3900 sclbyte type_to = MAX_BUTTON_TYPE;
3902 const sclboolean TRANSITION_TABLE[MAX_BUTTON_TYPE][MAX_BUTTON_TYPE] = {
3903 // NORMAL GRAB SELFISH DRAG MULTITAP ROTATION DIRECTION R_DIRECTION TOGGLE UIITEM
3905 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3907 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3909 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3911 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3913 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3915 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3917 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3918 // From : R_DIRECTION
3919 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3921 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
3923 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
3926 if (btn_from) type_from = btn_from->button_type;
3927 if (btn_to) type_to = btn_to->button_type;
3929 scl_assert_return_false(type_from >= 0 && type_from < MAX_BUTTON_TYPE);
3930 scl_assert_return_false(type_to >= 0 && type_to < MAX_BUTTON_TYPE);
3932 if (type_from < MAX_BUTTON_TYPE && type_to < MAX_BUTTON_TYPE) {
3933 ret = TRANSITION_TABLE[type_from][type_to];
3940 CSCLController::get_debug_mode()
3943 return m_debug_mode;
3945 return m_debug_mode;
3946 return DEBUGMODE_DISABLED;
3951 CSCLController::set_debug_mode(SCLDebugMode mode)
3953 CSCLEvents *events = CSCLEvents::get_instance();
3954 CSCLUtils *utils = CSCLUtils::get_instance();
3956 m_debug_mode = mode;
3957 m_debug_variable = 0;
3959 if (m_debug_mode == DEBUGMODE_AUTOTEST) {
3961 if (events && utils) {
3962 events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INITIAL_INTERVAL, 0, FALSE);
3963 utils->log("mode : %d\n", mode);
3969 CSCLController::disable_input_events(sclboolean disabled)
3971 m_input_events_disabled = disabled;