2 * Copyright 2012-2013 Samsung Electronics Co., Ltd.
4 * Licensed under the Flora License, Version 1.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://floralicense.org/license/
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"
35 //#define DIRECTLY_DRAW_ON_EVENTS
40 _play_tts_for_input_mode_name(int mode) {
43 CSCLContext *context = CSCLContext::get_instance();
44 if (context->get_tts_enabled() == FALSE) {
48 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
49 const SclInputModeConfigure *pinput_mode_table = sclres_manager->get_input_mode_configure_table();
50 if (NULL == pinput_mode_table) {
54 const char* name = pinput_mode_table[mode].name;
59 CSCLUtils *utils = CSCLUtils::get_instance();
60 utils->play_tts(name);
65 _play_tts_for_layout_autopopup_name() {
68 CSCLContext *context = CSCLContext::get_instance();
69 if (context->get_tts_enabled() == FALSE) {
73 CSCLUtils *utils = CSCLUtils::get_instance();
74 utils->play_tts(SCL_LAYOUT_AUTOPOPUP_NAME);
78 CSCLController* CSCLController::m_instance = NULL; /* For singleton */
81 CSCLController::CSCLController()
85 m_long_key_duration = SCL_LONGKEY_DURATION;
86 m_long_key_cancel_distance = SCL_LONGKEY_CANCEL_DIST;
87 m_repeat_key_duration = SCL_REPEATKEY_DURATION;
88 m_autopopup_key_duration = SCL_AUTOPOPUP_KEY_DURATION;
90 m_button_delay_duration = SCL_BUTTON_MIN_DURATION;
92 m_key_repeated_num = 0;
94 m_debug_mode = DEBUGMODE_DISABLED;
97 m_input_events_disabled = FALSE;
100 CSCLController::~CSCLController()
106 CSCLController::get_instance()
109 m_instance = new CSCLController();
111 return (CSCLController*)m_instance;
115 CSCLController::init()
120 //#define TEST_NEWBACKEND
121 #ifdef TEST_NEWBACKEND
122 #include <Ecore_Evas.h>
128 EFLOBJECT_CLIPOBJECT,
134 SclRectangle position;
137 sclboolean extracted;
140 #include <Ecore_Evas.h>
146 Evas_Object *clipper;
149 sclchar image_path[_POSIX_PATH_MAX];
159 sclboolean extrace_image;
168 scl::SclFontInfo font_info;
170 sclchar str[_POSIX_PATH_MAX];;
176 SCLLabelAlignment align;
180 sclbyte inner_height;
183 extern std::vector<ImageCache> g_ImageCache;
184 extern std::vector<TextCache> g_TextCache;
189 * Sets the current input mode to the given mode
192 CSCLController::process_input_mode_change(const sclbyte mode)
196 sclboolean ret = FALSE;
198 CSCLUtils *utils = CSCLUtils::get_instance();
199 CSCLContext *context = CSCLContext::get_instance();
200 CSCLWindows *windows = CSCLWindows::get_instance();
201 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
202 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
203 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
204 assert(sclres_input_mode_configure != NULL);
206 if (context && windows && cache && utils) {
207 if (mode == context->get_input_mode() || mode == (sclbyte)NOT_USED) {
208 /* BtnContext does not get initialized if we don't call here */
209 cache->recompute_layout(windows->get_base_window());
213 context->set_input_mode(mode);
214 /* FIXME : NEWXML temporary commenting out */
215 //context->set_base_layout(sclres_input_mode_configure[mode].layouts[context->get_display()]);
217 _play_tts_for_input_mode_name(mode);
219 sclwindow window = windows->get_base_window();
220 handle_engine_signal(SCL_SIG_INPMODE_CHANGE, window);
222 #ifdef TEST_NEWBACKEND
223 SclWindowContext *winctx = windows->get_window_context(window, FALSE);
225 if (winctx->etc_info) {
227 Eina_List *list = (Eina_List*)(winctx->etc_info);
228 Eina_List *iter = NULL;
229 Eina_List *iter_next = NULL;
233 EINA_LIST_FOREACH_SAFE(list, iter, iter_next, data) {
235 EFLObject *object = (EFLObject*)(data);
237 Evas_Object* eo = object->object;
238 if (object->extracted) {
239 void *data = evas_object_image_data_get(eo, 1);
246 for(loop = 0;loop < g_ImageCache.size();loop++) {
247 if (g_ImageCache[loop].image == object->object) {
248 g_ImageCache[loop].used = FALSE;
251 for(loop = 0;loop < g_TextCache.size();loop++) {
252 if (g_TextCache[loop].text == object->object) {
253 g_TextCache[loop].used = FALSE;
259 object->object = NULL;
263 list = eina_list_remove_list(list, iter);
267 winctx->etc_info= list;
277 * Sets the current display mode to the given mode
280 CSCLController::process_rotation_change(const SCLRotation rotation)
283 CSCLContext *context = CSCLContext::get_instance();
284 CSCLWindows *windows = CSCLWindows::get_instance();
285 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
286 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
287 assert(sclres_input_mode_configure != NULL);
289 if (context && windows) {
291 if (rotation == ROTATION_90_CW || rotation == ROTATION_90_CCW) {
292 mode = DISPLAYMODE_LANDSCAPE;
294 mode = DISPLAYMODE_PORTRAIT;
297 //if (mode == context->get_display()) return FALSE;
298 context->set_display_mode(mode);
299 context->set_rotation(rotation);
300 /* FIXME : NEWXML temporary commenting out */
301 //context->set_base_layout(sclres_input_mode_configure[context->get_input_mode()].layouts[context->get_display()]);
303 sclwindow window = windows->get_base_window();
304 handle_engine_signal(SCL_SIG_DISP_CHANGE, window);
305 windows->update_window(window);
307 /* Moved to here since the new WMSync requires the rotation call be invoked as the
308 last step of display change process */
309 /* Make sure to set window's rotation degree before sending engine signal, which adjusts the size of main window */
310 windows->set_window_rotation(NULL, rotation);
316 * Checks if the given button with given touch_id needs magnifier window
319 CSCLController::check_magnifier_available(sclwindow window, sclbyte key_index, scltouchdevice touch_id)
321 sclboolean ret = FALSE;
323 CSCLContext *context = CSCLContext::get_instance();
324 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
325 const SclLayout *layout = NULL;
326 SclButtonContext *btncontext = NULL;
327 const SclLayoutKeyCoordinate *coordinate = NULL;
329 if (context && cache) {
330 layout = cache->get_cur_layout(window);
331 btncontext = cache->get_cur_button_context(window, key_index);
332 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
334 SCLShiftState shiftidx = context->get_shift_state();
335 if (shiftidx < 0 || shiftidx >= SCL_SHIFT_STATE_MAX) shiftidx = SCL_SHIFT_STATE_OFF;
337 if (layout && coordinate && btncontext && context->get_magnifier_enabled() ) {
338 if (coordinate->key_type != KEY_TYPE_CONTROL &&
339 coordinate->key_type != KEY_TYPE_MODECHANGE &&
340 coordinate->key_type != KEY_TYPE_NONE) {
344 /* Do not show if current layout does not allow magnifier */
345 if (!(layout->use_magnifier_window)) {
346 //utils->log("show_magnifier !(layout->use_magnifier_window \n");
350 /* Do not show if there's nothing to show */
351 const sclchar* custom_label = NULL;
352 for(sclint label_index = 0;label_index < MAX_SIZE_OF_LABEL_FOR_ONE && !custom_label;label_index++) {
353 const sclchar *temp_label = context->get_custom_magnifier_label(touch_id, label_index);
355 custom_label = temp_label;
359 //if (coordinate->key_value[shiftidx][btncontext->multikeyIdx] == NULL) {
360 if (coordinate->label[shiftidx][btncontext->multikeyIdx] == NULL) {
361 //utils->log("show_magnifier coordinate->key_value[shift][btncontext->multikeyIdx] == NULL \n");
363 //} else if (strlen(coordinate->key_value[shiftidx][btncontext->multikeyIdx]) == 0) {
364 } else if (strlen(coordinate->label[shiftidx][btncontext->multikeyIdx]) == 0) {
365 //utils->log("show_magnifier coordinate->key_value[shift][btncontext->multikeyIdx]) == 0 \n");
370 if (touch_id != context->get_last_touch_device_id()) {
381 CSCLController::process_button_pressed_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
382 scltouchdevice touch_id, sclboolean actual_event)
386 sclboolean ret = FALSE;
387 sclboolean redraw = FALSE;
389 CSCLContext *context = CSCLContext::get_instance();
390 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
391 CSCLWindows *windows = CSCLWindows::get_instance();
392 CSCLEvents *events = CSCLEvents::get_instance();
393 CSCLUtils *utils = CSCLUtils::get_instance();
394 CSCLFeedback *feedback = CSCLFeedback::get_instance();
395 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
396 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
397 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
398 PSclLayout sclres_layout = sclres_manager->get_layout_table();
399 assert(sclres_input_mode_configure != NULL);
400 assert(sclres_layout != NULL);
402 SclButtonContext *btncontext = NULL;
403 const SclLayoutKeyCoordinate *coordinate = NULL;
405 if (context && cache) {
406 btncontext = cache->get_cur_button_context(window, key_index);
407 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
410 static sclwindow prevwin = SCLWINDOW_INVALID;
411 static sclbyte prevkey = NOT_USED;
413 if (context && cache && windows && events && utils && feedback && handler && btncontext && coordinate) {
414 /* First check if this button is enabled in current active sublayout */
415 sclboolean sub_layout_match = TRUE;
416 if (coordinate->sub_layout && context->get_cur_sublayout()) {
417 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
418 sub_layout_match = FALSE;
421 /* If this button is pressed */
422 if ( x >= coordinate->x - coordinate->add_hit_left &&
423 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
424 y >= coordinate->y - coordinate->add_hit_top &&
425 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
426 /* Process the event only if the this item's sublayout id is active one */
428 //utils->log("process_button_pressed_event___TRUE\n");
430 /* If newly pressed key has type MULTI_TOUCH_TYPE_EXCLUSIVE, release all existing pressed events */
432 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_EXCLUSIVE) {
433 /* When calling mouse_release, the seq order of current multitouch events will be changed,
434 so we put all the multitouch events into a vector and use them afterwards forreleasing */
436 sclint multi_touch_context_num = context->get_multi_touch_context_num();
437 std::vector<SclUIEventDesc> multi_touch_events;
438 for(loop = 0;loop < multi_touch_context_num;loop++) {
440 context->get_multi_touch_event(loop, &desc);
441 multi_touch_events.push_back(desc);
443 for(loop = 0;loop < multi_touch_context_num;loop++) {
444 SclUIEventDesc desc = multi_touch_events[loop];
445 if (desc.touch_id != touch_id) {
446 mouse_release(context->get_cur_move_window(desc.touch_id),
447 context->get_cur_move_point(desc.touch_id).x, context->get_cur_move_point(desc.touch_id).y,
448 desc.touch_id, FALSE);
454 /* Make an unique ID for timer */
455 const scl16 uniqId = utils->get_unique_id();
457 context->set_cur_pressed_event_id(touch_id, uniqId);
458 context->set_cur_pressed_key(touch_id, key_index);
459 context->set_cur_pressed_window(touch_id, window);
461 btncontext->state = BUTTON_STATE_PRESSED;
466 #ifndef DIRECTLY_DRAW_ON_EVENTS
467 /* If the window doesn't get exposed before corresponding release event,
468 * the inverted state of a button will never be drawn onto screen.
469 * To prevent such a case, we draw the inverted state of button forcefully and directly,
470 * without waiting for expose event */
471 /*CSCLGraphics *grps = CSCLGraphics::get_instance();
472 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
473 scldrawctx draw_ctx = grps->begin_paint(window, TRUE);
474 builder->draw_button(window, draw_ctx, key_index, btncontext->state, TRUE);
475 grps->end_paint(window, draw_ctx);*/
479 feedback->button_pressed(window, key_index);
481 /* Special routine for autopopup */
482 if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
483 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
485 /* for long key & repeat key */
486 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
489 SCLShiftState shiftidx = context->get_shift_state();
490 if (shiftidx < 0 || shiftidx >= SCL_SHIFT_STATE_MAX) shiftidx = SCL_SHIFT_STATE_OFF;
492 SclUIEventDesc key_event_desc = {0};
493 key_event_desc.key_value = coordinate->key_value[shiftidx][0];
494 key_event_desc.key_event = coordinate->key_event[shiftidx][0];
495 key_event_desc.key_type = coordinate->key_type;
496 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
497 key_event_desc.event_type = EVENT_TYPE_PRESS;
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 handler->on_event_drag_state_changed(key_event_desc);
509 /* Now process normal behaviours of each button type */
510 switch (coordinate->button_type) {
511 case BUTTON_TYPE_NORMAL:
512 case BUTTON_TYPE_GRAB:
513 case BUTTON_TYPE_SELFISH:
514 case BUTTON_TYPE_DIRECTION:
515 case BUTTON_TYPE_RELATIVE_DIRECTION: {
516 /* Send click event right away if this button uses repeat key */
517 if (coordinate->use_repeat_key) {
518 handler->on_event_key_clicked(key_event_desc);
522 case BUTTON_TYPE_MULTITAP: {
525 case BUTTON_TYPE_ROTATION: {
528 case BUTTON_TYPE_DRAG: {
529 /* Drag buttons fires click event immediately when they are pressed */
530 handler->on_event_key_clicked(key_event_desc);
536 switch (coordinate->popup_type) {
537 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: {
538 sclint popup_input_mode = sclres_manager->get_inputmode_id(coordinate->popup_input_mode[SCL_DRAG_STATE_NONE]);
539 SCLDisplayMode display_mode = context->get_display_mode();
541 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
542 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
543 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
544 sclshort popupLayoutId =
545 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
546 SclRectangle popupRect;
547 SclRectangle baseWndRect;
548 SclLayout *layout = NULL;
550 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
551 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
552 layout = &sclres_layout[popupLayoutId];
555 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
556 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
557 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
558 //popupRect.width = utils->get_scale_x(layout->width);
559 //popupRect.height= utils->get_scale_y(layout->height);
560 popupRect.width = layout->width;
561 popupRect.height= layout->height;
562 windows->close_all_popups();
563 SclWindowOpener opener;
564 opener.window = window;
565 opener.key = key_index;
566 windows->open_popup(opener,
570 coordinate->popup_type,
571 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
572 sclres_input_mode_configure[popup_input_mode].use_dim_window,
573 coordinate->extract_offset_x,
574 coordinate->extract_offset_y,
575 sclres_input_mode_configure[popup_input_mode].timeout
577 /* FIXME : The parent key should be turned back to NORMAL state when RELEASED,
578 in case of POPUP_TYPE_BTN_PRESS_POPUP_DRAG type. Temporariliy setting NORMAL here. */
579 btncontext->state = BUTTON_STATE_NORMAL;
580 _play_tts_for_input_mode_name(popup_input_mode);
585 case POPUP_TYPE_BTN_RELEASE_POPUP:
586 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
587 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
588 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
589 case POPUP_TYPE_AUTO_POPUP:
590 case POPUP_TYPE_NONE:
591 /* Nothing to do in here */
595 /* Shows the magnifier window(the magnifier window will display when a kind of button type is character) */
596 //if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
597 if (coordinate->use_magnifier) {
598 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
600 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
601 PSclMagnifierWndConfigure magnifier_configure = NULL;
602 if (sclres_manager) {
603 magnifier_configure = sclres_manager->get_magnifier_configure();
605 if (showMagnifier && magnifier_configure) {
607 /* calculates x position to be set */
608 pos.x = (coordinate->x + (coordinate->width / 2)) - (magnifier_configure->width / 2);
610 /* calculates y position to be set */
611 sclint scnWidth, scnHeight;
612 utils->get_screen_resolution(&scnWidth, &scnHeight);
614 pos.y = coordinate->y - magnifier_configure->height;
616 /* FIXME : Temporary way of clearing magnifier window */
617 /*SclWindowContext *winctx = windows->get_window_context(windows->get_magnifier_window(), FALSE);
618 sclboolean clearmagwin = FALSE;
620 clearmagwin = !(winctx->hidden);
622 static int clearnum = 0;
623 if (key_index == prevkey && window == prevwin) {
627 if (++clearnum > 1) {
635 CSCLGraphics *graphics = CSCLGraphics::get_instance();
636 CSCLUtils *utils = CSCLUtils::get_instance();
637 sclchar composed_path[_POSIX_PATH_MAX] = {0,};
638 scldrawctx draw_ctx = graphics->begin_paint(windows->get_magnifier_window());
639 utils->get_composed_path(composed_path, scl_magnifier_configure.bg_image_path);
640 graphics->draw_image(windows->get_magnifier_window(), draw_ctx, composed_path, 0, 0);
641 graphics->end_paint(windows->get_magnifier_window(), draw_ctx);
644 windows->hide_window(windows->get_magnifier_window());
646 SclWindowContext *winctx = windows->get_window_context(window);
648 pos.x += winctx->geometry.x;
649 pos.y += winctx->geometry.y;
652 if (pos.x < 0 - magnifier_configure->padding_x) {
653 pos.x = 0 - magnifier_configure->padding_x;
655 if (pos.x > scnWidth + magnifier_configure->padding_x - magnifier_configure->width) {
656 pos.x = scnWidth + magnifier_configure->padding_x - magnifier_configure->width;
658 pos.y += magnifier_configure->padding_y;
659 pos.x += coordinate->magnifier_offset_x;
660 pos.y += coordinate->magnifier_offset_y;
661 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
662 //windows->resize_window(windows->get_magnifier_window(), utils->get_scale_x(scl_magnifier_configure.width), utils->get_scale_y(scl_magnifier_configure.height));
663 /*If we use transient_for them the ISE will occure some crash. It needs to check X11 */
664 /*windows->set_parent(windows->get_base_window(), windows->get_magnifier_window());*/
666 windows->show_window(windows->get_magnifier_window(), TRUE);
667 //windows->update_window(windows->get_magnifier_window());
670 static int fFirst = true;
672 windows->show_window(windows->get_magnifier_window());
675 windows->update_window(windows->get_magnifier_window());
678 /* We cannot use move_resize_window. It had occured some wrong behavior */
679 /*windows->move_resize_window(windows->get_magnifier_window(), pos.x, pos.y, scl_magnifier_configure.width, scl_magnifier_configure.height);*/
680 if (!showMagnifier) {
681 windows->hide_window(windows->get_magnifier_window());
688 /* COMMENTED OUT FOR TESTING MULTITOUCH!! */
689 ///* In case the current button is not the given key index */
690 //if (btncontext->state == BUTTON_STATE_PRESSED) {
691 // /* Even if the press event occured outside of this button's physical area, reset its context */
692 // btncontext->state = BUTTON_STATE_NORMAL;
695 /* BUTTON_TYPE_MULTITAP type button should restore its multikey index when another button is clicked */
696 if (coordinate->button_type & BUTTON_TYPE_MULTITAP) {
697 btncontext->multikeyIdx = 0;
701 /* If there is any need for redrawing */
703 #ifdef DIRECTLY_DRAW_ON_EVENTS
704 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
706 builder->draw_button(window, NULL, key_index, btncontext->state, TRUE);
709 CSCLWindows *windows = CSCLWindows::get_instance();
711 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
721 CSCLController::process_button_long_pressed_event(sclwindow window, sclbyte key_index,
722 scltouchdevice touch_id, sclboolean actual_event)
726 sclboolean ret = FALSE;
728 CSCLContext *context = CSCLContext::get_instance();
729 CSCLWindows *windows = CSCLWindows::get_instance();
730 CSCLActionState *state = CSCLActionState::get_instance();
731 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
732 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
733 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
734 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
735 PSclLayout sclres_layout = sclres_manager->get_layout_table();
737 assert(sclres_input_mode_configure != NULL);
738 assert(sclres_layout != NULL);
739 if (context && cache && handler && windows && state) {
740 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
742 /* Should return FALSE if this key does not have any longkey related property */
745 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
746 /* When calling mouse_release, the seq order of current multitouch events will be ch anged,
747 so we put all the multitouch events into a vector and use them afterwards for rel easing */
748 sclboolean finished = FALSE;
750 sclint multi_touch_context_num = context->get_multi_touch_context_num();
751 std::vector<SclUIEventDesc> multitouch_events;
752 for (loop = 0;loop < multi_touch_context_num;loop++) {
754 context->get_multi_touch_event(loop, &desc);
755 multitouch_events.push_back(desc);
757 for (loop = 0;loop < multi_touch_context_num && !finished;loop++) {
758 SclUIEventDesc desc = multitouch_events[loop];
759 if (desc.touch_id != touch_id) {
760 sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
761 scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
762 const SclLayoutKeyCoordinate *cur_pressed_coordinate =
763 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
764 if (cur_pressed_coordinate) {
765 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
766 mouse_release(context->get_cur_move_window(desc.touch_id),
767 context->get_cur_move_point(desc.touch_id).x,
768 context->get_cur_move_point(desc.touch_id).y,
769 desc.touch_id, FALSE);
780 /* Should return FALSE if this key does not have any longkey related property */
782 if (coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP ||
783 coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE ) {
784 SclRectangle popupRect;
785 SclRectangle baseWndRect;
786 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
787 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
788 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
789 sclint popup_input_mode = sclres_manager->get_inputmode_id(coordinate->popup_input_mode[SCL_DRAG_STATE_NONE]);
790 SCLDisplayMode display_mode = context->get_display_mode();
792 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
793 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
794 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
795 SclLayout *layout = NULL;
796 sclshort popupLayoutId =
797 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
799 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
800 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
801 layout = &sclres_layout[popupLayoutId];
804 //popupRect.width = utils->get_scale_x(layout->width);
805 //popupRect.height= utils->get_scale_y(layout->height);
806 popupRect.width = layout->width;
807 popupRect.height= layout->height;
809 SclWindowOpener opener;
810 opener.window = window;
811 opener.key = key_index;
817 coordinate->popup_type,
818 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
819 sclres_input_mode_configure[popup_input_mode].use_dim_window,
820 coordinate->extract_offset_x,
821 coordinate->extract_offset_y,
822 sclres_input_mode_configure[popup_input_mode].timeout
824 _play_tts_for_input_mode_name(popup_input_mode);
828 } else if (coordinate->long_key_value) {
829 if (strlen(coordinate->long_key_value) > 0) {
830 SclPoint ptMoving = context->get_cur_move_point(touch_id);
831 /*if (ptMoving.x >= coordinate->x && ptMoving.x <= coordinate->x + coordinate->width &&
832 ptMoving.y >= coordinate->y && ptMoving.y <= coordinate->y + coordinate->height) {*/
833 if (windows->is_base_window(window)) {
834 state->set_cur_action_state(ACTION_STATE_BASE_LONGKEY);
836 state->set_cur_action_state(ACTION_STATE_POPUP_LONGKEY);
840 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
841 PSclMagnifierWndConfigure magnifier_configure = NULL;
842 if (sclres_manager) {
843 magnifier_configure = sclres_manager->get_magnifier_configure();
845 if (coordinate->use_long_key_magnifier && magnifier_configure) {
846 CSCLUtils *utils = CSCLUtils::get_instance();
849 const SclLayout* layout = cache->get_cur_layout(window);
851 sclfloat scale_rate_x, scale_rate_y;
852 if (layout->display_mode == DISPLAYMODE_PORTRAIT) {
853 scale_rate_x = utils->get_scale_rate_x();
854 scale_rate_y = utils->get_scale_rate_y();
856 scale_rate_x = utils->get_scale_rate_y();
857 scale_rate_y = utils->get_scale_rate_x();
859 sclint scnWidth, scnHeight;
860 utils->get_screen_resolution(&scnWidth, &scnHeight);
862 //SclWindowContext *winctx = windows->get_window_context(window, TRUE);
863 SclWindowContext *winctx = windows->get_window_context(window);
865 pos.x = winctx->geometry.x + (coordinate->x + (coordinate->width / 2)) -
866 (magnifier_configure->width / 2);
867 pos.y = winctx->geometry.y + coordinate->y - magnifier_configure->height;
869 if (pos.x < 0 - magnifier_configure->padding_x) {
870 pos.x = 0 - magnifier_configure->padding_x;
872 if (pos.x > scnWidth + magnifier_configure->padding_x - magnifier_configure->width) {
873 pos.x = scnWidth + magnifier_configure->padding_x - magnifier_configure->width;
875 pos.y += magnifier_configure->padding_y;
876 pos.x += coordinate->magnifier_offset_x;
877 pos.y += coordinate->magnifier_offset_y;
878 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
879 windows->update_window(windows->get_magnifier_window());
880 windows->show_window(windows->get_magnifier_window(),TRUE);
884 SclUIEventDesc key_event_desc = {0};
885 key_event_desc.key_type = coordinate->long_key_type;
886 key_event_desc.key_value = coordinate->long_key_value;
887 key_event_desc.key_event = coordinate->long_key_event;
888 key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
890 key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
891 key_event_desc.touch_id = touch_id;
892 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
893 key_event_desc.mouse_current_point = context->get_cur_move_point(touch_id);
894 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
896 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
898 handler->on_event_key_clicked(key_event_desc);
904 context->set_cur_key_modifier(touch_id, KEY_MODIFIER_LONGKEY);
907 /* Longkey processing in here */
912 CSCLController::process_button_repeat_pressed_event(sclwindow window, sclbyte key_index,
913 scltouchdevice touch_id, sclboolean actual_event)
916 CSCLContext *context = CSCLContext::get_instance();
917 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
918 CSCLWindows *windows = CSCLWindows::get_instance();
919 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
921 if (context && cache && windows && handler) {
922 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
924 SCLShiftState shiftidx = context->get_shift_state();
925 if (shiftidx < 0 || shiftidx >= SCL_SHIFT_STATE_MAX) shiftidx = SCL_SHIFT_STATE_OFF;
928 switch (coordinate->button_type) {
929 case BUTTON_TYPE_NORMAL:
930 case BUTTON_TYPE_GRAB:
931 case BUTTON_TYPE_SELFISH:
932 case BUTTON_TYPE_DIRECTION:
933 case BUTTON_TYPE_RELATIVE_DIRECTION: {
934 /* This is for enabling backspace key in search layout*/
935 //if (coordinate->key_type != KEY_TYPE_MODECHANGE && coordinate->key_type != KEY_TYPE_COMPOSITION) {
936 //if (coordinate->key_type != KEY_TYPE_MODECHANGE || coordinate->key_event[0][0] == MVK_BackSpace) {
937 if (coordinate->key_type != KEY_TYPE_MODECHANGE) {
938 sclulong repeatKeyEvent = coordinate->key_event[shiftidx][0];
940 /* In case of Delete key, Change from Char deletion to Word deletion
941 when the input accelation speed is reached to Max */
942 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
943 PSclDefaultConfigure default_configure = NULL;
944 if (sclres_manager) {
945 default_configure = sclres_manager->get_default_configure();
947 if (default_configure) {
948 if (default_configure->use_word_deletion) {
949 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
950 if (repeatKeyEvent == MVK_BackSpace &&
951 interval <= SCL_REPEATKEY_WORD_DELETION_START_DURATION) {
952 repeatKeyEvent = MVK_3270_DeleteWord;
957 SclUIEventDesc key_event_desc = {0};
958 key_event_desc.key_value = coordinate->key_value[shiftidx][0];
959 key_event_desc.key_event = repeatKeyEvent;
960 key_event_desc.key_type = coordinate->key_type;
961 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
963 key_event_desc.event_type = EVENT_TYPE_REPEAT;
964 key_event_desc.touch_id = touch_id;
965 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
966 key_event_desc.mouse_current_point = context->get_cur_move_point(touch_id);
967 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
969 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
971 handler->on_event_key_clicked(key_event_desc);
979 /* Longkey processing in here */
984 CSCLController::process_button_move_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
985 scltouchdevice touch_id, sclboolean actual_event)
989 sclboolean ret = FALSE;
991 CSCLUtils *utils = CSCLUtils::get_instance();
992 CSCLEvents *events = CSCLEvents::get_instance();
993 CSCLContext *context = CSCLContext::get_instance();
994 CSCLWindows *windows = CSCLWindows::get_instance();
995 CSCLFeedback *feedback = CSCLFeedback::get_instance();
996 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
997 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
999 SclButtonContext *btncontext = NULL;
1001 const SclLayoutKeyCoordinate *coordinate = NULL;
1004 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1005 btncontext = cache->get_cur_button_context(window, key_index);
1008 if (btncontext && coordinate && feedback && utils && context && handler && cache && events && windows) {
1009 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1010 sclint thresholdX = 0;
1011 sclint thresholdY = 0;
1012 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1013 thresholdX = utils->get_scale_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1014 thresholdY = utils->get_scale_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1017 /* First check if this button is enabled in current active sublayout */
1018 sclboolean subLayoutMatch = TRUE;
1019 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1020 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1021 subLayoutMatch = FALSE;
1024 if ( x >= coordinate->x - coordinate->add_hit_left - thresholdX &&
1025 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX&&
1026 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1027 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1031 SCLShiftState shiftidx = context->get_shift_state();
1032 if (shiftidx < 0 || shiftidx >= SCL_SHIFT_STATE_MAX) shiftidx = SCL_SHIFT_STATE_OFF;
1034 const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1036 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1037 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1038 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1039 const SclLayoutKeyCoordinate *pressed_coordinate =
1040 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1042 if (pressed_context == NULL || pressed_coordinate == NULL) {
1046 if (key_index != pressed_key || window != pressed_window ) {
1047 /* When the focus has moved to another button, destroy all the timers */
1048 events->destroy_all_timer();
1050 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1052 sclfloat scale_rate_x, scale_rate_y;
1053 if (layout->display_mode == DISPLAYMODE_PORTRAIT) {
1054 scale_rate_x = utils->get_scale_rate_x();
1055 scale_rate_y = utils->get_scale_rate_y();
1057 scale_rate_x = utils->get_scale_rate_y();
1058 scale_rate_y = utils->get_scale_rate_x();
1061 const scl16 uniqId = utils->get_unique_id();
1062 context->set_cur_pressed_event_id(touch_id, uniqId);
1063 /* Special routine for autopopup */
1064 if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
1065 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
1067 /* for long key & repeat key */
1068 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
1071 context->set_cur_pressed_window(touch_id, window);
1072 context->set_cur_pressed_key(touch_id, key_index);
1074 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
1076 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1077 PSclMagnifierWndConfigure magnifier_configure = NULL;
1078 if (sclres_manager) {
1079 magnifier_configure = sclres_manager->get_magnifier_configure();
1081 if (showMagnifier && magnifier_configure) {
1082 SclPoint pos = {0,};
1083 /* calculates x position to be set */
1084 pos.x = (coordinate->x + (coordinate->width / 2)) - (magnifier_configure->width / 2);
1086 /* calculates y position to be set */
1087 sclint scnWidth, scnHeight;
1088 utils->get_screen_resolution(&scnWidth, &scnHeight);
1090 pos.y = (scnHeight - layout->height) + coordinate->y - magnifier_configure->height;
1092 if (pos.x < 0 - magnifier_configure->padding_x) {
1093 pos.x = 0 - magnifier_configure->padding_x;
1095 if (pos.x > scnWidth + magnifier_configure->padding_x - magnifier_configure->width) {
1096 pos.x = scnWidth + magnifier_configure->padding_x - magnifier_configure->width;
1098 pos.y += magnifier_configure->padding_y;
1099 if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
1100 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y);
1101 windows->update_window(windows->get_magnifier_window());
1106 feedback->button_moved(window, key_index);
1108 btncontext->state = BUTTON_STATE_PRESSED;
1109 if (pressed_context) {
1110 /* But, if this button should be in pressed state in other multitouch id, do not initialize it */
1111 sclboolean found = FALSE;
1112 for(sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1113 SclUIEventDesc desc;
1114 context->get_multi_touch_event(loop, &desc);
1115 if (desc.touch_id != touch_id) {
1116 MultiTouchContext *mulctx = context->find_multi_touch_context(desc.touch_id);
1118 if (mulctx->cur_pressed_window == pressed_window &&
1119 mulctx->cur_pressed_key == pressed_key) {
1126 pressed_context->state = BUTTON_STATE_NORMAL;
1129 /* If the window doesn't get exposed before corresponding release event,
1130 * the inverted state of a button will never be drawn onto screen.
1131 * To prevent such a case, we draw the inverted state of button forcefully and directly,
1132 * without waiting for expose event */
1133 /* Redrawing pressed button does not work properly, commented out */
1135 CSCLGraphics *grps = CSCLGraphics::get_instance();
1136 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1137 scldrawctx draw_ctx;
1138 if (pressed_window != SCLWINDOW_INVALID && pressed_key != NOT_USED) {
1139 draw_ctx = grps->begin_paint(pressed_window, TRUE);
1140 builder->draw_button(pressed_window, draw_ctx, pressed_key, FALSE);
1141 grps->end_paint(pressed_window, draw_ctx);
1143 draw_ctx = grps->begin_paint(window, TRUE);
1144 builder->draw_button(window, draw_ctx, key_index, TRUE);
1145 grps->end_paint(window, draw_ctx);
1148 switch (coordinate->button_type) {
1149 case BUTTON_TYPE_DRAG: {
1150 SclUIEventDesc key_event_desc = {0};
1151 key_event_desc.key_value = coordinate->key_value[shiftidx][0];
1152 key_event_desc.key_event = coordinate->key_event[shiftidx][0];
1153 key_event_desc.key_type = coordinate->key_type;
1154 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1156 key_event_desc.event_type = EVENT_TYPE_MOVE;
1157 key_event_desc.touch_id = touch_id;
1158 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1159 key_event_desc.mouse_current_point = context->get_cur_move_point(touch_id);
1160 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1162 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1164 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1165 PSclMagnifierWndConfigure magnifier_configure = NULL;
1166 if (sclres_manager) {
1167 magnifier_configure = sclres_manager->get_magnifier_configure();
1169 sclboolean processed = handler->on_event_drag_state_changed(key_event_desc);
1170 if (processed && context->get_magnifier_enabled() && magnifier_configure) {
1171 SclPoint zoomwinpos = {0,};
1172 const SclLayout *layout = cache->get_cur_layout(windows->get_base_window());
1173 sclfloat scale_rate_x, scale_rate_y;
1174 if (layout->display_mode == DISPLAYMODE_PORTRAIT) {
1175 scale_rate_x = utils->get_scale_rate_x();
1176 scale_rate_y = utils->get_scale_rate_y();
1178 scale_rate_x = utils->get_scale_rate_y();
1179 scale_rate_y = utils->get_scale_rate_x();
1181 /* calculates x position to be set */
1182 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
1183 (magnifier_configure->width / 2);
1185 /* calculates y position to be set */
1186 sclint scnWidth, scnHeight;
1187 utils->get_screen_resolution(&scnWidth, &scnHeight);
1189 zoomwinpos.y = coordinate->y - magnifier_configure->height;
1190 SclWindowContext *winctx = windows->get_window_context(window);
1192 zoomwinpos.x += winctx->geometry.x;
1193 zoomwinpos.y += winctx->geometry.y;
1195 if (zoomwinpos.x < 0 - magnifier_configure->padding_x) {
1196 zoomwinpos.x = 0 - magnifier_configure->padding_x;
1198 if (zoomwinpos.x > scnWidth + magnifier_configure->padding_x -
1199 magnifier_configure->width) {
1200 zoomwinpos.x = scnWidth + magnifier_configure->padding_x -
1201 magnifier_configure->width;
1203 zoomwinpos.y += magnifier_configure->padding_y;
1204 zoomwinpos.x += coordinate->magnifier_offset_x;
1205 zoomwinpos.y += coordinate->magnifier_offset_y;
1206 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y);
1207 windows->show_window(windows->get_magnifier_window(), 0);
1210 handler->on_event_key_clicked(key_event_desc);
1211 if (!(windows->is_base_window(window))) {
1212 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
1213 //SclWindowContext *winctx = windows->get_window_context(window, FALSE);
1214 SclWindowContext *winctx = windows->get_window_context(window);
1216 if (winctx->timeout > 0) {
1217 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
1218 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, winctx->timeout, 0, TRUE);
1226 #ifdef DIRECTLY_DRAW_ON_EVENTS
1227 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1230 builder->draw_button(window, NULL, key_index, btncontext->state);
1232 if (pressedContext) {
1233 builder->draw_button(pressed_window, NULL, pressed_key, pressedContext->state, TRUE);
1237 windows->update_window(window,
1238 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1239 const SclLayoutKeyCoordinate *pressed_coordinate =
1240 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1241 if (pressed_coordinate) {
1242 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1243 pressed_coordinate->width, pressed_coordinate->height);
1248 //utils->log("Now Moving : %d %d\n", pos.x, pos.y);
1250 /* If the focus went out from our SELFISH button */
1251 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH) {
1252 pressed_context->state = BUTTON_STATE_NORMAL;
1253 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1254 pressed_coordinate->width, pressed_coordinate->height);
1255 /* And if this SELFISH button was the last button pressed */
1256 if (touch_id == context->get_last_touch_device_id()) {
1257 windows->hide_window(windows->get_magnifier_window());
1262 /* If the focus came back into our SELFISH button */
1263 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH && pressed_context->state != BUTTON_STATE_PRESSED) {
1264 pressed_context->state = BUTTON_STATE_PRESSED;
1265 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1266 pressed_coordinate->width, pressed_coordinate->height);
1267 /* And if this SELFISH button was the last button pressed */
1268 if (touch_id == context->get_last_touch_device_id()) {
1269 sclboolean showMagnifier = check_magnifier_available(pressed_window, pressed_key, touch_id);
1271 if (showMagnifier) {
1272 windows->show_window(windows->get_magnifier_window());
1284 CSCLController::process_button_over_event(sclwindow window, sclint x, sclint y, sclbyte keyindex)
1288 sclboolean ret = FALSE;
1290 CSCLUtils *utils = CSCLUtils::get_instance();
1291 CSCLEvents *events = CSCLEvents::get_instance();
1292 CSCLContext *context = CSCLContext::get_instance();
1293 CSCLWindows *windows = CSCLWindows::get_instance();
1294 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1295 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1297 SclButtonContext *btncontext = NULL;
1299 const SclLayoutKeyCoordinate *coordinate = NULL;
1301 coordinate = cache->get_cur_layout_key_coordinate(window, keyindex);
1302 btncontext = cache->get_cur_button_context(window, keyindex);
1305 if(btncontext && coordinate && feedback && utils && context && cache && events && windows) {
1306 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1307 sclboolean subLayoutMatch = TRUE;
1308 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1309 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1310 subLayoutMatch = FALSE;
1313 if ( x >= coordinate->x - coordinate->add_hit_left &&
1314 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
1315 y >= coordinate->y - coordinate->add_hit_top &&
1316 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
1320 SCLShiftState shiftidx = context->get_shift_state();
1321 if(shiftidx < 0 || shiftidx >= SCL_SHIFT_STATE_MAX) shiftidx = SCL_SHIFT_STATE_OFF;
1323 const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1325 sclwindow highlighted_window = context->get_cur_highlighted_window();
1326 scl8 highlighted_key = context->get_cur_highlighted_key();
1327 SclButtonContext *cur_context = cache->get_cur_button_context(window, keyindex);
1329 if(cur_context == NULL) {
1332 if (keyindex != highlighted_key || window != highlighted_window ) {
1333 printf("%d != %d || %p != %p\n", keyindex, highlighted_key, window, highlighted_window);
1335 SclPoint pos = {0,};
1336 sclfloat scale_rate_x, scale_rate_y;
1337 if(layout->display_mode == DISPLAYMODE_PORTRAIT) {
1338 scale_rate_x = utils->get_scale_rate_x();
1339 scale_rate_y = utils->get_scale_rate_y();
1341 scale_rate_x = utils->get_scale_rate_y();
1342 scale_rate_y = utils->get_scale_rate_x();
1345 if (coordinate->key_type != KEY_TYPE_NONE) {
1346 if (context->get_tts_enabled()) {
1347 const char *targetstr = coordinate->hint_string[shiftidx][btncontext->multikeyIdx];
1348 printf("coordinate->hint_string[%d][%d] : %p\n", shiftidx, btncontext->multikeyIdx, targetstr);
1349 if (targetstr == NULL) {
1350 targetstr = coordinate->key_value[shiftidx][btncontext->multikeyIdx];
1352 printf("coordinate->key_value[%d][%d] : %p\n", shiftidx, btncontext->multikeyIdx, targetstr);
1353 if (targetstr == NULL) {
1354 targetstr = coordinate->label[shiftidx][0];
1356 printf("coordinate->label[%d][0] : %p\n", shiftidx, targetstr);
1357 /*if(state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
1358 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ) {
1359 targetstr = coordinate->long_key_value;
1361 utils->play_tts(targetstr);
1366 context->set_cur_highlighted_window(window);
1367 context->set_cur_highlighted_key(keyindex);
1375 CSCLController::get_drag_key_modifier(sclint deltax, sclint deltay, sclfloat dist, sclboolean check_farthest,
1376 scltouchdevice touch_id, sclbyte extra_option) {
1380 SCLKeyModifier modifier;
1383 CSCLContext *context = CSCLContext::get_instance();
1384 SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1387 double theta = atan2(deltay , (deltax ? deltax : 1)); /* Avoid divide by 0 exception */
1388 sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
1389 SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
1390 if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS ||
1391 extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1392 extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN) { /* 8 directions */
1393 /* If the theta is below 0, the direction is upward since the y coordinate grows downward */
1394 /* The below angle values are customized for MoAKey, need to provide customizing API */
1395 DIRECTIONINFO info[] = {
1396 {-8 * (M_PI / 8), -7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1397 {-7 * (M_PI / 8), -5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_LEFT},
1398 {-5 * (M_PI / 8), -2.7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP},
1399 {-2.7 * (M_PI / 8), -1.5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_RIGHT},
1400 {-1.5 * (M_PI / 8), 1 * (M_PI / 8), KEY_MODIFIER_DIRECTION_RIGHT},
1401 { 1 * (M_PI / 8), 3 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_RIGHT},
1402 { 3 * (M_PI / 8), 5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN},
1403 { 5 * (M_PI / 8), 7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_LEFT},
1404 { 7 * (M_PI / 8), 8 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1406 for (sclint loop = 0;loop < sizeof(info) / sizeof(DIRECTIONINFO);loop++) {
1407 if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1408 key_modifier = info[loop].modifier;
1411 } else { /* 4 directions */
1412 /* If the state was dragging to one of 4 directions and the final release point is
1413 * far enough from inital press point, and the angle is in between out predefined angle value */
1414 if (extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE &&
1415 cur_drag_state != SCL_DRAG_STATE_NONE && cur_drag_state != SCL_DRAG_STATE_INVALID &&
1416 dist > SCL_DRAG_CURVE_RECOG_DIST &&
1417 ratio > (1 / SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) &&
1418 ratio < SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) {
1419 if (cur_drag_state == SCL_DRAG_STATE_DOWN) {
1420 if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_RIGHT;
1421 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_LEFT;
1423 if (cur_drag_state == SCL_DRAG_STATE_UP) {
1424 if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_RIGHT;
1425 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_LEFT;
1427 if (cur_drag_state == SCL_DRAG_STATE_LEFT) {
1428 if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_DOWN;
1429 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_UP;
1431 if (cur_drag_state == SCL_DRAG_STATE_RIGHT) {
1432 if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_DOWN;
1433 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_UP;
1436 DIRECTIONINFO info[] = {
1437 {-4 * (M_PI / 4), -3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1438 {-3 * (M_PI / 4), -1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_UP},
1439 {-1 * (M_PI / 4), 1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_RIGHT},
1440 { 1 * (M_PI / 4), 3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_DOWN},
1441 { 3 * (M_PI / 4), 4 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1443 for (sclint loop = 0;loop < sizeof(info) / sizeof(DIRECTIONINFO);loop++) {
1444 if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1445 key_modifier = info[loop].modifier;
1451 if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1452 extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_LONG) {
1453 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1454 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1455 key_modifier = (SCLKeyModifier)(key_modifier + 8); // Add LONG attribute;
1458 if (check_farthest || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
1459 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1460 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1461 key_modifier = (SCLKeyModifier)(key_modifier + 16); // Add RETURN attribute;
1466 return key_modifier;
1470 CSCLController::process_button_release_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1471 scltouchdevice touch_id, sclboolean actual_event)
1475 sclboolean ret = FALSE;
1476 sclboolean redraw = FALSE;
1477 sclboolean fireEvt = FALSE;
1478 SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1480 static sclwindow lastFiredWin = SCLWINDOW_INVALID;
1481 static sclbyte lastFiredKey = NOT_USED;
1483 CSCLUtils *utils = CSCLUtils::get_instance();
1484 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1485 CSCLWindows *windows = CSCLWindows::get_instance();
1486 CSCLContext *context = CSCLContext::get_instance();
1487 CSCLActionState *state = CSCLActionState::get_instance();
1488 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1489 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1491 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1492 PSclLayout sclres_layout = sclres_manager->get_layout_table();
1493 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
1494 assert(sclres_layout != NULL);
1495 assert(sclres_input_mode_configure != NULL);
1496 SclButtonContext *btncontext = NULL;
1497 const SclLayoutKeyCoordinate *coordinate = NULL;
1500 btncontext = cache->get_cur_button_context(window, key_index);
1501 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1504 const SclLayoutKeyCoordinate *targetCoordination = NULL;
1506 if (utils && feedback && windows && context && state && handler && cache && btncontext && coordinate) {
1507 scl8 savedInputMode = context->get_input_mode();
1509 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1510 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1513 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1514 /* When calling mouse_release, the seq order of current multitouch events will be changed,
1515 so we put all the multitouch events into a vector and use them afterwards for releasing */
1516 sclboolean finished = FALSE;
1518 sclint multi_touch_context_num = context->get_multi_touch_context_num();
1519 std::vector<SclUIEventDesc> multi_touch_events;
1520 for(loop = 0;loop < multi_touch_context_num;loop++) {
1521 SclUIEventDesc desc;
1522 context->get_multi_touch_event(loop, &desc);
1523 multi_touch_events.push_back(desc);
1525 for(loop = 0;loop < multi_touch_context_num && !finished;loop++) {
1526 SclUIEventDesc desc = multi_touch_events[loop];
1527 if (desc.touch_id != touch_id) {
1528 sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
1529 scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
1530 const SclLayoutKeyCoordinate *cur_pressed_coordinate =
1531 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
1532 if (cur_pressed_coordinate) {
1533 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1534 mouse_release(context->get_cur_move_window(desc.touch_id),
1535 context->get_cur_move_point(desc.touch_id).x, context->get_cur_move_point(desc.touch_id).y,
1536 desc.touch_id, FALSE);
1546 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1547 sclint thresholdX = 0;
1548 sclint thresholdY = 0;
1550 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1551 thresholdX = utils->get_scale_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1552 thresholdY = utils->get_scale_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1556 /* Check if the pressed button's type is directional button */
1557 if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1559 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1561 sclboolean check_farthest = FALSE;
1566 /* If the buttontype is RELATIVE_DIRECTION, get the distance from last move point */
1567 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1568 startx = context->get_prev_move_point(touch_id).x;
1569 starty = context->get_prev_move_point(touch_id).y;
1571 startx = context->get_cur_pressed_point(touch_id).x;
1572 starty = context->get_cur_pressed_point(touch_id).y;
1575 sclint deltax = x - startx;
1576 sclint deltay = y - starty;
1578 sclfloat dist = utils->get_distance(x, y, startx, starty);
1579 sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
1580 if (coordinate->is_side_button) {
1581 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
1583 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1584 direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
1586 if (context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN &&
1587 coordinate->button_type != BUTTON_TYPE_RELATIVE_DIRECTION) {
1588 if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
1589 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
1590 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
1591 deltax = context->get_farthest_move_point(touch_id).x - context->get_cur_pressed_point(touch_id).x;
1592 deltay = context->get_farthest_move_point(touch_id).y - context->get_cur_pressed_point(touch_id).y;
1593 dist = utils->get_distance(context->get_farthest_move_point(touch_id), context->get_cur_pressed_point(touch_id));
1594 check_farthest = TRUE;
1597 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1598 key_modifier = context->get_cur_key_modifier(touch_id);
1599 } else if (dist > direction_recog_dist) {
1600 key_modifier = get_drag_key_modifier(deltax, deltay, dist, check_farthest, touch_id, coordinate->extra_option);
1606 /* First check if this button is enabled in current active sublayout */
1607 sclboolean subLayoutMatch = TRUE;
1608 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1609 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1610 subLayoutMatch = FALSE;
1613 /* Check if the event occured inside this button's rectangle */
1614 if ( x >= coordinate->x - coordinate->add_hit_left - thresholdX &&
1615 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX &&
1616 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1617 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1624 feedback->button_released(window, key_index);
1626 /* If this button's index is the same as the one initially pressed */
1627 if (pressed_window == window && pressed_key == key_index) {
1629 targetCoordination = coordinate;
1631 const SclLayoutKeyCoordinate *pressed_coordinate =
1632 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1634 if (pressed_coordinate) {
1635 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1637 targetCoordination = pressed_coordinate;
1645 /* In case of mode change buttons, event should be fired only when it was pressed lastly */
1647 if (coordinate->key_type == KEY_TYPE_MODECHANGE) {
1648 if (touch_id != context->get_last_touch_device_id()) {
1654 /* If this key's modifier is LONGKEY, this means the event is already fired so skip this one */
1655 if (context->get_cur_key_modifier(touch_id) == KEY_MODIFIER_LONGKEY) {
1659 /* Don't fire any events if we're in longkey state */
1660 if (state->get_cur_action_state() != ACTION_STATE_BASE_LONGKEY &&
1661 state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
1662 state->get_cur_action_state() != ACTION_STATE_POPUP_LONGKEY &&
1663 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY) {
1664 /* An event occured? */
1666 if (targetCoordination) {
1667 SCLShiftState shiftidx = context->get_shift_state();
1668 if (shiftidx < 0 || shiftidx >= SCL_SHIFT_STATE_MAX) shiftidx = SCL_SHIFT_STATE_OFF;
1670 SclUIEventDesc key_event_desc = {0};
1671 key_event_desc.key_type = targetCoordination->key_type;
1673 key_event_desc.event_type = EVENT_TYPE_RELEASE;
1674 key_event_desc.touch_id = touch_id;
1675 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1676 key_event_desc.mouse_current_point = context->get_cur_move_point(touch_id);
1677 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1679 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1681 switch (targetCoordination->button_type) {
1682 case BUTTON_TYPE_NORMAL:
1683 case BUTTON_TYPE_GRAB :
1684 case BUTTON_TYPE_SELFISH:
1685 case BUTTON_TYPE_DIRECTION :
1686 case BUTTON_TYPE_RELATIVE_DIRECTION: {
1687 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1688 if (pressed_context) {
1689 if (!(targetCoordination->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1690 key_event_desc.key_value = targetCoordination->key_value[shiftidx][0];
1691 key_event_desc.key_event = targetCoordination->key_event[shiftidx][0];
1692 key_event_desc.key_modifier = key_modifier;
1693 handler->on_event_key_clicked(key_event_desc);
1698 case BUTTON_TYPE_MULTITAP:
1699 case BUTTON_TYPE_ROTATION: {
1700 if (targetCoordination->button_type == BUTTON_TYPE_MULTITAP) {
1701 if (window == lastFiredWin && key_index == lastFiredKey) {
1702 key_modifier = KEY_MODIFIER_MULTITAP_REPEAT;
1704 key_modifier = KEY_MODIFIER_MULTITAP_START;
1707 key_modifier = KEY_MODIFIER_NONE;
1709 if (btncontext->multikeyIdx < MAX_SIZE_OF_MULTITAP_CHAR) {
1710 key_event_desc.key_value = coordinate->key_value[shiftidx][btncontext->multikeyIdx];
1711 key_event_desc.key_event = coordinate->key_event[shiftidx][btncontext->multikeyIdx];
1712 key_event_desc.key_modifier = key_modifier;
1713 handler->on_event_key_clicked(key_event_desc);
1715 /* Check if the multikey index is in valid range, and increase by one */
1716 if (btncontext->multikeyIdx >= MAX_SIZE_OF_MULTITAP_CHAR - 1) {
1717 btncontext->multikeyIdx = 0;
1719 sclbyte orgindex = btncontext->multikeyIdx;
1720 btncontext->multikeyIdx = 0;
1721 if (targetCoordination->key_value[shiftidx][orgindex + 1]) {
1722 if (strlen(targetCoordination->key_value[shiftidx][orgindex + 1]) > 0) {
1723 btncontext->multikeyIdx = orgindex + 1;
1729 case BUTTON_TYPE_DRAG : {
1734 switch (coordinate->popup_type) {
1735 case POPUP_TYPE_BTN_RELEASE_POPUP:
1736 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE: {
1737 SCLDragState dragstate = context->get_cur_drag_state(touch_id);
1738 sclint popup_input_mode = NOT_USED;
1739 if (scl_check_arrindex(dragstate, SCL_DRAG_STATE_MAX)) {
1740 popup_input_mode = sclres_manager->get_inputmode_id(coordinate->popup_input_mode[dragstate]);
1742 //if (!scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP)) {
1743 if (!scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE)) {
1745 sclres_manager->get_inputmode_id(coordinate->popup_input_mode[SCL_DRAG_STATE_NONE]);
1748 SCLDisplayMode display_mode = context->get_display_mode();
1750 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
1751 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
1752 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
1753 sclshort popupLayoutId =
1754 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
1755 if (popupLayoutId == NOT_USED){
1756 // deal with NOT_USED
1757 printf("popupLayoutID is not used.\n");
1759 SclLayout *layout = NULL;
1761 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
1762 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
1763 layout = &sclres_layout[popupLayoutId];
1766 SclRectangle popupRect;
1767 SclRectangle baseWndRect;
1768 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
1769 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
1770 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
1772 //popupRect.width = utils->get_scale_x(layout->width);
1773 //popupRect.height= utils->get_scale_y(layout->height);
1774 popupRect.width = layout->width;
1775 popupRect.height= layout->height;
1777 /* Let's make sure this popup window does not go beyond the screen area */
1778 sclint scr_w, scr_h;
1779 utils->get_screen_resolution(&scr_w, &scr_h);
1781 if (popupRect.x + popupRect.width > scr_w) {
1782 popupRect.x = scr_w - popupRect.width;
1784 if (popupRect.y + popupRect.height > scr_h) {
1785 popupRect.y = scr_h - popupRect.height;
1788 SclWindowOpener opener;
1789 opener.window = window;
1790 opener.key = key_index;
1791 windows->open_popup(
1796 coordinate->popup_type,
1797 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
1798 sclres_input_mode_configure[popup_input_mode].use_dim_window,
1799 coordinate->extract_offset_x,
1800 coordinate->extract_offset_y,
1801 sclres_input_mode_configure[popup_input_mode].timeout
1803 _play_tts_for_input_mode_name(popup_input_mode);
1808 case POPUP_TYPE_AUTO_POPUP:
1809 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG:
1810 case POPUP_TYPE_NONE:
1811 /* Nothing to do in here */
1816 lastFiredWin = window;
1817 lastFiredKey = key_index;
1821 /* If this button was pressed, initialize the button context regardless of event */
1822 if (btncontext->state == BUTTON_STATE_PRESSED) {
1823 /* But, if this button should be in pressed state in other multitouch id, do not initialize */
1824 sclboolean found = FALSE;
1825 for(sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1826 SclUIEventDesc desc;
1827 context->get_multi_touch_event(loop, &desc);
1828 if (desc.touch_id != touch_id) {
1829 MultiTouchContext *mulctx = context->find_multi_touch_context(desc.touch_id);
1831 if (mulctx->cur_pressed_window == window && mulctx->cur_pressed_key == key_index) {
1838 btncontext->state = BUTTON_STATE_NORMAL;
1843 /* If this button needs to be redrawn */
1845 #ifdef DIRECTLY_DRAW_ON_EVENTS
1846 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1848 builder->draw_button(window, NULL, key_index, btncontext->state, TRUE);
1851 if (savedInputMode == context->get_input_mode()) {
1852 CSCLWindows *windows = CSCLWindows::get_instance();
1854 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1866 CSCLController::mouse_press(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
1869 sclboolean ret = FALSE;
1871 if (m_input_events_disabled) return FALSE;
1873 //utils->log("Controller::mouse_press : %d %d\n", x, y);
1875 /* Adjust x,y coordinate by touch offset */
1876 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
1878 CSCLContext *context = CSCLContext::get_instance();
1879 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1880 CSCLActionState *state = CSCLActionState::get_instance();
1881 CSCLWindows *windows = CSCLWindows::get_instance();
1882 CSCLUtils *utils = CSCLUtils::get_instance();
1884 sclint btnIndex = NOT_USED;
1885 SclWindowContext *winctx = NULL;
1887 const SclLayout *layout = cache->get_cur_layout(window);
1889 x += layout->mouse_manipulate_x;
1890 y += layout->mouse_manipulate_y;
1892 winctx = windows->get_window_context(window);
1893 /* If the dim window is virtual and currently active, let's just skip this event */
1894 if (windows->is_base_window(window)) {
1895 SclWindowContext *dimctx = windows->get_window_context(windows->get_dim_window());
1897 if (dimctx->is_virtual && !(dimctx->hidden)) {
1898 window = windows->get_dim_window();
1905 if (cache && state && windows && context && winctx) {
1906 SCLDisplayMode display_mode = context->get_display_mode();
1907 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1908 PSclDefaultConfigure default_configure = NULL;
1909 if (sclres_manager) {
1910 default_configure = sclres_manager->get_default_configure();
1912 if (default_configure) {
1913 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
1916 sclboolean isSubEvent = FALSE;
1917 if (context->get_multi_touch_context_num() > 0) {
1918 SclUIEventDesc desc;
1919 context->get_multi_touch_event(0, &desc);
1920 sclwindow pressed_window = context->get_cur_pressed_window(desc.touch_id);
1921 scl8 pressed_key = context->get_cur_pressed_key(desc.touch_id);
1922 SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1924 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_GRAB_SUB_EVENTS) {
1926 utils->play_vibration(DEFAULT_VIBRATION_STYLE, DEFAULT_VIBRATION_DURATION);
1930 context->create_multi_touch_context(touch_id, isSubEvent);
1931 context->set_cur_pressed_window(touch_id, window);
1932 context->set_cur_pressed_point(touch_id, x, y);
1933 context->set_cur_pressed_time(touch_id);
1934 context->set_cur_move_window(touch_id, window);
1935 context->set_cur_move_point(touch_id, x, y);
1936 context->set_last_touch_device_id(touch_id);
1937 context->set_cur_drag_state(touch_id, SCL_DRAG_STATE_NONE);
1938 context->set_cur_key_modifier(touch_id, KEY_MODIFIER_NONE);
1939 for(sclint labelidx = 0;labelidx < MAX_SIZE_OF_LABEL_FOR_ONE;labelidx++) {
1940 context->set_custom_magnifier_label(touch_id, labelidx, NULL);
1943 /* If there is postponed update of button, update it now */
1944 CSCLEvents *events = CSCLEvents::get_instance();
1945 sclwindow last_win = context->get_last_pressed_window();
1946 scl8 last_key = context->get_last_pressed_key();
1947 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
1948 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
1950 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
1953 context->set_prev_pressed_window(touch_id, SCLWINDOW_INVALID);
1954 context->set_prev_pressed_key(touch_id, NOT_USED);
1955 context->set_prev_drag_state(touch_id, SCL_DRAG_STATE_NONE);
1956 context->set_prev_move_point(touch_id, x, y);
1958 /* Destroy key related timers */
1959 events->destroy_timer(SCL_TIMER_BUTTON_DELAY);
1960 events->destroy_timer(SCL_TIMER_AUTOPOPUP);
1961 events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
1962 events->destroy_timer(SCL_TIMER_LONGKEY);
1963 events->destroy_timer(SCL_TIMER_REPEATKEY);
1965 /* Do what has to be done when mouse gets pressed */
1966 handle_engine_signal(SCL_SIG_MOUSE_PRESS, window);
1968 /* Adjust event x and y positions as relative position to the virtual window */
1970 /*if (winctx->isVirtual) {
1971 SclWindowContext *basectx = windows->get_window_context(windows->get_base_window());
1973 x -= (winctx->x - basectx->x);
1974 y -= (winctx->y - basectx->y);
1980 /* Iterate all the buttons and inform the event */
1981 sclboolean ended = FALSE;
1982 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
1983 SclButtonContext *btncontext = cache->get_cur_button_context(window, loop);
1984 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
1985 if (btncontext && coordinate) {
1986 if (!(btncontext->used)) {
1988 } else if (btncontext->state != BUTTON_STATE_DISABLED &&
1989 coordinate->button_type != BUTTON_TYPE_UIITEM) {
1990 if (process_button_pressed_event(window, x, y, loop, touch_id, actual_event)) {
1991 if (windows->is_base_window(window)) {
1992 state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
1994 state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2003 /* For covering a missing area about 1 pixel */
2005 for (int loop = 0;loop < MAX_KEY;loop++) {
2006 SclButtonContext *btncontext = cache->get_cur_button_context(window, loop);
2007 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2008 if (btncontext && coordinate) {
2009 if (!(btncontext->used)) {
2011 } else if (btncontext->state != BUTTON_STATE_DISABLED &&
2012 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2013 if (process_button_pressed_event(window, x+1, y+1, loop, touch_id, actual_event)) {
2014 if (windows->is_base_window(window)) {
2015 state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2017 state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2028 sclwindow skipwindow = window;
2029 if (ret && btnIndex != NOT_USED) {
2030 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, btnIndex);
2032 sclboolean dont_close_popup = FALSE;
2033 if (coordinate->dont_close_popup) {
2034 dont_close_popup = TRUE;
2036 /* If the button's popup type is drag type, the opened popup could be the one opened by this press event */
2037 if (coordinate->popup_type == POPUP_TYPE_BTN_PRESS_POPUP_DRAG) {
2038 /* Check the opened popup was opened by this button */
2039 sclwindow popupwin = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2040 SclWindowContext *popupctx = windows->get_window_context(popupwin);
2042 SclWindowOpener opener = popupctx->opener;
2043 if (opener.window == window && opener.key == btnIndex) {
2044 dont_close_popup = TRUE;
2048 if (dont_close_popup) {
2049 skipwindow = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2053 windows->close_all_popups(skipwindow);
2055 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
2056 if (!(windows->is_base_window(window))) {
2057 if (winctx->timeout > 0) {
2058 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2059 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, winctx->timeout, 0, TRUE);
2061 } else if (skipwindow != window) { /* Or the pressed button has dont_close_popup property, reset POPUP_TIMEOUT timer */
2062 //SclWindowContext *skipwinctx = windows->get_window_context(skipwindow, FALSE);
2063 SclWindowContext *skipwinctx = windows->get_window_context(skipwindow);
2065 if (skipwinctx->timeout > 0) {
2066 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2067 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, skipwinctx->timeout, 0, TRUE);
2077 CSCLController::mouse_release(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2080 sclboolean ret = FALSE;
2082 //if (m_input_events_disabled) return FALSE;
2084 //utils->log("Controller::mouse_release : %d %d\n", x, y);
2085 /* Adjust x,y coordinate by touch offset */
2086 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2088 CSCLContext *context = CSCLContext::get_instance();
2089 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2090 CSCLActionState *state = CSCLActionState::get_instance();
2091 CSCLWindows *windows = CSCLWindows::get_instance();
2092 CSCLUtils *utils = CSCLUtils::get_instance();
2093 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2095 sclint btnIndex = NOT_USED;
2097 if (cache && state && windows && context && utils && handler && context->find_multi_touch_context(touch_id)) {
2098 const SclLayout *layout = cache->get_cur_layout(window);
2100 x += layout->mouse_manipulate_x;
2101 y += layout->mouse_manipulate_y;
2104 sclwindow skipwindow = SCLWINDOW_INVALID;
2105 SCLDisplayMode display_mode = context->get_display_mode();
2107 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2108 PSclDefaultConfigure default_configure = NULL;
2109 if (sclres_manager) {
2110 default_configure = sclres_manager->get_default_configure();
2112 if (default_configure) {
2113 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2116 context->set_cur_move_window(touch_id, SCLWINDOW_INVALID);
2118 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2119 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2120 //SclWindowContext *winctx = windows->get_window_context(window, TRUE);
2121 SclWindowContext *winctx = windows->get_window_context(window);
2122 /* Adjust event x and y positions as relative position to the virtual window */
2124 /*if (winctx->isVirtual) {
2125 SclWindowContext *basectx = windows->get_window_context(windows->get_base_window());
2127 x -= (winctx->x - basectx->x);
2128 y -= (winctx->y - basectx->y);
2131 /* If the dim window is virtual and currently active, consider base window's event is occured in dim window */
2132 if (windows->is_base_window(window)) {
2133 SclWindowContext *dimctx = windows->get_window_context(windows->get_dim_window());
2135 if (dimctx->is_virtual && !(dimctx->hidden)) {
2136 window = windows->get_dim_window();
2143 /* Iterate all the buttons and inform the event */
2144 sclboolean ended = FALSE;
2145 CSCLUtils *utils = CSCLUtils::get_instance();
2147 /* FIXME : The routine below seems to be removed, which was originally requested by Vodafone,
2148 * to slow down the speed of repeat key right before stopping repeatkey event */
2149 /* if (state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY) {
2150 if (m_key_repeated_num > 10) {
2152 process_button_repeat_pressed_event(pressed_window, pressed_key, touch_id);
2157 if (context->get_cur_pressed_window(touch_id) == window) {
2158 if (abs(context->get_cur_pressed_point(touch_id).x - x) > utils->get_scale_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD) ||
2159 abs(context->get_cur_pressed_point(touch_id).y - y) > utils->get_scale_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD) )
2161 struct timeval t0 = context->get_cur_pressed_time(touch_id);
2163 gettimeofday(&t1, NULL);
2165 etime = ((t1.tv_sec * 1000000 + t1.tv_usec) - (t0.tv_sec * 1000000 + t0.tv_usec))/1000.0;
2166 if (etime < SCL_FLICK_GESTURE_RECOG_TIME) {
2167 sclint direction = DRAG_NONE;
2168 if (x > context->get_cur_pressed_point(touch_id).x + utils->get_scale_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2169 direction = DRAG_RIGHT;
2171 if (x < context->get_cur_pressed_point(touch_id).x - utils->get_scale_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2172 direction = DRAG_LEFT;
2174 if (y > context->get_cur_pressed_point(touch_id).y + utils->get_scale_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2175 direction = DRAG_DOWN;
2177 if (y < context->get_cur_pressed_point(touch_id).y - utils->get_scale_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2178 direction = DRAG_UP;
2180 if (handler->on_event_notification(SCL_UINOTITYPE_GESTURE_FLICK, direction)) {
2187 /* FIXME : We should consider this kind of action in general manner, not only specific to autopopup */
2188 /* And also, this kind of implementation only selects button that was highlighted at least once. */
2189 /* iPhone supports highlighting autopopup buttons with its direction, even if the pointer never goes up on the button */
2191 //SclWindowContext *pressedCtx = windows->get_window_context(pressed_window, FALSE);
2192 SclWindowContext *pressedCtx = windows->get_window_context(pressed_window);
2194 utils->log("PRESSED CTX : %p %d %d\n", pressed_window, pressedCtx->geometry.x, pressedCtx->geometry.y);
2195 //if (pressedCtx->popuptype == POPUP_TYPE_AUTO_POPUP) {
2196 sclboolean grab_event = FALSE;
2197 const SclLayout *layout = cache->get_cur_layout(pressed_window);
2199 if (layout->style == LAYOUT_STYLE_POPUP_GRAB) {
2202 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
2204 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
2205 sclboolean in_grab_area = TRUE;
2206 if (layout->add_grab_left != NOT_USED && x < (pressedCtx->geometry.x - layout->add_grab_left)) {
2207 in_grab_area = FALSE;
2209 if (layout->add_grab_right != NOT_USED &&
2210 x > (pressedCtx->geometry.x + pressedCtx->geometry.width + layout->add_grab_right)) {
2211 in_grab_area = FALSE;
2213 if (layout->add_grab_top != NOT_USED && y < (pressedCtx->geometry.y - layout->add_grab_top)) {
2214 in_grab_area = FALSE;
2216 if (layout->add_grab_bottom != NOT_USED &&
2217 y > (pressedCtx->geometry.y + pressedCtx->geometry.height + layout->add_grab_bottom)) {
2218 in_grab_area = FALSE;
2221 SclLayoutKeyCoordinate *coord = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2223 x = coord->x + (coord->width / 2);
2224 y = coord->y + (coord->height / 2);
2226 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2227 SclButtonContext *btncontext = cache->get_cur_button_context(pressed_window, loop);
2228 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2229 if (btncontext && coordinate) {
2230 if (!(btncontext->used)) {
2232 } else if (btncontext->state != BUTTON_STATE_DISABLED &&
2233 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2234 if (process_button_release_event(pressed_window, x, y, loop, touch_id, actual_event)) {
2248 SclButtonContext *btncontext = cache->get_cur_button_context(pressed_window, pressed_key);
2249 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2251 /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2252 /* Ignore base window's release event if a popup window is opened */
2253 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2254 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2255 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2256 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2257 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2258 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2259 if (windows->is_base_window(window)) {
2261 /* In case of direction button, the release event on other window should be processed */
2262 if (coordinate && winctx && pressedCtx) {
2263 if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2264 sclint relx = (winctx->geometry.x + x) - pressedCtx->geometry.x;
2265 sclint rely = (winctx->geometry.y + y) - pressedCtx->geometry.y;
2266 if (process_button_release_event(pressed_window, relx, rely, pressed_key, touch_id, actual_event)) {
2267 btnIndex = pressed_key;
2269 x = coordinate->x + (coordinate->width / 2);
2270 y = coordinate->y + (coordinate->height / 2);
2271 skipwindow = pressed_window;
2278 MultiTouchContext *mulctx = context->find_multi_touch_context(touch_id);
2280 if (!(mulctx->is_sub_event)) {
2281 /* First check if the event occured in pressed key's threshold area */
2282 if (btncontext && coordinate && !ended) {
2283 if (btncontext->used && btncontext->state != BUTTON_STATE_DISABLED) {
2284 if (process_button_release_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
2285 btnIndex = pressed_key;
2287 x = coordinate->x + (coordinate->width / 2);
2288 y = coordinate->y + (coordinate->height / 2);
2292 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2293 SclButtonContext *btncontext = cache->get_cur_button_context(window, loop);
2294 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2295 if (btncontext && coordinate) {
2296 if (!(btncontext->used)) {
2298 } else if (btncontext->state != BUTTON_STATE_DISABLED &&
2299 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2300 if (window != pressed_window || loop != pressed_key) {
2301 if (process_button_release_event(window, x, y, loop, touch_id, actual_event)) {
2310 SclUIEventDesc key_event_desc = {0};
2311 key_event_desc.key_value = NULL;
2312 key_event_desc.key_event = NOT_USED;
2313 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
2314 key_event_desc.event_type = EVENT_TYPE_NONE;
2315 key_event_desc.touch_id = touch_id;
2316 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2317 key_event_desc.mouse_current_point = context->get_cur_move_point(touch_id);
2318 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2320 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2322 handler->on_event_key_clicked(key_event_desc);
2326 /* For covering a missing area about 1 pixel */
2330 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2331 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2332 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2333 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2334 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2335 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2336 if (windows->is_base_window(window)) {
2341 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2342 SclButtonContext *btncontext = cache->get_cur_button_context(window, loop);
2343 if (btncontext && coordinate) {
2344 if (!(btncontext->used)) {
2347 } else if (btncontext->state != BUTTON_STATE_DISABLED &&
2348 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2349 if (process_button_release_event(window, x+1, y+1, loop, touch_id)) {
2359 if (windows->is_base_window(window)) {
2360 state->set_cur_action_state(ACTION_STATE_BASE_INIT);
2362 state->set_cur_action_state(ACTION_STATE_POPUP_INIT);
2365 /* Restore previously pressed button's context and redraw it */
2366 if (btncontext && coordinate) {
2367 btncontext->state = BUTTON_STATE_NORMAL;
2368 /* Commented below line to postpone some of the feedback for releasing */
2369 //windows->update_window(pressed_window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2372 /* If there is postponed update of button, update it now */
2373 CSCLEvents *events = CSCLEvents::get_instance();
2374 sclwindow last_win = context->get_last_pressed_window();
2375 scl8 last_key = context->get_last_pressed_key();
2376 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2377 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2379 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2383 /* To postpone some of the feedback for releasing */
2384 context->set_last_pressed_key(context->get_cur_pressed_key(touch_id));
2385 context->set_last_pressed_window(context->get_cur_pressed_window(touch_id));
2387 /* Do what has to be done when mouse gets released */
2388 sclboolean signaled = FALSE;
2390 switch (coordinate->popup_type) {
2391 case POPUP_TYPE_BTN_RELEASE_POPUP:
2392 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
2393 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
2394 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
2395 /* Fix me : We should consider z-order */
2396 skipwindow = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2397 handle_engine_signal(SCL_SIG_MOUSE_RELEASE, skipwindow);
2403 //SclWindowContext *ctx = windows->get_window_context(window, FALSE);
2404 SclWindowContext *ctx = windows->get_window_context(window);
2406 if (ctx->popup_type == POPUP_TYPE_BTN_RELEASE_POPUP ||
2407 ctx->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP) {
2408 /* Don't close window if the clicked button is a child of ReleasePopup window */
2409 skipwindow = window;
2410 handle_engine_signal(SCL_SIG_MOUSE_RELEASE, window);
2415 handle_engine_signal(SCL_SIG_MOUSE_RELEASE);
2419 context->set_cur_pressed_key(touch_id, NOT_USED);
2420 context->set_cur_pressed_window(touch_id, SCLWINDOW_INVALID);
2422 if (ret && btnIndex != NOT_USED) {
2423 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, btnIndex);
2425 if (coordinate->dont_close_popup) {
2426 skipwindow = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2430 if (pressed_window == windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP)) {
2432 if (pressedCtx->popup_type != POPUP_TYPE_BTN_RELEASE_POPUP_ONCE &&
2433 pressedCtx->popup_type != POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE &&
2434 pressedCtx->popup_type != POPUP_TYPE_AUTO_POPUP &&
2435 pressedCtx->popup_type != POPUP_TYPE_BTN_PRESS_POPUP_DRAG)
2437 skipwindow = pressed_window;
2442 windows->close_all_popups(skipwindow);
2444 /* Destroy key related timers */
2445 events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2446 events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2447 events->destroy_timer(SCL_TIMER_LONGKEY);
2448 events->destroy_timer(SCL_TIMER_REPEATKEY);
2450 /* If there are more than 1 active multitouch ids, don't play button_delay trick */
2451 if (context->get_multi_touch_context_num() == 1) {
2452 /* To postpone some of the feedback for releasing */
2453 events->create_timer(SCL_TIMER_BUTTON_DELAY, m_button_delay_duration, 0);
2455 sclwindow last_win = context->get_last_pressed_window();
2456 scl8 last_key = context->get_last_pressed_key();
2458 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2459 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(last_win, last_key);
2461 windows->update_window(last_win,
2462 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2466 windows->hide_window(windows->get_magnifier_window());
2467 context->set_last_pressed_window(SCLWINDOW_INVALID);
2468 context->set_last_pressed_key(NOT_USED);
2473 if (touch_id == context->get_last_touch_device_id()) {
2474 context->set_last_touch_device_id(SCLTOUCHDEVICE_INVALID);
2476 context->destroy_multi_touch_context(touch_id);
2482 SCLDragState get_drag_state(sclint deltax, sclint deltay)
2484 SCLDragState ret = SCL_DRAG_STATE_MAX;
2486 sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
2487 /* If tan(theta) is smaller than our predefined value */
2488 if (ratio <= (1 / SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE)) {
2490 ret = SCL_DRAG_STATE_RIGHT;
2492 ret = SCL_DRAG_STATE_LEFT;
2494 } /* If tan(theta) is bigger than our predefined value */
2495 else if (ratio >= SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE) {
2497 ret = SCL_DRAG_STATE_DOWN;
2499 ret = SCL_DRAG_STATE_UP;
2502 ret = SCL_DRAG_STATE_INVALID;
2509 CSCLController::mouse_move(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2512 sclboolean ret = FALSE;
2514 if (m_input_events_disabled) return FALSE;
2516 //utils->log("Controller::mouse_move : %d %d\n", x, y);
2518 /* Adjust x,y coordinate by touch offset */
2519 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2521 CSCLContext *context = CSCLContext::get_instance();
2522 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2523 CSCLActionState *state = CSCLActionState::get_instance();
2524 CSCLWindows *windows = CSCLWindows::get_instance();
2525 CSCLEvents *events = CSCLEvents::get_instance();
2526 CSCLUtils *utils = CSCLUtils::get_instance();
2527 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2528 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2529 PSclModifierDecoration sclres_modifier_decoration = sclres_manager->get_modifier_decoration_table();
2530 assert(sclres_modifier_decoration != NULL);
2532 if (cache && state && windows && context && utils && adjustment) {
2533 const SclLayout *layout = cache->get_cur_layout(window);
2535 x += layout->mouse_manipulate_x;
2536 y += layout->mouse_manipulate_y;
2539 if (!(context->find_multi_touch_context(touch_id))) return FALSE;
2541 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2542 PSclDefaultConfigure default_configure = NULL;
2543 if (sclres_manager) {
2544 default_configure = sclres_manager->get_default_configure();
2546 if (default_configure) {
2547 SCLDisplayMode display_mode = context->get_display_mode();
2548 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2551 //SclWindowContext *winctx = windows->get_window_context(window, FALSE);
2552 SclWindowContext *winctx = windows->get_window_context(window);
2553 /* Adjust event x and y positions as relative position to the virtual window */
2555 /*if (winctx->isVirtual) {
2556 SclWindowContext *basectx = windows->get_window_context(windows->get_base_window());
2558 x -= (winctx->x - basectx->x);
2559 y -= (winctx->y - basectx->y);
2562 /* If the dim window is virtual and currently active, let's just skip this event */
2563 if (windows->is_base_window(window)) {
2564 SclWindowContext *dimctx = windows->get_window_context(windows->get_dim_window());
2566 if (dimctx->is_virtual && !(dimctx->hidden)) {
2571 /* If the pressed event was occured in dim window, let's just skip this move event */
2572 if (context->get_last_pressed_window() == windows->get_dim_window()) {
2577 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2578 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2579 SclButtonContext *btncontext = cache->get_cur_button_context(pressed_window, pressed_key);
2580 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2582 /* If the multitouch type is SETTLE_PREVIOUS and is not the last touch device, let's ignore move events */
2584 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
2585 if (context->get_last_touch_device_id() != touch_id) {
2591 context->set_cur_move_point(touch_id, x, y);
2592 context->set_cur_move_window(touch_id, window);
2594 /* If in longkey state, do not process, just return */
2595 if (state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
2596 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
2597 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
2598 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY) {
2601 /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2602 /* And if the event occured in popup window, don't come back to base window */
2603 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2604 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2605 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2606 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2607 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2608 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2609 if (windows->is_base_window(window)) {
2614 /* FIXME : Add a condition to skip this code if longkey timer is not active */
2615 /* If the mouse has moved out of threshold value of longkey keypress area, destroy longkey timer */
2616 if (m_long_key_cancel_distance > 0) {
2617 sclfloat dist = utils->get_distance(x, y,
2618 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2619 if (m_long_key_cancel_distance < dist) {
2620 events->destroy_timer(SCL_TIMER_LONGKEY);
2624 if (windows->is_base_window(window)) {
2625 state->set_cur_action_state(ACTION_STATE_BASE_MOVING);
2627 state->set_cur_action_state(ACTION_STATE_POPUP_MOVING);
2630 /* Iterate all the buttons and inform the event */
2631 sclboolean ended = FALSE;
2633 /* Check farthest move point and update it */
2636 if (pressed_window != window) {
2637 //SclWindowContext *pressedwinctx = windows->get_window_context(pressed_window, FALSE);
2638 SclWindowContext *pressedwinctx = windows->get_window_context(pressed_window);
2639 if (winctx && pressedwinctx) {
2640 originx = (winctx->geometry.x - pressedwinctx->geometry.x) + x;
2641 originy = (winctx->geometry.y - pressedwinctx->geometry.y) + y;
2644 sclint startx = originx;
2645 sclint starty = originy;
2647 /* Check if we should recognize drag curve */
2649 startx = context->get_cur_pressed_point(touch_id).x;
2650 starty = context->get_cur_pressed_point(touch_id).y;
2651 sclint deltax = originx - startx;
2652 sclint deltay = originy - starty;
2653 sclfloat dist = utils->get_approximate_distance(originx, originy, startx, starty);
2654 CSCLUtils *utils = CSCLUtils::get_instance();
2656 sclboolean update_magnifier = FALSE;
2657 sclboolean drag_state_changed = FALSE;
2658 SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
2659 SCLDragState next_drag_state = SCL_DRAG_STATE_NONE;
2660 sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
2661 if (coordinate->is_side_button) {
2662 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
2665 if (coordinate->button_type == BUTTON_TYPE_DIRECTION) {
2666 /* Do not check farthest move point if current drag state is SCL_DRAG_STATE_RETURN */
2667 if (context->get_cur_drag_state(touch_id) != SCL_DRAG_STATE_RETURN) {
2668 if (dist > context->get_farthest_move_dist(touch_id)) {
2669 context->set_farthest_move_point(touch_id, originx, originy);
2673 if (cur_drag_state == SCL_DRAG_STATE_RETURN) {
2674 direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_RETURN;
2675 } else if (cur_drag_state != SCL_DRAG_STATE_NONE) {
2676 direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_OTHER;
2678 if (dist > direction_recog_dist) {
2679 next_drag_state = get_drag_state(deltax, deltay);
2680 /* Disable longkey if dragging is recognized */
2681 events->destroy_timer(SCL_TIMER_LONGKEY);
2683 if (cur_drag_state != next_drag_state) {
2684 drag_state_changed = TRUE;
2686 if (cur_drag_state == SCL_DRAG_STATE_NONE) {
2687 //if (nextDragState != SCL_DRAG_STATE_INVALID) {
2688 cur_drag_state = next_drag_state;
2690 } else if (cur_drag_state != next_drag_state) {
2691 if (next_drag_state == SCL_DRAG_STATE_NONE) {
2692 cur_drag_state = SCL_DRAG_STATE_RETURN;
2694 cur_drag_state = next_drag_state;
2698 context->set_cur_drag_state(touch_id, cur_drag_state);
2699 sclboolean check_farthest = FALSE;
2700 sclshort display = context->get_display_mode();
2701 if (!scl_check_arrindex(display, DISPLAYMODE_MAX)) display = 0;
2702 sclfloat dist = utils->get_distance(originx, originy,
2703 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2704 if (dist < direction_recog_dist && context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
2705 if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
2706 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
2707 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
2708 deltax = context->get_farthest_move_point(touch_id).x -
2709 context->get_cur_pressed_point(touch_id).x;
2710 deltay = context->get_farthest_move_point(touch_id).y -
2711 context->get_cur_pressed_point(touch_id).y;
2712 dist = utils->get_distance(context->get_farthest_move_point(touch_id),
2713 context->get_cur_pressed_point(touch_id));
2714 check_farthest = TRUE;
2717 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist,
2718 check_farthest, touch_id, coordinate->extra_option);
2719 if (dist > direction_recog_dist) {
2720 context->set_cur_key_modifier(touch_id, key_modifier);
2722 /* If this button needs to be decorated when dragged */
2723 if (coordinate->modifier_decorator) {
2724 const SclModifierDecoration *decoration = NULL;
2726 /*if (scl_check_arrindex(coordinate->modifier_decorator,
2727 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
2728 scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
2729 if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
2730 if (sclres_modifier_decoration[decoration_id].valid) {
2731 decoration = &(sclres_modifier_decoration[decoration_id]);
2734 /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
2736 if (decoration->bg_image_path[display][key_modifier]) {
2737 windows->update_window(window,
2738 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2742 if (dist > direction_recog_dist) {
2743 SclUIEventDesc desc = {0};
2744 SCLShiftState shiftidx = context->get_shift_state();
2745 desc.key_type = coordinate->key_type;
2746 desc.key_value = coordinate->key_value[shiftidx][0];
2747 desc.key_event = coordinate->key_event[shiftidx][0];
2748 desc.event_type = EVENT_TYPE_MOVE;
2749 desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2750 desc.mouse_current_point = context->get_cur_move_point(touch_id);
2751 desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2752 desc.key_modifier = key_modifier;
2754 if (handler->on_event_drag_state_changed(desc) && context->get_magnifier_enabled()) {
2755 update_magnifier = TRUE;
2758 } else if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2759 if (cur_drag_state != SCL_DRAG_STATE_NONE) {
2760 startx = context->get_prev_move_point(touch_id).x;
2761 starty = context->get_prev_move_point(touch_id).y;
2762 dist = utils->get_approximate_distance(originx, originy, startx, starty);
2763 direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
2765 deltax = originx - startx;
2766 deltay = originy - starty;
2767 //printf("DIST : %f, RECOG : %f\n", dist, direction_recog_dist);
2768 if (dist > direction_recog_dist) {
2769 next_drag_state = get_drag_state(deltax, deltay);
2770 /* Disable longkey if dragging is recognized */
2771 events->destroy_timer(SCL_TIMER_LONGKEY);
2773 if (cur_drag_state != next_drag_state) {
2774 drag_state_changed = TRUE;
2776 if (next_drag_state != SCL_DRAG_STATE_NONE) {
2777 cur_drag_state = next_drag_state;
2779 context->set_cur_drag_state(touch_id, cur_drag_state);
2781 startx = context->get_farthest_move_point(touch_id).x;
2782 starty = context->get_farthest_move_point(touch_id).y;
2783 deltax = originx - startx;
2784 deltay = originy - starty;
2785 sclfloat dist_farthest = utils->get_approximate_distance(originx, originy, startx, starty);
2786 printf("%d %d %d %d %f, %d %d\n", originx, originy, startx, starty, dist_farthest, cur_drag_state, next_drag_state);
2787 /* Let's see how much we are away from the last farthest point */
2788 sclfloat diffdir_recog_dist = SCL_DIRECTION_RELATIVE_DIFFDIR_RECOG_DIST * utils->get_smallest_scale_rate();
2789 /* If we moved certain amount from the point where direction changed, process drag state change routine */
2790 if (dist_farthest > diffdir_recog_dist || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_NONE) {
2791 sclshort display = context->get_display_mode();
2792 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist_farthest,
2793 FALSE, touch_id, coordinate->extra_option);
2794 context->set_cur_key_modifier(touch_id, key_modifier);
2795 /* If this button needs to be decorated when dragged */
2796 if (coordinate->modifier_decorator) {
2797 const SclModifierDecoration *decoration = NULL;
2799 /*if (scl_check_arrindex(coordinate->modifier_decorator,
2800 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
2801 scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
2802 if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
2803 if (sclres_modifier_decoration[decoration_id].valid) {
2804 decoration = &(sclres_modifier_decoration[decoration_id]);
2807 /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
2809 if (decoration->bg_image_path[display][key_modifier]) {
2810 windows->update_window(window,
2811 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2816 SclUIEventDesc desc = {0};
2817 SCLShiftState shiftidx = context->get_shift_state();
2818 desc.key_type = coordinate->key_type;
2819 desc.key_value = coordinate->key_value[shiftidx][0];
2820 desc.key_event = coordinate->key_event[shiftidx][0];
2821 desc.event_type = EVENT_TYPE_MOVE;
2822 desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2823 desc.mouse_current_point = context->get_cur_move_point(touch_id);
2824 desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2825 desc.key_modifier = key_modifier;
2827 if (handler->on_event_drag_state_changed(desc) && context->get_magnifier_enabled()) {
2828 update_magnifier = TRUE;
2831 context->set_prev_move_point(touch_id, originx, originy);
2833 if (drag_state_changed) {
2834 /* When the dragging direction changes, save the current position as farthest point for future comparison */
2835 context->set_farthest_move_point(touch_id, originx, originy);
2836 printf("SET_FARTHEST : %d %d %d\n", originx, originy, context->get_cur_drag_state(touch_id));
2840 if (update_magnifier) {
2841 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2842 PSclMagnifierWndConfigure magnifier_configure = NULL;
2843 if (sclres_manager) {
2844 magnifier_configure = sclres_manager->get_magnifier_configure();
2847 const SclLayout *layout = cache->get_cur_layout(windows->get_base_window());
2848 if (layout && magnifier_configure) {
2849 sclfloat scale_rate_x, scale_rate_y;
2850 if (layout->display_mode == DISPLAYMODE_PORTRAIT) {
2851 scale_rate_x = utils->get_scale_rate_x();
2852 scale_rate_y = utils->get_scale_rate_y();
2854 scale_rate_x = utils->get_scale_rate_y();
2855 scale_rate_y = utils->get_scale_rate_x();
2858 SclPoint zoomwinpos = {0,};
2859 /* calculates x position to be set */
2860 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
2861 (magnifier_configure->width / 2);
2863 /* calculates y position to be set */
2864 sclint scnWidth, scnHeight;
2865 utils->get_screen_resolution(&scnWidth, &scnHeight);
2867 zoomwinpos.y = coordinate->y - magnifier_configure->height;
2868 SclWindowContext *winctx = windows->get_window_context(window);
2870 zoomwinpos.x += winctx->geometry.x;
2871 zoomwinpos.y += winctx->geometry.y;
2873 if (zoomwinpos.x < 0 - magnifier_configure->padding_x) {
2874 zoomwinpos.x = 0 - magnifier_configure->padding_x;
2876 if (zoomwinpos.x > scnWidth + magnifier_configure->padding_x - magnifier_configure->width) {
2877 zoomwinpos.x = scnWidth + magnifier_configure->padding_x - magnifier_configure->width;
2879 zoomwinpos.y += magnifier_configure->padding_y;
2881 zoomwinpos.x += coordinate->magnifier_offset_x;
2882 zoomwinpos.y += coordinate->magnifier_offset_y;
2883 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y);
2884 windows->show_window(windows->get_magnifier_window(), 0);
2889 sclboolean grab_event = FALSE;
2891 if (layout->style == LAYOUT_STYLE_POPUP_GRAB) {
2894 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
2895 if (grab_event && winctx) {
2896 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
2897 sclboolean in_grab_area = TRUE;
2898 if (layout->add_grab_left != NOT_USED && x < -(layout->add_grab_left)) {
2899 in_grab_area = FALSE;
2901 if (layout->add_grab_right != NOT_USED && x > (winctx->geometry.width + layout->add_grab_right)) {
2902 in_grab_area = FALSE;
2904 if (layout->add_grab_top != NOT_USED && y < -(layout->add_grab_top)) {
2905 in_grab_area = FALSE;
2907 if (layout->add_grab_bottom != NOT_USED && y > (winctx->geometry.height + layout->add_grab_bottom)) {
2908 in_grab_area = FALSE;
2911 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2913 float min_dist = (float)((unsigned int)(-1));
2914 int min_dist_index = NOT_USED;
2915 for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
2916 btncontext = cache->get_cur_button_context(window, loop);
2917 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2918 if (btncontext && coordinate) {
2919 if (!(btncontext->used)) {
2921 } else if (btncontext->state != BUTTON_STATE_DISABLED &&
2922 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2923 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2925 float dist = utils->get_approximate_distance(x, y,
2926 coordinate->x + (coordinate->width / 2), coordinate->y + (coordinate->height / 2));
2927 if (dist < min_dist) {
2928 min_dist_index = loop;
2935 /* When we found the nearest button, generate this event on the button */
2936 if (min_dist_index != NOT_USED) {
2937 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, min_dist_index);
2938 x = coordinate->x + (coordinate->width / 2);
2939 y = coordinate->y + (coordinate->height / 2);
2940 if (process_button_move_event(window, x, y, min_dist_index, touch_id, actual_event)) {
2947 MultiTouchContext *mulctx = context->find_multi_touch_context(touch_id);
2949 if (!(mulctx->is_sub_event)) {
2950 /* First check if the event occured in pressed key's threshold area */
2951 if (btncontext && coordinate) {
2952 if (pressed_window == window) { // Check only when the window is the one initally pressed
2953 if (btncontext->used && btncontext->state != BUTTON_STATE_DISABLED) {
2954 if (process_button_move_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
2956 x = coordinate->x + (coordinate->width / 2);
2957 y = coordinate->y + (coordinate->height / 2);
2962 for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
2963 btncontext = cache->get_cur_button_context(window, loop);
2964 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2965 if (btncontext && coordinate) {
2966 if (!(btncontext->used)) {
2968 } else if (btncontext->state != BUTTON_STATE_DISABLED &&
2969 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2970 if (window != pressed_window || loop != pressed_key) {
2971 if (process_button_move_event(window, x, y, loop, touch_id, actual_event)) {
2988 CSCLController::mouse_over(sclwindow window, sclint x, sclint y)
2991 sclboolean ret = FALSE;
2993 if(m_input_events_disabled)
2996 /* Adjust x,y coordinate by touch offset */
2997 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2998 /* Iterate all the buttons and inform the event */
3000 CSCLContext *context = CSCLContext::get_instance();
3001 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3002 CSCLActionState *state = CSCLActionState::get_instance();
3003 CSCLWindows *windows = CSCLWindows::get_instance();
3004 CSCLUtils *utils = CSCLUtils::get_instance();
3005 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3007 if (cache && state && windows && context && utils && adjustment && sclres_manager) {
3008 const SclLayout *layout = cache->get_cur_layout(window);
3010 x += layout->mouse_manipulate_x;
3011 y += layout->mouse_manipulate_y;
3014 SCLDisplayMode cur_display_mode = context->get_display_mode();
3016 const SclDefaultConfigure *default_configure = sclres_manager->get_default_configure();
3017 if (default_configure) {
3018 adjustment->apply_touch_offset(default_configure->touch_offset_level[cur_display_mode], &x, &y);
3021 /* Iterate all the buttons and inform the event */
3022 sclboolean ended = FALSE;
3024 for (int loop = 0; loop < MAX_KEY && !ended && !ret; loop++) {
3025 SclButtonContext *btncontext = cache->get_cur_button_context(window, loop);
3026 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3027 if (btncontext && coordinate) {
3028 if (!(btncontext->used)) {
3030 } else if (btncontext->state != BUTTON_STATE_DISABLED &&
3031 coordinate->button_type != BUTTON_TYPE_UIITEM) {
3032 if (process_button_over_event(window, x, y, loop)) {
3045 * Processes a timer event
3046 * If return FALSE, the current timer will be stop
3047 * ID : SCL_LOWORD(data)
3048 * value : SCL_HIWORD(data)
3051 CSCLController::timer_event(const scl32 data)
3054 struct typeA {short x; short y;};
3055 struct typeB {short x; short y;};
3058 CSCLWindows *windows = CSCLWindows::get_instance();
3059 CSCLContext *context = CSCLContext::get_instance();
3060 CSCLEvents* events = CSCLEvents::get_instance();
3061 CSCLActionState *state = CSCLActionState::get_instance();
3062 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3063 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3065 scl16 id = SCL_LOWORD(data); /* Timer ID */
3066 scl16 value = SCL_HIWORD(data); /* event unique ID */
3069 case SCL_TIMER_AUTOPOPUP: {
3070 /* Checks whether my event id is availble */
3071 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3072 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3073 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3074 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3075 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3076 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3077 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3078 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3079 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3080 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3081 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3083 /* Ignores if the event id is different */
3087 SclRectangle rect = {0,};
3088 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3089 sclbyte keyIndex = context->get_cur_pressed_key(context->get_last_touch_device_id());
3091 if (configure_autopopup_window(window, keyIndex, &rect)) {
3092 /* Let's change out pressed button's state back to normal */
3093 SclButtonContext *btncontext = cache->get_cur_button_context(window, keyIndex);
3094 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, keyIndex);
3097 if (btncontext->state == BUTTON_STATE_PRESSED) {
3098 btncontext->state = BUTTON_STATE_NORMAL;
3099 CSCLWindows *windows = CSCLWindows::get_instance();
3100 if (windows && coordinate) {
3101 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3105 /* Hide magnifier window when opening autopopup window */
3106 windows->hide_window(windows->get_magnifier_window());
3107 /* Currently, window does not support virtual window */
3108 SclWindowOpener opener;
3109 opener.window = window;
3110 opener.key = keyIndex;
3111 sclwindow popup_window = windows->open_popup(
3115 SCL_LAYOUT_AUTOPOPUP, POPUP_TYPE_AUTO_POPUP,
3119 _play_tts_for_layout_autopopup_name();
3121 sclwindow move_window = context->get_cur_move_window(context->get_last_touch_device_id());
3122 SclPoint move_point = context->get_cur_move_point(context->get_last_touch_device_id());
3123 SclWindowContext *move_ctx = windows->get_window_context(move_window);
3124 SclWindowContext *popup_ctx = windows->get_window_context(popup_window);
3125 if (move_ctx && popup_ctx) {
3126 move_point.x = (move_ctx->geometry.x - popup_ctx->geometry.x) + move_point.x;
3127 move_point.y = (move_ctx->geometry.y - popup_ctx->geometry.y) + move_point.y;
3129 printf("AUTOPOPUP : %d %d\n", move_point.x, move_point.y);
3131 CSCLWindows *windows = CSCLWindows::get_instance();
3132 if (windows && coordinate) {
3133 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3136 events->destroy_timer(id);
3142 case SCL_TIMER_LONGKEY: {
3143 /* Checks whether my event id is availble */
3144 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3145 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3146 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3147 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3148 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3149 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3150 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3151 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3152 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3153 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3154 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3156 /* Ignores if the event id is different */
3159 /* Ignores if the event id is different */
3160 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3161 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3162 if (process_button_long_pressed_event(window, key_index, context->get_last_touch_device_id())) {
3163 /* The button processed long key event, now enter longkey mode not to fire any events before releasing */
3164 handle_engine_signal(SCL_SIG_MOUSE_LONG_PRESS, window);
3165 windows->update_window(windows->get_magnifier_window());
3167 SclButtonContext *btncontext = cache->get_cur_button_context(window, key_index);
3168 if (btncontext->state == BUTTON_STATE_PRESSED) {
3169 btncontext->state = BUTTON_STATE_NORMAL;
3170 CSCLWindows *windows = CSCLWindows::get_instance();
3172 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3173 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3176 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3177 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3180 /* Start the repeat key timer for NORMAL or GRAB buttons if longkey is not supported */
3181 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3184 /* This is for enabling backspace key in search layout*/
3185 //if (coordinate->use_repeat_key) {
3186 if (coordinate->use_repeat_key
3187 || coordinate->key_event[0][0] == MVK_BackSpace) {
3188 if (coordinate->button_type == BUTTON_TYPE_NORMAL ||
3189 coordinate->button_type == BUTTON_TYPE_GRAB ||
3190 coordinate->button_type == BUTTON_TYPE_SELFISH ||
3191 coordinate->button_type == BUTTON_TYPE_DIRECTION ||
3192 coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
3193 m_key_repeated_num = 0;
3194 events->create_timer(SCL_TIMER_REPEATKEY, m_repeat_key_duration, value);
3195 if (windows->is_base_window(window)) {
3196 state->set_cur_action_state(ACTION_STATE_BASE_REPEATKEY);
3198 state->set_cur_action_state(ACTION_STATE_POPUP_REPEATKEY);
3204 events->destroy_timer(id);
3209 case SCL_TIMER_REPEATKEY: {
3210 /* Checks whether my event id is availble */
3211 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3212 (state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
3213 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY)
3215 /* Ignores if the event id is different */
3218 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3219 sclbyte keyIndex = context->get_cur_pressed_key(context->get_last_touch_device_id());
3220 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
3221 if (interval < SCL_REPEATKEY_MIN_DURATION) {
3222 interval = SCL_REPEATKEY_MIN_DURATION;
3224 process_button_repeat_pressed_event(window, keyIndex, context->get_last_touch_device_id());
3225 events->destroy_timer(id);
3226 events->create_timer(SCL_TIMER_REPEATKEY, interval, value);
3227 m_key_repeated_num++;
3231 case SCL_TIMER_BUTTON_DELAY: {
3232 /* If there is postponed update of button, update it now */
3233 sclwindow last_window = context->get_last_pressed_window();
3234 scl8 last_key = context->get_last_pressed_key();
3236 if (last_window != SCLWINDOW_INVALID && last_key != NOT_USED) {
3237 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_window, last_key);
3239 windows->update_window(last_window, coords->x, coords->y, coords->width, coords->height);
3243 /* FIXME : Temporary way of clearing magnifier window */
3245 CSCLGraphics *graphics = CSCLGraphics::get_instance();
3246 CSCLUtils *utils = CSCLUtils::get_instance();
3247 sclchar composed_path[_POSIX_PATH_MAX] = {0,};
3248 scldrawctx draw_ctx = graphics->begin_paint(windows->get_magnifier_window());
3249 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3250 PSclMagnifierWndConfigure magnifier_configure = NULL;
3251 if (sclres_manager) {
3252 magnifier_configure = sclres_manager->get_magnifier_configure();
3254 if (magnifier_configure) {
3255 utils->get_composed_path(composed_path, IMG_PATH_PREFIX, magnifier_configure->bg_image_path);
3256 graphics->draw_image(windows->get_magnifier_window(), draw_ctx, composed_path, 0, 0);
3257 graphics->end_paint(windows->get_magnifier_window(), draw_ctx);
3261 windows->hide_window(windows->get_magnifier_window());
3262 context->set_last_pressed_window(SCLWINDOW_INVALID);
3263 context->set_last_pressed_key(NOT_USED);
3264 events->destroy_timer(id);
3268 case SCL_TIMER_POPUP_TIMEOUT: {
3269 windows->close_all_popups();
3271 handler->on_event_notification(SCL_UINOTITYPE_POPUP_TIMEOUT, data);
3272 events->destroy_timer(id);
3276 case SCL_TIMER_AUTOTEST: {
3277 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3278 SCLDisplayMode display_mode = context->get_display_mode();
3280 sclint rnd = rand() % 100;
3281 sclint x = (rand() % (cache->get_cur_layout(windows->get_base_window())->width));
3282 sclint y = (rand() % (cache->get_cur_layout(windows->get_base_window())->height));
3285 events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3286 events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3287 } else if (rnd < 90) {
3288 events->generate_mouse_event(SCL_MOUSE_EVENT_MOVE, x, y);
3289 } else if (rnd < 95) {
3290 events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3292 events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3296 if (m_debug_variable < SCL_AUTOTEST_NUM) events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INTERVAL, 0, FALSE);
3297 else m_debug_mode = DEBUGMODE_DISABLED;
3303 events->destroy_timer(id);
3311 /* Handles signals to manage contexts mainly focusing on resetting variables and cleaning up states */
3312 void CSCLController::handle_engine_signal( SclInternalSignal signal, sclwindow targetWindow )
3317 SIGACTION_RESIZE_RESOURCES,
3318 SIGACTION_DESTROY_TIMERS,
3319 SIGACTION_CLEAR_PRIVATEKEYS,
3320 SIGACTION_RECOMPUTE_LAYOUT,
3321 SIGACTION_FREE_IMAGES,
3322 SIGACTION_CLOSE_POPUP,
3323 SIGACTION_CLOSE_MAGNIFIER,
3324 SIGACTION_UNSET_SHIFT,
3325 SIGACTION_UNPRESS_KEYS,
3326 SIGACTION_INIT_DISPLAY,
3327 SIGACTION_INIT_INPUTMODE,
3331 const sclboolean SIGNAL_TABLE[SIGACTION_MAXNUM][SCL_SIG_MAXNUM] = {
3332 // START, SHOW, HIDE, INPCHNG, DISPCHNG, POPUPSHOW, POPUPHIDE, MOUSEPRES, M-LONGPRES, MOUSEREL, KEYEVT, FOCUSCHNG
3333 // SIGACTION_RESIZE_RESOURCES
3334 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3335 // SIGACTION_DESTROY_TIMERS
3336 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3337 // SIGACTION_CLEAR_PRIVATEKEYS
3338 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TRUE },
3339 // SIGACTION_RECOMPUTE_LAYOUT
3340 { 0, TRUE, 0, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
3341 // SIGACTION_FREE_IMAGES
3342 { TRUE, 0, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0 },
3343 // SIGACTION_CLOSE_POPUP
3344 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3345 // SIGACTION_CLOSE_MAGNIFIER
3346 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3347 // SIGACTION_UNSET_SHIFT
3348 { TRUE, 0 , 0 , TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE },
3349 // SIGACTION_UNPRESS_KEYS
3350 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3351 // SIGACTION_INIT_DISPLAY
3352 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3353 // SIGACTION_INIT_INPUTMODE
3354 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TRUE },
3357 scl_assert_return(signal >= 0 && signal < SCL_SIG_MAXNUM);
3359 CSCLEvents* events = CSCLEvents::get_instance();
3360 CSCLWindows *windows = CSCLWindows::get_instance();
3361 CSCLContext *context = CSCLContext::get_instance();
3362 CSCLImageProxy *proxy = CSCLImageProxy::get_instance();
3363 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3368 context->set_hidden_state(FALSE);
3373 context->set_hidden_state(TRUE);
3374 windows->close_all_popups();
3380 for (loop = 0;loop < SIGACTION_MAXNUM;loop++) {
3381 if (SIGNAL_TABLE[loop][signal] == TRUE) {
3383 case SIGACTION_RESIZE_RESOURCES:
3385 case SIGACTION_DESTROY_TIMERS:
3386 events->destroy_all_timer();
3388 case SIGACTION_CLEAR_PRIVATEKEYS:
3390 case SIGACTION_RECOMPUTE_LAYOUT: {
3391 if (targetWindow != SCLWINDOW_INVALID) {
3392 cache->recompute_layout(targetWindow);
3394 windows->update_window(targetWindow);
3398 case SIGACTION_FREE_IMAGES:
3399 proxy->free_images();
3401 case SIGACTION_CLOSE_POPUP: {
3402 /* If there is a popup still opened, don't destroy POPUP_TIMEOUT timer */
3403 if (!(windows->close_all_popups(targetWindow))) {
3404 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
3408 case SIGACTION_CLOSE_MAGNIFIER: {
3409 /* FIXME : Temporary way of clearing magnifier window */
3410 CSCLGraphics *graphics = CSCLGraphics::get_instance();
3411 CSCLUtils *utils = CSCLUtils::get_instance();
3412 sclchar composed_path[_POSIX_PATH_MAX] = {0,};
3413 scldrawctx draw_ctx = graphics->begin_paint(windows->get_magnifier_window());
3414 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3415 PSclMagnifierWndConfigure magnifier_configure = NULL;
3416 if (sclres_manager) {
3417 magnifier_configure = sclres_manager->get_magnifier_configure();
3419 if (magnifier_configure) {
3420 utils->get_composed_path(composed_path, IMG_PATH_PREFIX, magnifier_configure->bg_image_path);
3421 graphics->draw_image(windows->get_magnifier_window(), draw_ctx, composed_path, 0, 0);
3422 graphics->end_paint(windows->get_magnifier_window(), draw_ctx);
3426 if (signal == SCL_SIG_HIDE) {
3427 windows->hide_window(windows->get_magnifier_window(), TRUE);
3429 windows->hide_window(windows->get_magnifier_window());
3431 //events->create_timer(SCL_TIMER_BUTTON_DELAY, SCL_BUTTON_MIN_DURATION, 0);
3433 case SIGACTION_UNSET_SHIFT: {
3434 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3436 if (SCL_EVENT_PASS_ON ==
3437 handler->on_event_notification(SCL_UINOTITYPE_SHIFT_STATE_CHANGE, SCL_SHIFT_STATE_OFF)) {
3438 context->set_shift_state(SCL_SHIFT_STATE_OFF);
3443 case SIGACTION_UNPRESS_KEYS:
3444 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3445 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3447 case SIGACTION_INIT_DISPLAY:
3449 case SIGACTION_INIT_INPUTMODE:
3457 * Sets the duration value for longkey
3458 * If not set, it will use default longkey duration. see sclconfig
3461 CSCLController::set_longkey_duration(scllong msc)
3464 sclboolean ret = FALSE;
3466 m_long_key_duration = msc;
3473 * Sets the distance value for cancel longkey
3474 * If not set, it will use default longkey duration. see sclconfig
3477 CSCLController::set_longkey_cancel_dist(sclshort dist)
3480 sclboolean ret = FALSE;
3482 m_long_key_cancel_distance = dist;
3489 * Sets the duration value for repeatkey
3490 * If not set, it will use default repeatkey duration. see sclconfig
3493 CSCLController::set_repeatkey_duration(scllong msc)
3496 sclboolean ret = FALSE;
3498 m_repeat_key_duration = msc;
3505 * Sets the duration value for autopopup key
3506 * If not set, it will use default short longkey duration. see sclconfig
3509 CSCLController::set_autopopup_key_duration(scllong msc)
3512 sclboolean ret = FALSE;
3514 m_autopopup_key_duration = msc;
3521 * Sets the amount value for button delay
3522 * If not set, it will use default button delay amount. see sclconfig
3525 CSCLController::set_button_delay_duration(scllong msc)
3528 sclboolean ret = FALSE;
3530 m_button_delay_duration = msc;
3537 * Configures the variables for auto-popup window
3538 * It will return rectangle area
3539 * @return FALSE It's not avaiable popup key
3542 CSCLController::configure_autopopup_window(sclwindow window, sclbyte key_index, SclRectangle* rect)
3545 scl_assert_return_false(window);
3546 scl_assert_return_false(key_index >= 0);
3548 sclboolean ret = TRUE;
3550 sclbyte num_keys, num_columns, num_rows;
3552 CSCLUtils *utils = CSCLUtils::get_instance();
3553 CSCLContext *context = CSCLContext::get_instance();
3554 CSCLWindows *windows = CSCLWindows::get_instance();
3555 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3557 const SclLayoutKeyCoordinate *coordinate = NULL;
3560 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3563 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3564 PSclAutoPopupConfigure autopopup_configure = NULL;
3565 if (sclres_manager) {
3566 autopopup_configure = sclres_manager->get_autopopup_configure();
3569 if (utils && context && windows && cache && coordinate && rect && autopopup_configure) {
3570 SCLShiftState shiftidx = context->get_shift_state();
3571 if (shiftidx < 0 || shiftidx >= SCL_SHIFT_STATE_MAX) shiftidx = SCL_SHIFT_STATE_OFF;
3572 if (utils->get_autopopup_window_variables(coordinate->autopopup_key_labels[shiftidx],
3573 &num_keys, &num_columns, &num_rows, &rect->width, &rect->height)) {
3575 /* There is no need for an autopopup window if number of keys are equal to or less than 0 */
3576 if (!(num_keys > 0)) {
3579 /* calculates y position to be set */
3580 SclRectangle baseWndRect;
3581 int scrwidth, scrheight;
3582 utils->get_screen_resolution(&scrwidth, &scrheight);
3584 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
3585 /* Let the autopopup have its position right above the pressed button, with center alignment) */
3586 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) - (rect->width / 2);
3587 rect->y = baseWndRect.y + coordinate->y - rect->height + autopopup_configure->decoration_size;
3588 /* First check the growing direction of this autopopup window */
3589 if (coordinate->x < baseWndRect.width / 2) {
3590 /* We're growing left to right, caculate the left start point */
3591 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) -
3592 (autopopup_configure->button_width / 2) - autopopup_configure->bg_padding;
3593 if (rect->x + rect->width > baseWndRect.x + baseWndRect.width) {
3594 sclint relocate_unit = autopopup_configure->button_width +
3595 autopopup_configure->button_spacing;
3596 rect->x -= (((rect->x + rect->width - (baseWndRect.x + baseWndRect.width)) /
3597 relocate_unit) + 1) * relocate_unit;
3600 /* We're growing right to left, caculate the right end point */
3601 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) +
3602 (autopopup_configure->button_width / 2) + autopopup_configure->bg_padding;
3603 rect->x -= rect->width;
3604 if (rect->x < baseWndRect.x) {
3605 sclint relocate_unit = autopopup_configure->button_width +
3606 autopopup_configure->button_spacing;
3607 rect->x += (((baseWndRect.x - rect->x) /
3608 relocate_unit) + 1) * relocate_unit;
3611 //rect->y = (scrheight - layout->height) + coordinate->y - rect->height + autopopup_configure->decoration_size;
3612 /* Check if the window goes out of screen boundary */
3613 //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;
3614 if (rect->x + rect->width > scrwidth) rect->x = (scrwidth) - rect->width;
3615 if (rect->y + rect->height > scrheight) rect->y = scrheight - rect->height;
3616 if (rect->x < 0 - autopopup_configure->decoration_size) rect->x = 0 - autopopup_configure->decoration_size;
3618 if (rect->x < 0) rect->x = 0;
3619 if (rect->y < 0) rect->y = 0;
3628 * If the mouse was pressed on the button A and moved to B without releasing,
3629 * this function decides whether we should allow event transition, meaning
3630 * button A gets restored to its initial state and B gets pressed instead.
3633 CSCLController::check_event_transition_enabled(const SclLayoutKeyCoordinate *btnFrom, const SclLayoutKeyCoordinate *btnTo)
3635 sclboolean ret = FALSE;
3636 sclbyte typeFrom = BUTTON_TYPE_NORMAL; /* To enable event transition even if no button is pressed currently */
3637 sclbyte typeTo = MAX_BUTTON_TYPE;
3639 const sclboolean TRANSITION_TABLE[MAX_BUTTON_TYPE][MAX_BUTTON_TYPE] = {
3640 // NORMAL GRAB SELFISH DRAG MULTITAP ROTATION DIRECTION R_DIRECTION UIITEM
3642 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, 0},
3644 { 0, 0, 0, 0, 0, 0, 0, 0, 0},
3646 { 0, 0, 0, 0, 0, 0, 0, 0, 0},
3648 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, 0},
3650 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, 0},
3652 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, 0},
3654 { 0, 0, 0, 0, 0, 0, 0, 0, 0},
3655 // From : R_DIRECTION
3656 { 0, 0, 0, 0, 0, 0, 0, 0, 0},
3658 { 0, 0, 0, 0, 0, 0, 0, 0, 0},
3661 if (btnFrom) typeFrom = btnFrom->button_type;
3662 if (btnTo) typeTo = btnTo->button_type;
3664 scl_assert_return_false(typeFrom >= 0 && typeFrom < MAX_BUTTON_TYPE);
3665 scl_assert_return_false(typeTo >= 0 && typeTo < MAX_BUTTON_TYPE);
3667 if (typeFrom < MAX_BUTTON_TYPE && typeTo < MAX_BUTTON_TYPE) {
3668 ret = TRANSITION_TABLE[typeFrom][typeTo];
3675 CSCLController::get_debug_mode()
3678 return m_debug_mode;
3680 return m_debug_mode;
3681 return DEBUGMODE_DISABLED;
3686 CSCLController::set_debug_mode(SCLDebugMode mode)
3688 CSCLEvents *events = CSCLEvents::get_instance();
3689 CSCLUtils *utils = CSCLUtils::get_instance();
3691 m_debug_mode = mode;
3692 m_debug_variable = 0;
3694 if (m_debug_mode == DEBUGMODE_AUTOTEST) {
3696 if (events && utils) {
3697 events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INITIAL_INTERVAL, 0, FALSE);
3698 utils->log("mode : %d\n", mode);
3704 CSCLController::disable_input_events(sclboolean disabled)
3706 m_input_events_disabled = disabled;