2 * Copyright (c) 2012 - 2014 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
23 #include "sclcontroller.h"
25 #include "sclresourcecache.h"
26 #include "sclactionstate.h"
27 #include "scluibuilder.h"
28 #include "sclkeydefines.h"
29 #include "sclfeedback.h"
30 #include "sclerroradjustment.h"
31 #include "sclimageproxy.h"
32 #include "sclres_manager.h"
33 #include "scleventhandler.h"
34 #include "sclanimator.h"
35 #include "sclkeyfocushandler.h"
38 //#define DIRECTLY_DRAW_ON_EVENTS
43 _play_tts_for_input_mode_name(int mode) {
46 CSCLContext *context = CSCLContext::get_instance();
47 if (context && context->get_tts_enabled() == FALSE) {
51 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
52 if (!sclres_manager) return FALSE;
54 const SclInputModeConfigure *pinput_mode_table = sclres_manager->get_input_mode_configure_table();
55 if (NULL == pinput_mode_table) {
59 const char* name = pinput_mode_table[mode].name;
64 CSCLUtils *utils = CSCLUtils::get_instance();
66 utils->play_tts(name);
71 _play_tts_for_layout_autopopup_name() {
74 CSCLContext *context = CSCLContext::get_instance();
75 if (context && context->get_tts_enabled() == FALSE) {
79 CSCLUtils *utils = CSCLUtils::get_instance();
81 utils->play_tts(SCL_LAYOUT_AUTOPOPUP_NAME);
85 CSCLController::CSCLController()
89 m_long_key_duration = SCL_LONGKEY_DURATION;
90 m_long_key_cancel_distance = SCL_LONGKEY_CANCEL_DIST;
91 m_repeat_key_duration = SCL_REPEATKEY_DURATION;
92 m_autopopup_key_duration = SCL_AUTOPOPUP_KEY_DURATION;
94 m_button_delay_duration = SCL_BUTTON_MIN_DURATION;
95 m_multitap_delay_duration = SCL_MULTITAP_DEFAULT_DURATION;
97 m_key_repeated_num = 0;
99 m_debug_mode = DEBUGMODE_DISABLED;
100 m_debug_variable = 0;
102 m_input_events_disabled = FALSE;
105 CSCLController::~CSCLController()
111 CSCLController::get_instance()
113 static CSCLController instance;
118 CSCLController::init()
123 //#define TEST_NEWBACKEND
124 #ifdef TEST_NEWBACKEND
125 #include <Ecore_Evas.h>
131 EFLOBJECT_CLIPOBJECT,
137 SclRectangle position;
140 sclboolean extracted;
143 #include <Ecore_Evas.h>
149 Evas_Object *clipper;
152 sclchar image_path[_POSIX_PATH_MAX];
162 sclboolean extrace_image;
171 scl::SclFontInfo font_info;
173 sclchar str[_POSIX_PATH_MAX];;
179 SCLLabelAlignment align;
183 sclbyte inner_height;
186 extern std::vector<ImageCache> g_ImageCache;
187 extern std::vector<TextCache> g_TextCache;
192 * Sets the current input mode to the given mode
195 CSCLController::process_input_mode_change(const sclbyte mode)
199 sclboolean ret = FALSE;
201 CSCLUtils *utils = CSCLUtils::get_instance();
202 CSCLContext *context = CSCLContext::get_instance();
203 CSCLWindows *windows = CSCLWindows::get_instance();
204 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
205 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
207 if (!utils || !context || !windows || !cache || !sclres_manager) return FALSE;
209 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
210 if (!sclres_input_mode_configure) return FALSE;
212 if (context && windows && cache && utils) {
213 if (mode == context->get_input_mode() || mode == (sclbyte)NOT_USED) {
214 /* ButtonContext does not get initialized if we don't call here */
215 cache->recompute_layout(windows->get_base_window());
219 context->set_input_mode(mode);
220 /* FIXME : NEWXML temporary commenting out */
221 //context->set_base_layout(sclres_input_mode_configure[mode].layouts[context->get_display()]);
223 _play_tts_for_input_mode_name(mode);
225 sclwindow window = windows->get_base_window();
226 handle_engine_signal(SCL_SIG_INPMODE_CHANGE, window);
228 #ifdef TEST_NEWBACKEND
229 SclWindowContext *window_context = windows->get_window_context(window, FALSE);
230 if (window_context) {
231 if (window_context->etc_info) {
232 Eina_List *list = (Eina_List*)(window_context->etc_info);
233 Eina_List *iter = NULL;
234 Eina_List *iter_next = NULL;
238 EINA_LIST_FOREACH_SAFE(list, iter, iter_next, data) {
240 EFLObject *object = (EFLObject*)(data);
242 Evas_Object* eo = object->object;
243 if (object->extracted) {
244 void *data = evas_object_image_data_get(eo, 1);
251 for (loop = 0;loop < (sclint)g_ImageCache.size();loop++) {
252 if (g_ImageCache[loop].image == object->object) {
253 g_ImageCache[loop].used = FALSE;
256 for (loop = 0;loop < (sclint)g_TextCache.size();loop++) {
257 if (g_TextCache[loop].text == object->object) {
258 g_TextCache[loop].used = FALSE;
264 object->object = NULL;
268 list = eina_list_remove_list(list, iter);
272 window_context->etc_info = list;
282 * Sets the current display mode to the given mode
285 CSCLController::process_rotation_change(const SCLRotation rotation)
288 CSCLContext *context = CSCLContext::get_instance();
289 CSCLWindows *windows = CSCLWindows::get_instance();
290 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
292 if (!sclres_manager) return FALSE;
294 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
295 if (!sclres_input_mode_configure) return FALSE;
297 if (context && windows) {
299 if (rotation == ROTATION_90_CW || rotation == ROTATION_90_CCW) {
300 mode = DISPLAYMODE_LANDSCAPE;
302 mode = DISPLAYMODE_PORTRAIT;
305 if (mode == context->get_display_mode()) return FALSE;
307 context->set_display_mode(mode);
308 context->set_rotation(rotation);
309 /* FIXME : NEWXML temporary commenting out */
310 //context->set_base_layout(sclres_input_mode_configure[context->get_input_mode()].layouts[context->get_display()]);
312 sclwindow window = windows->get_base_window();
313 handle_engine_signal(SCL_SIG_DISP_CHANGE, window);
314 windows->update_window(window);
316 /* Moved to here since the new WMSync requires the rotation call be invoked as the
317 last step of display change process */
318 /* Make sure to set window's rotation degree before sending engine signal, which adjusts the size of main window */
319 windows->set_window_rotation(NULL, rotation);
325 * Checks if the given button with given touch_id needs magnifier window
328 CSCLController::check_magnifier_available(sclwindow window, sclbyte key_index, scltouchdevice touch_id)
330 sclboolean ret = FALSE;
332 CSCLContext *context = CSCLContext::get_instance();
333 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
334 const SclLayout *layout = NULL;
335 SclButtonContext *button_context = NULL;
336 const SclLayoutKeyCoordinate *coordinate = NULL;
338 if (context && cache) {
339 layout = cache->get_cur_layout(window);
340 button_context = cache->get_cur_button_context(window, key_index);
341 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
343 SCLShiftState shift_index = context->get_shift_state();
344 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
345 if (context->get_caps_lock_mode()) {
346 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
349 if (layout && coordinate && button_context && context->get_magnifier_enabled()) {
350 if (coordinate->key_type != KEY_TYPE_CONTROL &&
351 coordinate->key_type != KEY_TYPE_MODECHANGE &&
352 coordinate->key_type != KEY_TYPE_NONE) {
355 /* Do not show if current layout does not allow magnifier */
356 if (!(layout->use_magnifier_window)) {
357 //utils->log("show_magnifier !(layout->use_magnifier_window \n");
361 /* Do not show if there's nothing to show */
362 const sclchar* custom_label = NULL;
363 for (sclint label_index = 0;label_index < MAX_SIZE_OF_LABEL_FOR_ONE && !custom_label;label_index++) {
364 const sclchar *temp_label = context->get_custom_magnifier_label(touch_id, label_index);
366 custom_label = temp_label;
370 //if (coordinate->key_value[shift_index][button_context->multikeyIdx] == NULL) {
371 if (coordinate->label[shift_index][button_context->multitap_index] == NULL) {
372 //utils->log("show_magnifier coordinate->key_value[shift][button_context->multikeyIdx] == NULL \n");
374 //} else if (strlen(coordinate->key_value[shift_index][button_context->multikeyIdx]) == 0) {
375 } else if (strlen(coordinate->label[shift_index][button_context->multitap_index]) == 0) {
376 //utils->log("show_magnifier coordinate->key_value[shift][button_context->multikeyIdx]) == 0 \n");
381 if (touch_id != context->get_last_touch_device_id()) {
392 CSCLController::process_button_pressed_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
393 scltouchdevice touch_id, sclboolean actual_event)
397 sclboolean ret = FALSE;
398 sclboolean redraw = FALSE;
400 CSCLContext *context = CSCLContext::get_instance();
401 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
402 CSCLWindows *windows = CSCLWindows::get_instance();
403 CSCLEvents *events = CSCLEvents::get_instance();
404 CSCLUtils *utils = CSCLUtils::get_instance();
405 CSCLFeedback *feedback = CSCLFeedback::get_instance();
406 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
407 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
409 if (!sclres_manager) return FALSE;
411 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
412 PSclLayout sclres_layout = sclres_manager->get_layout_table();
413 if (!sclres_input_mode_configure || !sclres_layout) return FALSE;
415 SclButtonContext *button_context = NULL;
416 const SclLayoutKeyCoordinate *coordinate = NULL;
418 if (context && cache) {
419 button_context = cache->get_cur_button_context(window, key_index);
420 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
423 if (context && cache && windows && events && utils && feedback && handler && button_context && coordinate) {
424 /* First check if this button is enabled in current active sublayout */
425 sclboolean sub_layout_match = TRUE;
426 if (coordinate->sub_layout && context->get_cur_sublayout()) {
427 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
428 sub_layout_match = FALSE;
432 /* If this button is pressed */
433 if ( x >= coordinate->x - coordinate->add_hit_left &&
434 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
435 y >= coordinate->y - coordinate->add_hit_top &&
436 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
437 /* Process the event only if the this item's sublayout id is active one */
439 /* If currently shift mode is ON, and the last key was multitap, this means the shift did not
440 turned off because of multitap button. So we need to turn it off here forcibly */
441 sclwindow last_win = context->get_last_event_fired_window();
442 scl8 last_key = context->get_last_event_fired_key();
443 LOGD("last_win : %p last_key : :%d", last_win, last_key);
444 const SclLayoutKeyCoordinate *last_coordinate = cache->get_cur_layout_key_coordinate(last_win, last_key);
445 if (last_coordinate) {
446 LOGD("last_coordinate->button_type : %d", last_coordinate->button_type);
447 if (last_coordinate->button_type == BUTTON_TYPE_MULTITAP && context->get_shift_state() == SCL_SHIFT_STATE_ON) {
448 /* And if the multitap button was different from the one we are dealing with... */
449 LOGD("last_win %p window %p last_key %d key_index %d", last_win, window, last_key, key_index);
450 if (last_win != window || last_key != key_index) {
451 SclNotiShiftStateChangeDesc desc;
452 desc.ui_event_desc = NULL;
453 desc.shift_state = SCL_SHIFT_STATE_OFF;
455 SCLEventReturnType ret = handler->on_event_notification(SCL_UINOTITYPE_SHIFT_STATE_CHANGE, &desc);
456 if (ret == SCL_EVENT_PASS_ON) {
457 context->set_shift_state(SCL_SHIFT_STATE_OFF);
458 windows->update_window(windows->get_base_window());
464 /* If newly pressed key has type MULTI_TOUCH_TYPE_EXCLUSIVE, release all existing pressed events */
466 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_EXCLUSIVE) {
467 /* When calling mouse_release, the seq order of current multitouch events will be changed,
468 so we put all the multitouch events into a vector and use them afterwards forreleasing */
470 sclint multi_touch_context_num = context->get_multi_touch_context_num();
471 std::vector<SclUIEventDesc> multi_touch_events;
472 for (loop = 0;loop < multi_touch_context_num;loop++) {
474 context->get_multi_touch_event(loop, &desc);
475 multi_touch_events.push_back(desc);
477 for (loop = 0;loop < multi_touch_context_num;loop++) {
478 SclUIEventDesc desc = multi_touch_events[loop];
479 if (desc.touch_id != touch_id) {
480 mouse_release(context->get_cur_moving_window(desc.touch_id),
481 context->get_cur_moving_point(desc.touch_id).x,
482 context->get_cur_moving_point(desc.touch_id).y,
483 desc.touch_id, FALSE);
489 /* Make an unique ID for timer */
490 const scl16 uniqId = utils->get_unique_id();
492 context->set_cur_pressed_event_id(touch_id, uniqId);
493 context->set_cur_pressed_key(touch_id, key_index);
494 context->set_cur_pressed_window(touch_id, window);
496 button_context->state = BUTTON_STATE_PRESSED;
498 if (context->get_highlight_ui_enabled()) {
499 CSCLKeyFocusHandler* focus_handler = CSCLKeyFocusHandler::get_instance();
501 sclwindow prev_window = focus_handler->get_current_focus_window();
502 scl8 prev_key = focus_handler->get_current_focus_key();
503 const SclLayoutKeyCoordinate *prev_coordinate =
504 cache->get_cur_layout_key_coordinate(prev_window, prev_key);
506 focus_handler->set_current_focus(window, key_index);
508 if (prev_coordinate) {
509 windows->update_window(prev_window,
510 prev_coordinate->x, prev_coordinate->y, prev_coordinate->width, prev_coordinate->height);
518 #ifndef DIRECTLY_DRAW_ON_EVENTS
519 /* If the window doesn't get exposed before corresponding release event,
520 * the inverted state of a button will never be drawn onto screen.
521 * To prevent such a case, we draw the inverted state of button forcefully and directly,
522 * without waiting for expose event */
523 /*CSCLGraphics *grps = CSCLGraphics::get_instance();
524 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
525 scldrawctx draw_ctx = grps->begin_paint(window, TRUE);
526 builder->draw_button(window, draw_ctx, key_index, button_context->state, TRUE);
527 grps->end_paint(window, draw_ctx);*/
531 feedback->button_pressed(window, key_index);
533 /* Special routine for autopopup */
534 if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
535 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
537 /* for long key & repeat key */
538 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
541 SCLShiftState shift_index = context->get_shift_state();
542 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
543 if (context->get_caps_lock_mode()) {
544 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
547 SclUIEventDesc key_event_desc;
548 key_event_desc.key_value = coordinate->key_value[shift_index][0];
549 key_event_desc.key_event = coordinate->key_event[shift_index][0];
550 key_event_desc.key_type = coordinate->key_type;
551 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
552 key_event_desc.event_type = EVENT_TYPE_PRESS;
554 SclPoint curpoint = {x, y};
555 key_event_desc.touch_id = touch_id;
556 key_event_desc.mouse_pressed_point = curpoint;
557 key_event_desc.mouse_current_point = curpoint;
558 key_event_desc.mouse_farthest_point = curpoint;
560 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
562 SCLEventReturnType processed = handler->on_event_drag_state_changed(key_event_desc);
564 /* Only if the handler didn't return SCL_EVENT_DONE */
565 if (processed == SCL_EVENT_PASS_ON) {
566 /* Now process normal behaviours of each button type */
567 switch (coordinate->button_type) {
568 case BUTTON_TYPE_NORMAL:
569 case BUTTON_TYPE_GRAB:
570 case BUTTON_TYPE_SELFISH:
571 case BUTTON_TYPE_DIRECTION:
572 case BUTTON_TYPE_RELATIVE_DIRECTION: {
573 /* Send click event right away if this button uses repeat key */
574 if (coordinate->use_repeat_key) {
575 handler->on_event_key_clicked(key_event_desc);
579 case BUTTON_TYPE_MULTITAP: {
582 case BUTTON_TYPE_ROTATION: {
585 case BUTTON_TYPE_DRAG: {
586 /* Drag buttons fires click event immediately when they are pressed */
587 handler->on_event_key_clicked(key_event_desc);
590 case BUTTON_TYPE_UIITEM: break;
591 case MAX_BUTTON_TYPE: break;
594 switch (coordinate->popup_type) {
595 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: {
596 SclNotiPopupOpeningDesc desc;
597 desc.ui_event_desc = &key_event_desc;
598 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
599 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
600 sclint popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
601 SCLDisplayMode display_mode = context->get_display_mode();
603 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
604 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
605 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
606 sclshort popupLayoutId =
607 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
608 SclRectangle popupRect;
609 SclRectangle baseWndRect;
610 SclLayout *layout = NULL;
612 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
613 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
614 layout = &sclres_layout[popupLayoutId];
617 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
618 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
619 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
620 //popupRect.width = utils->get_scale_x(layout->width);
621 //popupRect.height= utils->get_scale_y(layout->height);
622 if (!(sclres_manager->loaded(popupLayoutId))) {
623 sclres_manager->load(popupLayoutId);
625 popupRect.width = layout->width;
626 popupRect.height = layout->height;
627 windows->close_all_popups();
629 SclWindowOpener opener;
630 opener.window = window;
631 opener.key = key_index;
633 sclwindow popup_window = windows->open_popup(opener,
637 coordinate->popup_type,
638 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
639 sclres_input_mode_configure[popup_input_mode].use_dim_window,
640 coordinate->extract_offset_x,
641 coordinate->extract_offset_y,
642 sclres_input_mode_configure[popup_input_mode].timeout);
644 SclNotiPopupOpenedDesc opened_desc;
645 opened_desc.ui_event_desc = &key_event_desc;
646 opened_desc.input_mode = desc.input_mode;
647 opened_desc.window = popup_window;
648 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
650 windows->hide_window(windows->get_magnifier_window());
651 /* FIXME : The parent key should be turned back to NORMAL state when RELEASED,
652 in case of POPUP_TYPE_BTN_PRESS_POPUP_DRAG type. Temporarily setting NORMAL here. */
653 button_context->state = BUTTON_STATE_NORMAL;
654 _play_tts_for_input_mode_name(popup_input_mode);
660 case POPUP_TYPE_BTN_RELEASE_POPUP:
661 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
662 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
663 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
664 case POPUP_TYPE_AUTO_POPUP:
665 case POPUP_TYPE_NONE:
668 /* Nothing to do in here */
673 /* Shows the magnifier window(the magnifier window will display when a kind of button type is character) */
674 //if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
675 if (coordinate->use_magnifier) {
676 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
678 PSclMagnifierWndConfigure magnifier_configure = NULL;
679 if (sclres_manager) {
680 magnifier_configure = sclres_manager->get_magnifier_configure();
682 if (showMagnifier && magnifier_configure) {
683 SclPoint pos = {0, 0};
684 /* calculates x position to be set */
685 pos.x = (coordinate->x + (coordinate->width / 2)) -
686 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
688 /* calculates y position to be set */
689 sclint scnWidth, scnHeight;
690 utils->get_screen_resolution(&scnWidth, &scnHeight);
692 pos.y = coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
694 /* FIXME : Temporary way of clearing magnifier window */
695 /*SclWindowContext *window_context = windows->get_window_context(windows->get_magnifier_window(), FALSE);
696 sclboolean clearmagwin = FALSE;
697 if (window_context) {
698 clearmagwin = !(window_context->hidden);
700 static int clearnum = 0;
701 if (key_index == prevkey && window == prevwin) {
705 if (++clearnum > 1) {
713 CSCLGraphics *graphics = CSCLGraphics::get_instance();
714 CSCLUtils *utils = CSCLUtils::get_instance();
715 sclchar composed_path[_POSIX_PATH_MAX] = {0,};
716 scldrawctx draw_ctx = graphics->begin_paint(windows->get_magnifier_window());
717 utils->get_composed_path(composed_path, scl_magnifier_configure.bg_image_path);
718 graphics->draw_image(windows->get_magnifier_window(), draw_ctx, composed_path, 0, 0);
719 graphics->end_paint(windows->get_magnifier_window(), draw_ctx);
722 windows->hide_window(windows->get_magnifier_window());
724 SclWindowContext *window_context = windows->get_window_context(window);
725 if (window_context) {
726 pos.x += window_context->geometry.x;
727 pos.y += window_context->geometry.y;
730 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
731 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
733 if (pos.x > scnWidth +
734 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
735 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
736 pos.x = scnWidth + magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
737 magnifier_configure->width * utils->get_custom_scale_rate_x();
739 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
740 pos.x += coordinate->magnifier_offset_x;
741 pos.y += coordinate->magnifier_offset_y;
742 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y, WINDOW_MAGNIFIER);
743 //windows->resize_window(windows->get_magnifier_window(), utils->get_scale_x(scl_magnifier_configure.width), utils->get_scale_y(scl_magnifier_configure.height));
744 /*If we use transient_for them the ISE will occur some crash. It needs to check X11 */
745 /*windows->set_parent(windows->get_base_window(), windows->get_magnifier_window());*/
747 windows->show_window(windows->get_magnifier_window(), TRUE);
748 //windows->update_window(windows->get_magnifier_window());
751 static int fFirst = true;
753 windows->show_window(windows->get_magnifier_window());
756 windows->update_window(windows->get_magnifier_window());
759 /* We cannot use move_resize_window. It had occured some wrong behavior */
760 /*windows->move_resize_window(windows->get_magnifier_window(), pos.x, pos.y, scl_magnifier_configure.width, scl_magnifier_configure.height);*/
761 if (!showMagnifier) {
762 windows->hide_window(windows->get_magnifier_window());
766 /* COMMENTED OUT FOR TESTING MULTITOUCH!! */
767 ///* In case the current button is not the given key index */
768 //if (button_context->state == BUTTON_STATE_PRESSED) {
769 // /* Even if the press event occurs outside of this button's physical area, reset its context */
770 // button_context->state = BUTTON_STATE_NORMAL;
773 /* BUTTON_TYPE_MULTITAP type button should restore its multikey index when another button is clicked */
774 if (coordinate->button_type & BUTTON_TYPE_MULTITAP) {
775 button_context->multitap_index = 0;
779 /* If there is any need for redrawing */
781 #ifdef DIRECTLY_DRAW_ON_EVENTS
782 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
784 builder->draw_button(window, NULL, key_index, button_context->state, TRUE);
788 if (context && context->get_magnifier_enabled())
789 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height, WINDOW_MAGNIFIER);
791 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height, WINDOW_KEYPAD);
801 CSCLController::process_button_long_pressed_event(sclwindow window, sclbyte key_index,
802 scltouchdevice touch_id, sclboolean actual_event)
806 sclboolean ret = FALSE;
808 CSCLContext *context = CSCLContext::get_instance();
809 CSCLWindows *windows = CSCLWindows::get_instance();
810 CSCLActionState *state = CSCLActionState::get_instance();
811 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
812 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
813 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
815 if (!sclres_manager) return FALSE;
817 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
818 PSclLayout sclres_layout = sclres_manager->get_layout_table();
820 if (!sclres_input_mode_configure || !sclres_layout) return FALSE;
822 if (context && cache && handler && windows && state) {
823 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
824 SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
826 /* Should return FALSE if this key does not have any longkey related property */
829 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
830 /* When calling mouse_release, the seq order of current multitouch events will be changed,
831 so we put all the multitouch events into a vector and use them afterwards for releasing */
832 sclboolean finished = FALSE;
834 sclint multi_touch_context_num = context->get_multi_touch_context_num();
835 std::vector<SclUIEventDesc> multitouch_events;
836 for (loop = 0;loop < multi_touch_context_num;loop++) {
838 context->get_multi_touch_event(loop, &desc);
839 multitouch_events.push_back(desc);
841 for (loop = 0;loop < multi_touch_context_num && !finished;loop++) {
842 SclUIEventDesc desc = multitouch_events[loop];
843 if (desc.touch_id != touch_id) {
844 sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
845 scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
846 const SclLayoutKeyCoordinate *cur_pressed_coordinate =
847 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
848 if (cur_pressed_coordinate) {
849 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
850 mouse_release(context->get_cur_moving_window(desc.touch_id),
851 context->get_cur_moving_point(desc.touch_id).x,
852 context->get_cur_moving_point(desc.touch_id).y,
853 desc.touch_id, FALSE);
864 /* Should return FALSE if this key does not have any longkey related property */
866 if (coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP ||
867 coordinate->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE ) {
868 SclUIEventDesc key_event_desc;
869 key_event_desc.key_type = coordinate->long_key_type;
870 if (coordinate->long_key_value == NULL && coordinate->long_key_event == 0) {
871 SCLShiftState shift_index = context->get_shift_state();
872 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
873 if (context->get_caps_lock_mode()) {
874 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
877 key_event_desc.key_value = coordinate->key_value[shift_index][0];
878 key_event_desc.key_event = coordinate->key_event[shift_index][0];
880 key_event_desc.key_value = coordinate->long_key_value;
881 key_event_desc.key_event = coordinate->long_key_event;
883 key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
885 key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
886 key_event_desc.touch_id = touch_id;
887 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
888 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
889 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
891 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
893 SCLEventReturnType processed = handler->on_event_drag_state_changed(key_event_desc);
895 /* Only if the handler didn't return SCL_EVENT_DONE */
896 if (processed == SCL_EVENT_PASS_ON) {
897 SclRectangle popupRect;
898 SclRectangle baseWndRect;
899 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
900 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
901 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
903 SclNotiPopupOpeningDesc desc;
904 desc.ui_event_desc = &key_event_desc;
905 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
906 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
907 sclint popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
908 SCLDisplayMode display_mode = context->get_display_mode();
910 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
911 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
912 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
913 SclLayout *layout = NULL;
914 sclshort popupLayoutId =
915 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
917 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
918 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
919 layout = &sclres_layout[popupLayoutId];
922 //popupRect.width = utils->get_scale_x(layout->width);
923 //popupRect.height= utils->get_scale_y(layout->height);
924 if (!(sclres_manager->loaded(popupLayoutId))) {
925 sclres_manager->load(popupLayoutId);
927 popupRect.width = layout->width;
928 popupRect.height = layout->height;
930 SclWindowOpener opener;
931 opener.window = window;
932 opener.key = key_index;
934 sclwindow popup_window = windows->open_popup(
939 coordinate->popup_type,
940 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
941 sclres_input_mode_configure[popup_input_mode].use_dim_window,
942 coordinate->extract_offset_x,
943 coordinate->extract_offset_y,
944 sclres_input_mode_configure[popup_input_mode].timeout);
946 SclNotiPopupOpenedDesc opened_desc;
947 opened_desc.ui_event_desc = &key_event_desc;
948 opened_desc.input_mode = desc.input_mode;
949 opened_desc.window = popup_window;
950 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
952 windows->hide_window(windows->get_magnifier_window());
953 _play_tts_for_input_mode_name(popup_input_mode);
959 } else if (coordinate->long_key_value) {
960 if (strlen(coordinate->long_key_value) > 0) {
961 if (windows->is_base_window(window)) {
962 state->set_cur_action_state(ACTION_STATE_BASE_LONGKEY);
964 state->set_cur_action_state(ACTION_STATE_POPUP_LONGKEY);
968 PSclMagnifierWndConfigure magnifier_configure = NULL;
969 if (sclres_manager) {
970 magnifier_configure = sclres_manager->get_magnifier_configure();
972 if (coordinate->use_long_key_magnifier && magnifier_configure) {
973 CSCLUtils *utils = CSCLUtils::get_instance();
974 SclPoint pos = {0, 0};
976 const SclLayout* layout = cache->get_cur_layout(window);
977 if (utils && layout) {
978 sclint scnWidth, scnHeight;
979 utils->get_screen_resolution(&scnWidth, &scnHeight);
981 //SclWindowContext *window_context = windows->get_window_context(window, TRUE);
982 SclWindowContext *window_context = windows->get_window_context(window);
983 if (window_context) {
984 pos.x = window_context->geometry.x + (coordinate->x + (coordinate->width / 2)) -
985 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
986 pos.y = window_context->geometry.y + coordinate->y -
987 magnifier_configure->height * utils->get_custom_scale_rate_y();
989 if (pos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
990 pos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
992 if (pos.x > scnWidth +
993 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
994 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
996 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
997 magnifier_configure->width * utils->get_custom_scale_rate_x();
999 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1000 pos.x += coordinate->magnifier_offset_x;
1001 pos.y += coordinate->magnifier_offset_y;
1002 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y, WINDOW_MAGNIFIER);
1003 windows->update_window(windows->get_magnifier_window());
1004 windows->show_window(windows->get_magnifier_window(), TRUE);
1008 SclUIEventDesc key_event_desc;
1009 key_event_desc.key_type = coordinate->long_key_type;
1010 key_event_desc.key_value = coordinate->long_key_value;
1011 key_event_desc.key_event = coordinate->long_key_event;
1012 key_event_desc.key_modifier = KEY_MODIFIER_LONGKEY;
1014 key_event_desc.event_type = EVENT_TYPE_LONGPRESS;
1015 key_event_desc.touch_id = touch_id;
1016 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1017 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1018 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1020 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1022 handler->on_event_key_clicked(key_event_desc);
1028 context->set_cur_key_modifier(touch_id, KEY_MODIFIER_LONGKEY);
1029 if (coordinate && button_context) {
1030 if (coordinate->button_type & BUTTON_TYPE_MULTITAP) {
1031 button_context->multitap_index = 0;
1036 /* Longkey processing in here */
1041 CSCLController::process_button_repeat_pressed_event(sclwindow window, sclbyte key_index,
1042 scltouchdevice touch_id, sclboolean actual_event)
1045 CSCLContext *context = CSCLContext::get_instance();
1046 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1047 CSCLWindows *windows = CSCLWindows::get_instance();
1048 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1050 if (context && cache && windows && handler) {
1051 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1053 SCLShiftState shift_index = context->get_shift_state();
1054 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1055 if (context->get_caps_lock_mode()) {
1056 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1060 switch (coordinate->button_type) {
1061 case BUTTON_TYPE_NORMAL:
1062 case BUTTON_TYPE_GRAB:
1063 case BUTTON_TYPE_SELFISH:
1064 case BUTTON_TYPE_DIRECTION:
1065 case BUTTON_TYPE_RELATIVE_DIRECTION: {
1066 /* This is for enabling backspace key in search layout*/
1067 //if (coordinate->key_type != KEY_TYPE_MODECHANGE && coordinate->key_type != KEY_TYPE_COMPOSITION) {
1068 //if (coordinate->key_type != KEY_TYPE_MODECHANGE || coordinate->key_event[0][0] == MVK_BackSpace) {
1069 if (coordinate->key_type != KEY_TYPE_MODECHANGE) {
1070 sclulong repeatKeyEvent = coordinate->key_event[shift_index][0];
1072 /* In case of Delete key, Change from Char deletion to Word deletion
1073 when the input acceleration speed is reached to Max */
1074 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1075 PSclDefaultConfigure default_configure = NULL;
1076 if (sclres_manager) {
1077 default_configure = sclres_manager->get_default_configure();
1079 if (default_configure) {
1080 if (default_configure->use_word_deletion) {
1081 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
1082 if (repeatKeyEvent == MVK_BackSpace &&
1083 interval <= SCL_REPEATKEY_WORD_DELETION_START_DURATION) {
1084 repeatKeyEvent = MVK_3270_DeleteWord;
1089 SclUIEventDesc key_event_desc;
1090 key_event_desc.key_value = coordinate->key_value[shift_index][0];
1091 key_event_desc.key_event = repeatKeyEvent;
1092 key_event_desc.key_type = coordinate->key_type;
1093 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1095 key_event_desc.event_type = EVENT_TYPE_REPEAT;
1096 key_event_desc.touch_id = touch_id;
1097 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1098 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1099 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1101 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1103 handler->on_event_key_clicked(key_event_desc);
1107 case BUTTON_TYPE_UIITEM: break;
1108 case MAX_BUTTON_TYPE: break;
1114 /* Longkey processing in here */
1119 CSCLController::process_button_move_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1120 scltouchdevice touch_id, sclboolean actual_event)
1124 sclboolean ret = FALSE;
1126 CSCLUtils *utils = CSCLUtils::get_instance();
1127 CSCLEvents *events = CSCLEvents::get_instance();
1128 CSCLContext *context = CSCLContext::get_instance();
1129 CSCLWindows *windows = CSCLWindows::get_instance();
1130 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1131 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1132 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1134 SclButtonContext *button_context = NULL;
1136 const SclLayoutKeyCoordinate *coordinate = NULL;
1139 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1140 button_context = cache->get_cur_button_context(window, key_index);
1143 if (button_context && coordinate && feedback && utils && context && handler && cache && events && windows) {
1144 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1145 sclint thresholdX = 0;
1146 sclint thresholdY = 0;
1147 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1148 thresholdX = utils->get_scaled_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1149 thresholdY = utils->get_scaled_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1152 /* First check if this button is enabled in current active sublayout */
1153 sclboolean subLayoutMatch = TRUE;
1154 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1155 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1156 subLayoutMatch = FALSE;
1159 if ( x >= coordinate->x - coordinate->add_hit_left - thresholdX &&
1160 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX&&
1161 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1162 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1166 SCLShiftState shift_index = context->get_shift_state();
1167 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1168 if (context->get_caps_lock_mode()) {
1169 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1172 const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1174 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1175 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1176 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1177 const SclLayoutKeyCoordinate *pressed_coordinate =
1178 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1180 if (pressed_context == NULL || pressed_coordinate == NULL) {
1184 if (key_index != pressed_key || window != pressed_window) {
1185 /* When the focus has moved to another button, destroy all the timers */
1186 events->destroy_all_timer();
1188 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1190 const scl16 uniqId = utils->get_unique_id();
1191 context->set_cur_pressed_event_id(touch_id, uniqId);
1192 /* Special routine for autopopup */
1193 if (coordinate->popup_type == POPUP_TYPE_AUTO_POPUP) {
1194 events->create_timer(SCL_TIMER_AUTOPOPUP, m_autopopup_key_duration, uniqId);
1196 /* for long key & repeat key */
1197 events->create_timer(SCL_TIMER_LONGKEY, m_long_key_duration, uniqId);
1200 context->set_cur_pressed_window(touch_id, window);
1201 context->set_cur_pressed_key(touch_id, key_index);
1203 sclboolean showMagnifier = check_magnifier_available(window, key_index, touch_id);
1205 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1206 PSclMagnifierWndConfigure magnifier_configure = NULL;
1207 if (sclres_manager) {
1208 magnifier_configure = sclres_manager->get_magnifier_configure();
1211 SclWindowContext *window_context = windows->get_window_context(window);
1212 if (showMagnifier && magnifier_configure && window_context) {
1213 SclPoint pos = {0, 0};
1214 /* calculates x position to be set */
1215 pos.x = window_context->geometry.x;
1216 pos.x += (coordinate->x + (coordinate->width / 2)) -
1217 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
1219 /* calculates y position to be set */
1220 pos.y = window_context->geometry.y;
1221 pos.y += coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
1223 if (pos.x < window_context->geometry.x - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
1224 pos.x = window_context->geometry.x - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
1226 if (pos.x > window_context->geometry.x + window_context->geometry.width +
1227 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1228 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
1229 pos.x = window_context->geometry.x + window_context->geometry.width +
1230 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1231 magnifier_configure->width * utils->get_custom_scale_rate_x();
1233 pos.x += coordinate->magnifier_offset_x;
1234 pos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1235 pos.y += coordinate->magnifier_offset_y;
1236 if (windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP) == windows->get_base_window()) {
1237 windows->move_window(windows->get_magnifier_window(), pos.x, pos.y, WINDOW_MAGNIFIER);
1238 windows->update_window(windows->get_magnifier_window());
1243 feedback->button_moved(window, key_index);
1245 button_context->state = BUTTON_STATE_PRESSED;
1246 if (pressed_context) {
1247 /* But, if this button should be in pressed state in other multitouch id, do not initialize it */
1248 sclboolean found = FALSE;
1249 for (sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
1250 SclUIEventDesc desc;
1251 context->get_multi_touch_event(loop, &desc);
1252 if (desc.touch_id != touch_id) {
1253 MultiTouchContext *multi_touch_context =
1254 context->find_multi_touch_context(desc.touch_id);
1255 if (multi_touch_context) {
1256 if (multi_touch_context->cur_pressed_window == pressed_window &&
1257 multi_touch_context->cur_pressed_key == pressed_key) {
1264 pressed_context->state = BUTTON_STATE_NORMAL;
1267 /* If the window doesn't get exposed before corresponding release event,
1268 * the inverted state of a button will never be drawn onto screen.
1269 * To prevent such a case, we draw the inverted state of button forcefully and directly,
1270 * without waiting for expose event */
1271 /* Redrawing pressed button does not work properly, commented out */
1273 CSCLGraphics *grps = CSCLGraphics::get_instance();
1274 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1275 scldrawctx draw_ctx;
1276 if (pressed_window != SCLWINDOW_INVALID && pressed_key != NOT_USED) {
1277 draw_ctx = grps->begin_paint(pressed_window, TRUE);
1278 builder->draw_button(pressed_window, draw_ctx, pressed_key, FALSE);
1279 grps->end_paint(pressed_window, draw_ctx);
1281 draw_ctx = grps->begin_paint(window, TRUE);
1282 builder->draw_button(window, draw_ctx, key_index, TRUE);
1283 grps->end_paint(window, draw_ctx);
1286 switch (coordinate->button_type) {
1287 case BUTTON_TYPE_DRAG: {
1288 SclUIEventDesc key_event_desc;
1289 key_event_desc.key_value = coordinate->key_value[shift_index][0];
1290 key_event_desc.key_event = coordinate->key_event[shift_index][0];
1291 key_event_desc.key_type = coordinate->key_type;
1292 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1294 key_event_desc.event_type = EVENT_TYPE_MOVE;
1295 key_event_desc.touch_id = touch_id;
1296 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1297 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1298 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1300 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1302 if (sclres_manager) {
1303 magnifier_configure = sclres_manager->get_magnifier_configure();
1305 sclboolean processed = handler->on_event_drag_state_changed(key_event_desc);
1306 if (processed && context->get_magnifier_enabled() && magnifier_configure) {
1307 SclPoint zoomwinpos = {0, 0};
1308 /* calculates x position to be set */
1309 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
1310 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
1312 /* calculates y position to be set */
1313 sclint scnWidth, scnHeight;
1314 utils->get_screen_resolution(&scnWidth, &scnHeight);
1316 zoomwinpos.y = coordinate->y -
1317 magnifier_configure->height * utils->get_custom_scale_rate_y();
1318 SclWindowContext *window_context = windows->get_window_context(window);
1319 if (window_context) {
1320 zoomwinpos.x += window_context->geometry.x;
1321 zoomwinpos.y += window_context->geometry.y;
1323 if (zoomwinpos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
1324 zoomwinpos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
1326 if (zoomwinpos.x > scnWidth +
1327 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1328 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
1329 zoomwinpos.x = scnWidth +
1330 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
1331 magnifier_configure->width * utils->get_custom_scale_rate_x();
1333 zoomwinpos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
1334 zoomwinpos.x += coordinate->magnifier_offset_x;
1335 zoomwinpos.y += coordinate->magnifier_offset_y;
1336 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y, WINDOW_MAGNIFIER);
1337 windows->show_window(windows->get_magnifier_window(), 0);
1340 handler->on_event_key_clicked(key_event_desc);
1341 if (!(windows->is_base_window(window))) {
1342 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
1343 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
1344 SclWindowContext *window_context = windows->get_window_context(window);
1345 if (window_context) {
1346 if (window_context->timeout > 0) {
1347 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
1348 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, window_context->timeout, 0, TRUE);
1354 case BUTTON_TYPE_NORMAL: break;
1355 case BUTTON_TYPE_GRAB: break;
1356 case BUTTON_TYPE_SELFISH: break;
1357 case BUTTON_TYPE_MULTITAP: break;
1358 case BUTTON_TYPE_ROTATION: break;
1359 case BUTTON_TYPE_DIRECTION: break;
1360 case BUTTON_TYPE_RELATIVE_DIRECTION: break;
1361 case BUTTON_TYPE_UIITEM: break;
1362 case MAX_BUTTON_TYPE: break;
1367 #ifdef DIRECTLY_DRAW_ON_EVENTS
1368 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
1370 if (button_context) {
1371 builder->draw_button(window, NULL, key_index, button_context->state);
1373 if (pressedContext) {
1374 builder->draw_button(pressed_window, NULL, pressed_key, pressedContext->state, TRUE);
1378 windows->update_window(window,
1379 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
1380 if (pressed_coordinate) {
1381 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1382 pressed_coordinate->width, pressed_coordinate->height);
1387 //utils->log("Now Moving : %d %d\n", pos.x, pos.y);
1389 /* If the focus went out from our SELFISH button */
1390 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH) {
1391 pressed_context->state = BUTTON_STATE_NORMAL;
1392 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1393 pressed_coordinate->width, pressed_coordinate->height);
1394 /* And if this SELFISH button was the last button pressed */
1395 if (touch_id == context->get_last_touch_device_id()) {
1396 windows->hide_window(windows->get_magnifier_window());
1401 /* If the focus came back into our SELFISH button */
1402 if (pressed_coordinate->button_type == BUTTON_TYPE_SELFISH && pressed_context->state != BUTTON_STATE_PRESSED) {
1403 pressed_context->state = BUTTON_STATE_PRESSED;
1404 windows->update_window(pressed_window, pressed_coordinate->x, pressed_coordinate->y,
1405 pressed_coordinate->width, pressed_coordinate->height);
1406 /* And if this SELFISH button was the last button pressed */
1407 if (touch_id == context->get_last_touch_device_id()) {
1408 sclboolean showMagnifier = check_magnifier_available(pressed_window, pressed_key, touch_id);
1410 if (showMagnifier) {
1411 windows->show_window(windows->get_magnifier_window());
1423 CSCLController::process_button_over_event(sclwindow window, sclint x, sclint y, sclbyte key_index)
1427 sclboolean ret = FALSE;
1429 CSCLUtils *utils = CSCLUtils::get_instance();
1430 CSCLEvents *events = CSCLEvents::get_instance();
1431 CSCLContext *context = CSCLContext::get_instance();
1432 CSCLWindows *windows = CSCLWindows::get_instance();
1433 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1434 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1436 SclButtonContext *button_context = NULL;
1438 const SclLayoutKeyCoordinate *coordinate = NULL;
1440 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1441 button_context = cache->get_cur_button_context(window, key_index);
1444 if (button_context && coordinate && feedback && utils && context && cache && events && windows) {
1445 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1446 sclboolean subLayoutMatch = TRUE;
1447 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1448 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1449 subLayoutMatch = FALSE;
1452 if ( x >= coordinate->x - coordinate->add_hit_left &&
1453 x < coordinate->x + coordinate->width + coordinate->add_hit_right &&
1454 y >= coordinate->y - coordinate->add_hit_top &&
1455 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom &&
1459 SCLShiftState shift_index = context->get_shift_state();
1460 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1461 if (context->get_caps_lock_mode()) {
1462 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1465 const SclLayout* layout = cache->get_cur_layout(windows->get_base_window());
1467 sclwindow highlighted_window = context->get_cur_highlighted_window();
1468 scl8 highlighted_key = context->get_cur_highlighted_key();
1469 SclButtonContext *cur_context = cache->get_cur_button_context(window, key_index);
1471 if (cur_context == NULL) {
1474 if (key_index != highlighted_key || window != highlighted_window) {
1475 SECURE_LOGD("%d != %d || %p != %p", key_index, highlighted_key, window, highlighted_window);
1477 if (coordinate->key_type != KEY_TYPE_NONE) {
1478 if (context->get_tts_enabled()) {
1479 const sclchar *targetstr = coordinate->hint_string[shift_index][button_context->multitap_index];
1480 if (targetstr == NULL) {
1481 targetstr = coordinate->label[shift_index][0];
1483 if (targetstr == NULL) {
1484 targetstr = coordinate->key_value[shift_index][button_context->multitap_index];
1486 /*if(state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
1487 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ) {
1488 targetstr = coordinate->long_key_value;
1490 const sclchar *sayit = cache->find_substituted_string(targetstr);
1491 utils->play_tts(sayit);
1496 context->set_cur_highlighted_window(window);
1497 context->set_cur_highlighted_key(key_index);
1505 CSCLController::get_drag_key_modifier(sclint deltax, sclint deltay, sclfloat dist, sclboolean check_farthest,
1506 scltouchdevice touch_id, sclbyte extra_option) {
1510 SCLKeyModifier modifier;
1513 CSCLContext *context = CSCLContext::get_instance();
1514 SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1517 double theta = atan2(deltay , (deltax ? deltax : 1)); /* Avoid divide by 0 exception */
1518 sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
1519 SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
1520 if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS ||
1521 extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1522 extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN) { /* 8 directions */
1523 /* If the theta is below 0, the direction is upward since the y coordinate grows downward */
1524 /* The below angle values are customized for MoAKey, need to provide customizing API */
1525 DIRECTIONINFO info[] = {
1526 {-8 * (M_PI / 8), -7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1527 {-7 * (M_PI / 8), -5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_LEFT},
1528 {-5 * (M_PI / 8), -2.7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP},
1529 {-2.7 * (M_PI / 8), -1.5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_UP_RIGHT},
1530 {-1.5 * (M_PI / 8), 1 * (M_PI / 8), KEY_MODIFIER_DIRECTION_RIGHT},
1531 { 1 * (M_PI / 8), 3 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_RIGHT},
1532 { 3 * (M_PI / 8), 5 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN},
1533 { 5 * (M_PI / 8), 7 * (M_PI / 8), KEY_MODIFIER_DIRECTION_DOWN_LEFT},
1534 { 7 * (M_PI / 8), 8 * (M_PI / 8), KEY_MODIFIER_DIRECTION_LEFT},
1536 for (size_t loop = 0; loop < sizeof(info) / sizeof(DIRECTIONINFO); loop++) {
1537 if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1538 key_modifier = info[loop].modifier;
1541 } else { /* 4 directions */
1542 /* If the state was dragging to one of 4 directions and the final release point is
1543 * far enough from inital press point, and the angle is in between out predefined angle value */
1544 if (extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE &&
1545 cur_drag_state != SCL_DRAG_STATE_NONE && cur_drag_state != SCL_DRAG_STATE_INVALID &&
1546 dist > SCL_DRAG_CURVE_RECOG_DIST &&
1547 ratio > (1 / SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) &&
1548 ratio < SCL_DRAG_CURVE_FINAL_ANGLE_VALUE) {
1549 if (cur_drag_state == SCL_DRAG_STATE_DOWN) {
1550 if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_RIGHT;
1551 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_DOWN_LEFT;
1553 if (cur_drag_state == SCL_DRAG_STATE_UP) {
1554 if (deltax > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_RIGHT;
1555 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_UP_LEFT;
1557 if (cur_drag_state == SCL_DRAG_STATE_LEFT) {
1558 if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_DOWN;
1559 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_LEFT_UP;
1561 if (cur_drag_state == SCL_DRAG_STATE_RIGHT) {
1562 if (deltay > 0) key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_DOWN;
1563 else key_modifier = KEY_MODIFIER_DIRECTION_CURVE_RIGHT_UP;
1566 DIRECTIONINFO info[] = {
1567 {-4 * (M_PI / 4), -3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1568 {-3 * (M_PI / 4), -1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_UP},
1569 {-1 * (M_PI / 4), 1 * (M_PI / 4), KEY_MODIFIER_DIRECTION_RIGHT},
1570 { 1 * (M_PI / 4), 3 * (M_PI / 4), KEY_MODIFIER_DIRECTION_DOWN},
1571 { 3 * (M_PI / 4), 4 * (M_PI / 4), KEY_MODIFIER_DIRECTION_LEFT},
1573 for (size_t loop = 0; loop < sizeof(info) / sizeof(DIRECTIONINFO); loop++) {
1574 if (theta >= info[loop].lowerbound && theta <= info[loop].upperbound) {
1575 key_modifier = info[loop].modifier;
1581 if (extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_LONG ||
1582 extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_LONG) {
1583 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1584 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1585 key_modifier = (SCLKeyModifier)(key_modifier + 8); // Add LONG attribute;
1588 if (check_farthest || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
1589 if (key_modifier >= KEY_MODIFIER_DIRECTION_LEFT &&
1590 key_modifier <= KEY_MODIFIER_DIRECTION_DOWN_RIGHT) {
1591 key_modifier = (SCLKeyModifier)(key_modifier + 16); // Add RETURN attribute;
1596 return key_modifier;
1600 CSCLController::process_button_release_event(sclwindow window, sclint x, sclint y, sclbyte key_index,
1601 scltouchdevice touch_id, sclboolean actual_event)
1605 sclboolean ret = FALSE;
1606 sclboolean redraw = FALSE;
1607 sclboolean fire_event = FALSE;
1608 SCLKeyModifier key_modifier = KEY_MODIFIER_NONE;
1610 CSCLUtils *utils = CSCLUtils::get_instance();
1611 CSCLFeedback *feedback = CSCLFeedback::get_instance();
1612 CSCLWindows *windows = CSCLWindows::get_instance();
1613 CSCLContext *context = CSCLContext::get_instance();
1614 CSCLActionState *state = CSCLActionState::get_instance();
1615 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
1616 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
1618 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
1619 if (!sclres_manager) return FALSE;
1621 PSclLayout sclres_layout = sclres_manager->get_layout_table();
1622 PSclInputModeConfigure sclres_input_mode_configure = sclres_manager->get_input_mode_configure_table();
1623 if (!sclres_layout || !sclres_input_mode_configure) return FALSE;
1625 SclButtonContext *button_context = NULL;
1626 const SclLayoutKeyCoordinate *coordinate = NULL;
1629 button_context = cache->get_cur_button_context(window, key_index);
1630 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
1633 const SclLayoutKeyCoordinate *targetCoordinate = NULL;
1635 if (utils && feedback && windows && context && state && handler && cache && button_context && coordinate) {
1636 scl8 savedInputMode = context->get_input_mode();
1638 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
1639 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
1642 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1643 /* When calling mouse_release, the seq order of current multitouch events will be changed,
1644 so we put all the multitouch events into a vector and use them afterwards for releasing */
1645 sclboolean finished = FALSE;
1647 sclint multi_touch_context_num = context->get_multi_touch_context_num();
1648 std::vector<SclUIEventDesc> multi_touch_events;
1649 for (loop = 0;loop < multi_touch_context_num;loop++) {
1650 SclUIEventDesc desc;
1651 context->get_multi_touch_event(loop, &desc);
1652 multi_touch_events.push_back(desc);
1654 for (loop = 0;loop < multi_touch_context_num && !finished;loop++) {
1655 SclUIEventDesc desc = multi_touch_events[loop];
1656 if (desc.touch_id != touch_id) {
1657 sclwindow cur_pressed_window = context->get_cur_pressed_window(desc.touch_id);
1658 scl8 cur_pressed_key = context->get_cur_pressed_key(desc.touch_id);
1659 const SclLayoutKeyCoordinate *cur_pressed_coordinate =
1660 cache->get_cur_layout_key_coordinate(cur_pressed_window, cur_pressed_key);
1661 if (cur_pressed_coordinate) {
1662 if (cur_pressed_coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
1663 mouse_release(context->get_cur_moving_window(desc.touch_id),
1664 context->get_cur_moving_point(desc.touch_id).x,
1665 context->get_cur_moving_point(desc.touch_id).y,
1666 desc.touch_id, FALSE);
1676 /* If this key is the key previously pressed, add threshold value for avoiding unintended moving */
1677 sclint thresholdX = 0;
1678 sclint thresholdY = 0;
1680 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1681 thresholdX = utils->get_scaled_x(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_X);
1682 thresholdY = utils->get_scaled_y(SCL_MOUSE_BUTTON_CHANGE_THRESHOLD_Y);
1686 /* Check if the pressed button's type is directional button */
1687 if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1689 if (context->get_cur_pressed_window(touch_id) == window && context->get_cur_pressed_key(touch_id) == key_index) {
1691 sclboolean check_farthest = FALSE;
1696 /* If the buttontype is RELATIVE_DIRECTION, get the distance from last move point */
1697 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1698 startx = context->get_prev_moving_point(touch_id).x;
1699 starty = context->get_prev_moving_point(touch_id).y;
1701 startx = context->get_cur_pressed_point(touch_id).x;
1702 starty = context->get_cur_pressed_point(touch_id).y;
1705 sclint deltax = x - startx;
1706 sclint deltay = y - starty;
1708 sclfloat dist = utils->get_distance(x, y, startx, starty);
1709 sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
1710 if (coordinate->is_side_button) {
1711 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
1713 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1714 direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
1716 if (context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN &&
1717 coordinate->button_type != BUTTON_TYPE_RELATIVE_DIRECTION) {
1718 if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
1719 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
1720 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
1721 deltax = context->get_farthest_move_point(touch_id).x - context->get_cur_pressed_point(touch_id).x;
1722 deltay = context->get_farthest_move_point(touch_id).y - context->get_cur_pressed_point(touch_id).y;
1723 dist = utils->get_distance(context->get_farthest_move_point(touch_id), context->get_cur_pressed_point(touch_id));
1724 check_farthest = TRUE;
1727 if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
1728 key_modifier = context->get_cur_key_modifier(touch_id);
1729 } else if (dist > direction_recog_dist) {
1730 key_modifier = get_drag_key_modifier(deltax, deltay, dist, check_farthest, touch_id, coordinate->extra_option);
1736 /* First check if this button is enabled in current active sublayout */
1737 sclboolean subLayoutMatch = TRUE;
1738 if (coordinate->sub_layout && context->get_cur_sublayout()) {
1739 if (strncmp(coordinate->sub_layout, context->get_cur_sublayout(), MAX_SIZE_OF_SUBLAYOUT_STRING) != 0) {
1740 subLayoutMatch = FALSE;
1743 /* Check if the event occured inside this button's rectangle */
1744 if ( x >= coordinate->x - coordinate->add_hit_left - thresholdX &&
1745 x < coordinate->x + coordinate->width + coordinate->add_hit_right + thresholdX &&
1746 y >= coordinate->y - coordinate->add_hit_top - thresholdY &&
1747 y < coordinate->y + coordinate->height + coordinate->add_hit_bottom + thresholdY &&
1754 feedback->button_released(window, key_index);
1756 /* If this button's index is the same as the one initially pressed */
1757 if (pressed_window == window && pressed_key == key_index) {
1759 targetCoordinate = coordinate;
1761 const SclLayoutKeyCoordinate *pressed_coordinate =
1762 cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
1764 if (pressed_coordinate) {
1765 if (check_event_transition_enabled(pressed_coordinate, coordinate)) {
1767 targetCoordinate = pressed_coordinate;
1775 /* In case of mode change buttons, event should be fired only when it was pressed lastly */
1777 if (coordinate->key_type == KEY_TYPE_MODECHANGE) {
1778 if (touch_id != context->get_last_touch_device_id()) {
1784 /* If this key's modifier is LONGKEY, this means the event is already fired so skip this one */
1785 if (context->get_cur_key_modifier(touch_id) == KEY_MODIFIER_LONGKEY) {
1789 /* Don't fire any events if we're in longkey state */
1790 if (state->get_cur_action_state() != ACTION_STATE_BASE_LONGKEY &&
1791 state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
1792 state->get_cur_action_state() != ACTION_STATE_POPUP_LONGKEY &&
1793 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY) {
1795 SCLShiftState shift_index = context->get_shift_state();
1796 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1797 if (context->get_caps_lock_mode()) {
1798 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1801 SclUIEventDesc key_event_desc;
1802 if (targetCoordinate) {
1803 key_event_desc.key_type = targetCoordinate->key_type;
1805 key_event_desc.key_value = targetCoordinate->key_value[shift_index][button_context->multitap_index];
1806 key_event_desc.key_event = targetCoordinate->key_event[shift_index][button_context->multitap_index];
1808 key_event_desc.key_modifier = key_modifier;
1810 key_event_desc.event_type = EVENT_TYPE_RELEASE;
1811 key_event_desc.touch_id = touch_id;
1812 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1813 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1814 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1816 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1818 if (handler->on_event_drag_state_changed(key_event_desc) != SCL_EVENT_PASS_ON) {
1823 if (targetCoordinate) {
1824 SCLShiftState shift_index = context->get_shift_state();
1825 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
1826 if (context->get_caps_lock_mode()) {
1827 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
1830 SclUIEventDesc key_event_desc;
1831 key_event_desc.key_type = targetCoordinate->key_type;
1833 key_event_desc.event_type = EVENT_TYPE_RELEASE;
1834 key_event_desc.touch_id = touch_id;
1835 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
1836 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
1837 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
1839 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
1841 switch (targetCoordinate->button_type) {
1842 case BUTTON_TYPE_NORMAL:
1843 case BUTTON_TYPE_GRAB :
1844 case BUTTON_TYPE_SELFISH:
1845 case BUTTON_TYPE_DIRECTION :
1846 case BUTTON_TYPE_RELATIVE_DIRECTION: {
1847 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1848 if (pressed_context) {
1849 if (!(targetCoordinate->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1850 key_event_desc.key_value = targetCoordinate->key_value[shift_index][0];
1851 key_event_desc.key_event = targetCoordinate->key_event[shift_index][0];
1852 key_event_desc.key_modifier = key_modifier;
1853 handler->on_event_key_clicked(key_event_desc);
1858 case BUTTON_TYPE_MULTITAP:
1859 case BUTTON_TYPE_ROTATION: {
1860 if (targetCoordinate->button_type == BUTTON_TYPE_MULTITAP) {
1861 if (window == context->get_last_event_fired_window() &&
1862 key_index == context->get_last_event_fired_key()) {
1863 key_modifier = KEY_MODIFIER_MULTITAP_REPEAT;
1865 key_modifier = KEY_MODIFIER_MULTITAP_START;
1868 key_modifier = KEY_MODIFIER_NONE;
1870 if (button_context->multitap_index < MAX_SIZE_OF_MULTITAP_CHAR) {
1871 key_event_desc.key_value = coordinate->key_value[shift_index][button_context->multitap_index];
1872 key_event_desc.key_event = coordinate->key_event[shift_index][button_context->multitap_index];
1873 key_event_desc.key_modifier = key_modifier;
1874 if (SCL_EVENT_PASS_ON == handler->on_event_key_clicked(key_event_desc)) {
1875 CSCLEvents *events = CSCLEvents::get_instance();
1876 events->destroy_timer(SCL_TIMER_MULTITAP);
1877 events->create_timer(SCL_TIMER_MULTITAP, m_multitap_delay_duration, 0);
1880 /* Check if the multikey index is in valid range, and increase by one */
1881 if (button_context->multitap_index >= MAX_SIZE_OF_MULTITAP_CHAR - 1) {
1882 button_context->multitap_index = 0;
1884 sclbyte orgindex = button_context->multitap_index;
1885 button_context->multitap_index = 0;
1886 if (targetCoordinate->key_value[shift_index][orgindex + 1]) {
1887 if (strlen(targetCoordinate->key_value[shift_index][orgindex + 1]) > 0) {
1888 button_context->multitap_index = orgindex + 1;
1894 case BUTTON_TYPE_DRAG : {
1897 case BUTTON_TYPE_TOGGLE : {
1898 SclButtonContext *pressed_context = cache->get_cur_button_context(pressed_window, pressed_key);
1899 if (pressed_context) {
1900 if (!(targetCoordinate->use_repeat_key) && pressed_context->state == BUTTON_STATE_PRESSED) {
1901 key_event_desc.key_value = targetCoordinate->key_value[shift_index][0];
1902 key_event_desc.key_event = targetCoordinate->key_event[shift_index][0];
1903 if (pressed_context->toggled) {
1904 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
1906 key_event_desc.key_modifier = KEY_MODIFIER_TOGGLED;
1908 if (SCL_EVENT_PASS_ON == handler->on_event_key_clicked(key_event_desc)) {
1909 pressed_context->toggled = !(pressed_context->toggled);
1914 case BUTTON_TYPE_UIITEM: break;
1915 case MAX_BUTTON_TYPE: break;
1918 switch (coordinate->popup_type) {
1919 case POPUP_TYPE_BTN_RELEASE_POPUP:
1920 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE: {
1921 SCLDragState dragstate = context->get_cur_drag_state(touch_id);
1922 sclint popup_input_mode = NOT_USED;
1924 SclNotiPopupOpeningDesc desc;
1925 desc.ui_event_desc = &key_event_desc;
1927 if (scl_check_arrindex(dragstate, SCL_DRAG_STATE_MAX)) {
1928 desc.input_mode = coordinate->popup_input_mode[dragstate];
1929 popup_input_mode = sclres_manager->get_inputmode_id(coordinate->popup_input_mode[dragstate]);
1931 //if (!scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP)) {
1932 if (!scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE)) {
1933 desc.input_mode = coordinate->popup_input_mode[SCL_DRAG_STATE_NONE];
1936 if (SCL_EVENT_PASS_ON == handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
1937 popup_input_mode = sclres_manager->get_inputmode_id(desc.input_mode);
1938 SCLDisplayMode display_mode = context->get_display_mode();
1940 //if (scl_check_arrindex(popup_input_mode, MAX_INPUT_MODE_POPUP) &&
1941 if (scl_check_arrindex(popup_input_mode, MAX_SCL_INPUT_MODE) &&
1942 scl_check_arrindex(display_mode, DISPLAYMODE_MAX)) {
1943 sclshort popupLayoutId =
1944 sclres_manager->get_layout_id(sclres_input_mode_configure[popup_input_mode].layouts[display_mode]);
1945 if (popupLayoutId == NOT_USED) {
1946 // deal with NOT_USED
1947 LOGD("popupLayoutID is not used.");
1949 SclLayout *layout = NULL;
1951 //if (scl_check_arrindex(popupLayoutId, MAX_LAYOUT)) {
1952 if (scl_check_arrindex(popupLayoutId, MAX_SCL_LAYOUT)) {
1953 layout = &sclres_layout[popupLayoutId];
1956 SclRectangle popupRect;
1957 SclRectangle baseWndRect;
1958 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
1959 popupRect.x = coordinate->x + coordinate->popup_relative_x + baseWndRect.x;
1960 popupRect.y = coordinate->y + coordinate->popup_relative_y + baseWndRect.y;
1962 //popupRect.width = utils->get_scale_x(layout->width);
1963 //popupRect.height= utils->get_scale_y(layout->height);
1964 if (!(sclres_manager->loaded(popupLayoutId))) {
1965 sclres_manager->load(popupLayoutId);
1967 popupRect.width = layout->width;
1968 popupRect.height = layout->height;
1970 /* Let's make sure this popup window does not go beyond the screen area */
1971 sclint scr_w, scr_h;
1972 utils->get_screen_resolution(&scr_w, &scr_h);
1974 if (popupRect.x + popupRect.width > scr_w) {
1975 popupRect.x = scr_w - popupRect.width;
1977 if (popupRect.y + popupRect.height > scr_h) {
1978 popupRect.y = scr_h - popupRect.height;
1981 SclWindowOpener opener;
1982 opener.window = window;
1983 opener.key = key_index;
1985 sclwindow popup_window = windows->open_popup(
1990 coordinate->popup_type,
1991 sclres_input_mode_configure[popup_input_mode].use_virtual_window,
1992 sclres_input_mode_configure[popup_input_mode].use_dim_window,
1993 coordinate->extract_offset_x,
1994 coordinate->extract_offset_y,
1995 sclres_input_mode_configure[popup_input_mode].timeout);
1997 SclNotiPopupOpenedDesc opened_desc;
1998 opened_desc.ui_event_desc = &key_event_desc;
1999 opened_desc.input_mode = desc.input_mode;
2000 opened_desc.window = popup_window;
2001 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
2003 windows->hide_window(windows->get_magnifier_window());
2004 _play_tts_for_input_mode_name(popup_input_mode);
2010 case POPUP_TYPE_AUTO_POPUP:
2011 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG:
2012 case POPUP_TYPE_NONE:
2013 /* Nothing to do in here */
2015 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE: break;
2016 case POPUP_TYPE_BTN_LONGPRESS_POPUP: break;
2017 case MAX_POPUP_TYPE: break;
2022 context->set_last_event_fired_window(window);
2023 context->set_last_event_fired_key(key_index);
2026 if (targetCoordinate) {
2027 SCLShiftState shift_index = context->get_shift_state();
2028 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
2029 if (context->get_caps_lock_mode()) {
2030 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
2033 SclUIEventDesc key_event_desc;
2034 key_event_desc.key_type = targetCoordinate->key_type;
2036 key_event_desc.key_value = targetCoordinate->key_value[shift_index][button_context->multitap_index];
2037 key_event_desc.key_event = targetCoordinate->key_event[shift_index][button_context->multitap_index];
2038 key_event_desc.key_modifier = key_modifier;
2040 key_event_desc.event_type = EVENT_TYPE_RELEASE;
2041 key_event_desc.touch_id = touch_id;
2042 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2043 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2044 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2046 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2048 handler->on_event_drag_state_changed(key_event_desc);
2052 /* If this button was pressed, initialize the button context regardless of event */
2053 if (button_context->state == BUTTON_STATE_PRESSED) {
2054 /* But, if this button should be in pressed state in other multitouch id, do not initialize */
2055 sclboolean found = FALSE;
2056 for (sclint loop = 0;loop < context->get_multi_touch_context_num() && !found;loop++) {
2057 SclUIEventDesc desc;
2058 context->get_multi_touch_event(loop, &desc);
2059 if (desc.touch_id != touch_id) {
2060 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(desc.touch_id);
2061 if (multi_touch_context) {
2062 if (multi_touch_context->cur_pressed_window == window &&
2063 multi_touch_context->cur_pressed_key == key_index) {
2070 button_context->state = BUTTON_STATE_NORMAL;
2075 /* If this button needs to be redrawn */
2077 #ifdef DIRECTLY_DRAW_ON_EVENTS
2078 CSCLUIBuilder *builder = CSCLUIBuilder::get_instance();
2080 builder->draw_button(window, NULL, key_index, button_context->state, TRUE);
2083 if (savedInputMode == context->get_input_mode()) {
2084 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2095 CSCLController::mouse_press(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2098 sclboolean ret = FALSE;
2100 if (m_input_events_disabled) return FALSE;
2102 //utils->log("Controller::mouse_press : %d %d\n", x, y);
2104 /* Adjust x,y coordinate by touch offset */
2105 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2107 CSCLContext *context = CSCLContext::get_instance();
2108 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2109 CSCLActionState *state = CSCLActionState::get_instance();
2110 CSCLWindows *windows = CSCLWindows::get_instance();
2111 CSCLUtils *utils = CSCLUtils::get_instance();
2113 sclint button_index = NOT_USED;
2114 SclWindowContext *window_context = NULL;
2115 if (windows && cache) {
2116 const SclLayout *layout = cache->get_cur_layout(window);
2118 x += layout->mouse_manipulate_x;
2119 y += layout->mouse_manipulate_y;
2121 window_context = windows->get_window_context(window);
2122 /* If the dim window is virtual and currently active, let's just skip this event */
2123 if (windows->is_base_window(window)) {
2124 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2125 if (dim_window_context) {
2126 LOGD("dim window is_virtual:%d, hidden:%d", dim_window_context->is_virtual, dim_window_context->hidden);
2127 if (/*dim_window_context->is_virtual &&*/ !(dim_window_context->hidden)) {
2128 window = windows->get_dim_window();
2129 window_context = dim_window_context;
2135 if (cache && state && windows && context && window_context) {
2136 SCLDisplayMode display_mode = context->get_display_mode();
2137 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2138 PSclDefaultConfigure default_configure = NULL;
2139 if (sclres_manager) {
2140 default_configure = sclres_manager->get_default_configure();
2142 if (default_configure) {
2143 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2146 sclboolean isSubEvent = FALSE;
2147 if (context->get_multi_touch_context_num() > 0) {
2148 SclUIEventDesc desc;
2149 context->get_multi_touch_event(0, &desc);
2150 sclwindow pressed_window = context->get_cur_pressed_window(desc.touch_id);
2151 scl8 pressed_key = context->get_cur_pressed_key(desc.touch_id);
2152 SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2154 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_GRAB_SUB_EVENTS) {
2157 utils->play_vibration(DEFAULT_VIBRATION_STYLE, DEFAULT_VIBRATION_DURATION);
2161 context->create_multi_touch_context(touch_id, isSubEvent);
2162 context->set_cur_pressed_window(touch_id, window);
2163 context->set_cur_pressed_point(touch_id, x, y);
2164 context->set_cur_pressed_time(touch_id);
2165 context->set_cur_moving_window(touch_id, window);
2166 context->set_cur_moving_point(touch_id, x, y);
2167 context->set_last_touch_device_id(touch_id);
2168 context->set_cur_drag_state(touch_id, SCL_DRAG_STATE_NONE);
2169 context->set_cur_key_modifier(touch_id, KEY_MODIFIER_NONE);
2170 for (sclint labelidx = 0;labelidx < MAX_SIZE_OF_LABEL_FOR_ONE;labelidx++) {
2171 context->set_custom_magnifier_label(touch_id, labelidx, NULL);
2174 /* If there is postponed update of button, update it now */
2175 CSCLEvents *events = CSCLEvents::get_instance();
2176 sclwindow last_win = context->get_last_pressed_window();
2177 scl8 last_key = context->get_last_pressed_key();
2178 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2179 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2181 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2184 context->set_prev_pressed_window(touch_id, SCLWINDOW_INVALID);
2185 context->set_prev_pressed_key(touch_id, NOT_USED);
2186 context->set_prev_drag_state(touch_id, SCL_DRAG_STATE_NONE);
2187 context->set_prev_moving_point(touch_id, x, y);
2189 /* Destroy key related timers */
2190 events->destroy_timer(SCL_TIMER_BUTTON_DELAY);
2191 events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2192 events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2193 events->destroy_timer(SCL_TIMER_LONGKEY);
2194 events->destroy_timer(SCL_TIMER_REPEATKEY);
2195 events->destroy_timer(SCL_TIMER_MULTITAP);
2197 /* Do what has to be done when mouse gets pressed */
2198 handle_engine_signal(SCL_SIG_MOUSE_PRESS, window);
2200 /* Adjust event x and y positions as relative position to the virtual window */
2201 if (window_context) {
2202 /*if (window_context->isVirtual) {
2203 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2204 if (base_window_context) {
2205 x -= (window_context->x - base_window_context->x);
2206 y -= (window_context->y - base_window_context->y);
2212 sclboolean process_finished = FALSE;
2214 /* Iterate all the buttons and inform the event */
2215 sclboolean ended = FALSE;
2216 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2217 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
2218 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2219 if (button_context && coordinate) {
2220 if (!(button_context->used)) {
2222 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2223 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2224 if (process_button_pressed_event(window, x, y, loop, touch_id, actual_event)) {
2225 if (windows->is_base_window(window)) {
2226 state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2228 state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2230 button_index = loop;
2237 /* For covering a missing area about 1 pixel */
2239 for (int loop = 0;loop < MAX_KEY;loop++) {
2240 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
2241 const SclLayoutKeyCoordinate* coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2242 if (button_context && coordinate) {
2243 if (!(button_context->used)) {
2245 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2246 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2247 if (process_button_pressed_event(window, x+1, y+1, loop, touch_id, actual_event)) {
2248 if (windows->is_base_window(window)) {
2249 state->set_cur_action_state(ACTION_STATE_BASE_PRESS);
2251 state->set_cur_action_state(ACTION_STATE_POPUP_PRESS);
2253 button_index = loop;
2263 if (windows->is_base_window(window)) {
2264 process_finished = TRUE;
2265 } else if (button_index != NOT_USED) {
2266 process_finished = TRUE;
2268 const SclLayout *layout = cache->get_cur_layout(window);
2270 if (layout->use_sw_background && layout->bg_color.a == 0) {
2271 /* If we could not find appropriate button in this popup window and the popup is transparent */
2272 SclWindowContext *base_window_context =
2273 windows->get_window_context(windows->get_base_window());
2274 if (base_window_context) {
2275 x = (window_context->geometry.x + x - base_window_context->geometry.x);
2276 y = (window_context->geometry.y + y - base_window_context->geometry.y);
2278 window = windows->get_base_window();
2280 process_finished = TRUE;
2283 process_finished = TRUE;
2286 } while (!process_finished);
2289 sclwindow skip_window = window;
2290 if (ret && button_index != NOT_USED) {
2291 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, button_index);
2293 sclboolean dont_close_popup = FALSE;
2294 if (coordinate->dont_close_popup) {
2295 dont_close_popup = TRUE;
2297 /* If the button's popup type is drag type, the opened popup could be the one opened by this press event */
2298 if (coordinate->popup_type == POPUP_TYPE_BTN_PRESS_POPUP_DRAG) {
2299 /* Check the opened popup was opened by this button */
2300 sclwindow popupwin = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2301 SclWindowContext *popup_window_context = windows->get_window_context(popupwin);
2302 if (popup_window_context) {
2303 SclWindowOpener opener = popup_window_context->opener;
2304 if (opener.window == window && opener.key == button_index) {
2305 dont_close_popup = TRUE;
2309 if (dont_close_popup) {
2310 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2314 SclUIEventDesc key_event_desc;
2315 key_event_desc.event_type = EVENT_TYPE_PRESS;
2317 SclPoint curpoint = {x, y};
2318 key_event_desc.touch_id = touch_id;
2319 key_event_desc.mouse_pressed_point = curpoint;
2320 key_event_desc.mouse_current_point = curpoint;
2321 key_event_desc.mouse_farthest_point = curpoint;
2323 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2325 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2327 handler->on_event_drag_state_changed(key_event_desc);
2330 windows->close_all_popups(skip_window);
2332 /* When press event occured in popup window, reset POPUP_TIMEOUT timer */
2333 if (!(windows->is_base_window(window))) {
2334 if (window_context->timeout > 0) {
2335 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2336 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, window_context->timeout, 0, TRUE);
2338 } else if (skip_window != window) { /* Or the pressed button has dont_close_popup property, reset POPUP_TIMEOUT timer */
2339 //SclWindowContext *skip_window_context = windows->get_window_context(skip_window, FALSE);
2340 SclWindowContext *skip_window_context = windows->get_window_context(skip_window);
2341 if (skip_window_context) {
2342 if (skip_window_context->timeout > 0) {
2343 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
2344 events->create_timer(SCL_TIMER_POPUP_TIMEOUT, skip_window_context->timeout, 0, TRUE);
2354 CSCLController::mouse_release(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2357 sclboolean ret = FALSE;
2359 //if (m_input_events_disabled) return FALSE;
2361 //utils->log("Controller::mouse_release : %d %d\n", x, y);
2362 /* Adjust x,y coordinate by touch offset */
2363 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2365 CSCLContext *context = CSCLContext::get_instance();
2366 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2367 CSCLActionState *state = CSCLActionState::get_instance();
2368 CSCLWindows *windows = CSCLWindows::get_instance();
2369 CSCLUtils *utils = CSCLUtils::get_instance();
2370 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2371 CSCLEvents *events = CSCLEvents::get_instance();
2373 sclint button_index = NOT_USED;
2375 if (cache && state && windows && context && utils && handler && events &&
2376 context->find_multi_touch_context(touch_id)) {
2377 const SclLayout *layout = cache->get_cur_layout(window);
2379 x += layout->mouse_manipulate_x;
2380 y += layout->mouse_manipulate_y;
2383 sclwindow skip_window = SCLWINDOW_INVALID;
2384 SCLDisplayMode display_mode = context->get_display_mode();
2386 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2387 PSclDefaultConfigure default_configure = NULL;
2388 if (sclres_manager) {
2389 default_configure = sclres_manager->get_default_configure();
2391 if (default_configure) {
2392 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2395 context->set_cur_moving_window(touch_id, SCLWINDOW_INVALID);
2397 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2398 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2399 //SclWindowContext *window_context = windows->get_window_context(window, TRUE);
2400 SclWindowContext *window_context = windows->get_window_context(window);
2401 /* Adjust event x and y positions as relative position to the virtual window */
2402 if (window_context) {
2403 /*if (window_context->isVirtual) {
2404 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2405 if (base_window_context) {
2406 x -= (window_context->x - base_window_context->x);
2407 y -= (window_context->y - base_window_context->y);
2410 /* If the dim window is virtual and currently active, consider base window's event is occured in dim window */
2411 if (windows->is_base_window(window)) {
2412 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2413 if (dim_window_context) {
2414 if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2415 window = windows->get_dim_window();
2416 window_context = dim_window_context;
2422 /* Iterate all the buttons and inform the event */
2423 sclboolean ended = FALSE;
2425 /* FIXME : The routine below seems to be removed, which was originally requested by Vodafone,
2426 * to slow down the speed of repeat key right before stopping repeatkey event */
2427 /* if (state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY) {
2428 if (m_key_repeated_num > 10) {
2430 process_button_repeat_pressed_event(pressed_window, pressed_key, touch_id);
2435 if (context->get_cur_pressed_window(touch_id) == window) {
2436 if (abs(context->get_cur_pressed_point(touch_id).x - x) > utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD) ||
2437 abs(context->get_cur_pressed_point(touch_id).y - y) > utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD) )
2439 struct timeval t0 = context->get_cur_pressed_time(touch_id);
2441 gettimeofday(&t1, NULL);
2443 etime = ((t1.tv_sec * 1000000 + t1.tv_usec) - (t0.tv_sec * 1000000 + t0.tv_usec))/1000.0;
2444 if (etime < SCL_FLICK_GESTURE_RECOG_TIME) {
2445 SCLDragType drag_type = DRAG_NONE;
2446 if (x > context->get_cur_pressed_point(touch_id).x + utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2447 drag_type = DRAG_RIGHT;
2449 if (x < context->get_cur_pressed_point(touch_id).x - utils->get_scaled_x(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2450 drag_type = DRAG_LEFT;
2452 if (y > context->get_cur_pressed_point(touch_id).y + utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2453 drag_type = DRAG_DOWN;
2455 if (y < context->get_cur_pressed_point(touch_id).y - utils->get_scaled_y(SCL_FLICK_GESTURE_RECOG_THRESHOLD)) {
2456 drag_type = DRAG_UP;
2458 SclNotiGestureFlickDesc desc;
2459 SclUIEventDesc ui_event_desc;
2460 ui_event_desc.key_value = NULL;
2461 ui_event_desc.key_event = NOT_USED;
2462 ui_event_desc.key_modifier = KEY_MODIFIER_NONE;
2463 ui_event_desc.event_type = EVENT_TYPE_RELEASE;
2464 ui_event_desc.touch_id = touch_id;
2465 ui_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2466 ui_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2467 ui_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2468 ui_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2469 desc.ui_event_desc = &ui_event_desc;
2470 desc.drag_type = drag_type;
2471 if (handler->on_event_notification(SCL_UINOTITYPE_GESTURE_FLICK, &desc)) {
2478 /* FIXME : We should consider this kind of action in general manner, not only specific to autopopup */
2479 /* And also, this kind of implementation only selects button that was highlighted at least once. */
2481 //SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window, FALSE);
2482 SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window);
2483 if (pressed_window_context) {
2484 utils->log("PRESSED CTX : %p %d %d\n", pressed_window,
2485 pressed_window_context->geometry.x, pressed_window_context->geometry.y);
2486 //if (pressedCtx->popuptype == POPUP_TYPE_AUTO_POPUP) {
2487 sclboolean grab_event = FALSE;
2488 const SclLayout *pressed_layout = cache->get_cur_layout(pressed_window);
2489 if (pressed_layout) {
2490 if (pressed_layout->style == LAYOUT_STYLE_POPUP_GRAB) {
2493 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
2495 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
2496 sclboolean in_grab_area = TRUE;
2497 if (pressed_layout->add_grab_left != NOT_USED &&
2498 x < (pressed_window_context->geometry.x - pressed_layout->add_grab_left)) {
2499 in_grab_area = FALSE;
2501 if (pressed_layout->add_grab_right != NOT_USED &&
2502 x > (pressed_window_context->geometry.x + pressed_window_context->geometry.width
2503 + pressed_layout->add_grab_right)) {
2504 in_grab_area = FALSE;
2506 if (pressed_layout->add_grab_top != NOT_USED &&
2507 y < (pressed_window_context->geometry.y - pressed_layout->add_grab_top)) {
2508 in_grab_area = FALSE;
2510 if (pressed_layout->add_grab_bottom != NOT_USED &&
2511 y > (pressed_window_context->geometry.y + pressed_window_context->geometry.height
2512 + pressed_layout->add_grab_bottom)) {
2513 in_grab_area = FALSE;
2516 SclLayoutKeyCoordinate *coord = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2518 x = coord->x + (coord->width / 2);
2519 y = coord->y + (coord->height / 2);
2521 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2522 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, loop);
2523 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, loop);
2524 if (button_context && coordinate) {
2525 if (!(button_context->used)) {
2527 } else if (button_context->state != BUTTON_STATE_DISABLED &&
2528 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2529 if (process_button_release_event(pressed_window, x, y, loop, touch_id, actual_event)) {
2543 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2544 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2546 /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2547 /* Ignore base window's release event if a popup window is opened */
2548 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2549 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2550 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2551 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2552 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2553 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2554 if (windows->is_base_window(window)) {
2556 /* In case of direction button, the release event on other window should be processed */
2557 if (coordinate && window_context && pressed_window_context) {
2558 if (coordinate->button_type == BUTTON_TYPE_DIRECTION || coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
2559 sclint relx = (window_context->geometry.x + x) - pressed_window_context->geometry.x;
2560 sclint rely = (window_context->geometry.y + y) - pressed_window_context->geometry.y;
2561 if (process_button_release_event(pressed_window, relx, rely, pressed_key, touch_id, actual_event)) {
2562 button_index = pressed_key;
2564 x = coordinate->x + (coordinate->width / 2);
2565 y = coordinate->y + (coordinate->height / 2);
2566 skip_window = pressed_window;
2573 sclboolean process_finished = FALSE;
2575 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(touch_id);
2576 if (multi_touch_context) {
2577 if (!(multi_touch_context->is_sub_event)) {
2578 /* First check if the event occured in pressed key's threshold area */
2579 if (button_context && coordinate && !ended) {
2580 if (button_context->used && button_context->state != BUTTON_STATE_DISABLED) {
2581 if (process_button_release_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
2582 button_index = pressed_key;
2584 x = coordinate->x + (coordinate->width / 2);
2585 y = coordinate->y + (coordinate->height / 2);
2589 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2590 SclButtonContext *cur_context = cache->get_cur_button_context(window, loop);
2591 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
2592 if (cur_context && cur_coordinate) {
2593 if (!(cur_context->used)) {
2595 } else if (cur_context->state != BUTTON_STATE_DISABLED &&
2596 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
2597 if (window != pressed_window || loop != pressed_key) {
2598 if (process_button_release_event(window, x, y, loop, touch_id, actual_event)) {
2599 button_index = loop;
2607 process_finished = TRUE;
2609 SclUIEventDesc key_event_desc;
2610 key_event_desc.key_value = NULL;
2611 key_event_desc.key_event = NOT_USED;
2612 key_event_desc.key_modifier = KEY_MODIFIER_NONE;
2613 key_event_desc.event_type = EVENT_TYPE_NONE;
2614 key_event_desc.touch_id = touch_id;
2615 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2616 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2617 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2619 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2621 handler->on_event_key_clicked(key_event_desc);
2625 /* For covering a missing area about 1 pixel */
2629 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2630 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2631 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2632 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2633 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2634 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2635 if (windows->is_base_window(window)) {
2640 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
2641 SclButtonContext *cur_context = cache->get_cur_button_context(window, loop);
2642 if (cur_context && coordinate) {
2643 if (!(cur_context->used)) {
2646 } else if (cur_context->state != BUTTON_STATE_DISABLED &&
2647 coordinate->button_type != BUTTON_TYPE_UIITEM) {
2648 if (process_button_release_event(window, x+1, y+1, loop, touch_id)) {
2649 button_index = loop;
2657 if (windows->is_base_window(window)) {
2658 process_finished = TRUE;
2659 } else if (button_index != NOT_USED) {
2660 process_finished = TRUE;
2662 if (layout && layout->use_sw_background && layout->bg_color.a == 0) {
2663 /* If we could not find appropriate button in this popup window and the popup is transparent */
2664 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2665 if (base_window_context && window_context) {
2666 x = (window_context->geometry.x + x - base_window_context->geometry.x);
2667 y = (window_context->geometry.y + y - base_window_context->geometry.y);
2669 window = windows->get_base_window();
2671 process_finished = TRUE;
2674 } while (!process_finished);
2677 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2678 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2680 SCLShiftState shift_index = context->get_shift_state();
2681 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
2682 if (context->get_caps_lock_mode()) {
2683 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
2686 SclUIEventDesc key_event_desc;
2687 if (coordinate && button_context) {
2688 key_event_desc.key_type = coordinate->key_type;
2690 key_event_desc.key_value = coordinate->key_value[shift_index][button_context->multitap_index];
2691 key_event_desc.key_event = coordinate->key_event[shift_index][button_context->multitap_index];
2693 key_event_desc.key_modifier = context->get_cur_key_modifier(touch_id);;
2695 key_event_desc.event_type = EVENT_TYPE_RELEASE;
2696 key_event_desc.touch_id = touch_id;
2697 key_event_desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2698 key_event_desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2699 key_event_desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2701 key_event_desc.touch_event_order = context->get_multi_touch_event_order(touch_id);
2703 handler->on_event_drag_state_changed(key_event_desc);
2706 if (windows->is_base_window(window)) {
2707 state->set_cur_action_state(ACTION_STATE_BASE_INIT);
2709 state->set_cur_action_state(ACTION_STATE_POPUP_INIT);
2712 /* Restore previously pressed button's context and redraw it */
2713 if (button_context && coordinate) {
2714 button_context->state = BUTTON_STATE_NORMAL;
2715 /* Commented below line to postpone some of the feedback for releasing */
2716 //windows->update_window(pressed_window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
2719 /* If there is postponed update of button, update it now */
2720 sclwindow last_win = context->get_last_pressed_window();
2721 scl8 last_key = context->get_last_pressed_key();
2722 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2723 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_win, last_key);
2725 windows->update_window(last_win, coords->x, coords->y, coords->width, coords->height);
2729 /* To postpone some of the feedback for releasing */
2730 context->set_last_pressed_key(context->get_cur_pressed_key(touch_id));
2731 context->set_last_pressed_window(context->get_cur_pressed_window(touch_id));
2733 /* Do what has to be done when mouse gets released */
2734 sclboolean signaled = FALSE;
2736 switch (coordinate->popup_type) {
2737 case POPUP_TYPE_BTN_RELEASE_POPUP:
2738 case POPUP_TYPE_BTN_RELEASE_POPUP_ONCE:
2739 case POPUP_TYPE_BTN_LONGPRESS_POPUP:
2740 case POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE:
2742 /* Fix me : We should consider z-order */
2743 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2744 handle_engine_signal(SCL_SIG_MOUSE_RELEASE, skip_window);
2748 case POPUP_TYPE_NONE: break;
2749 case POPUP_TYPE_BTN_PRESS_POPUP_DRAG: break;
2750 case POPUP_TYPE_AUTO_POPUP: break;
2751 case MAX_POPUP_TYPE: break;
2756 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
2757 window_context = windows->get_window_context(window);
2758 if (window_context) {
2759 if (window_context->popup_type == POPUP_TYPE_BTN_RELEASE_POPUP ||
2760 window_context->popup_type == POPUP_TYPE_BTN_LONGPRESS_POPUP) {
2761 /* Don't close window if the clicked button is a child of ReleasePopup window */
2762 skip_window = window;
2763 handle_engine_signal(SCL_SIG_MOUSE_RELEASE, window);
2768 handle_engine_signal(SCL_SIG_MOUSE_RELEASE);
2772 context->set_cur_pressed_key(touch_id, NOT_USED);
2773 context->set_cur_pressed_window(touch_id, SCLWINDOW_INVALID);
2775 if (ret && button_index != NOT_USED) {
2776 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, button_index);
2777 if (cur_coordinate) {
2778 if (cur_coordinate->dont_close_popup) {
2779 skip_window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
2783 if (pressed_window == windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP)) {
2784 if (pressed_window_context) {
2785 if (pressed_window_context->popup_type != POPUP_TYPE_BTN_RELEASE_POPUP_ONCE &&
2786 pressed_window_context->popup_type != POPUP_TYPE_BTN_LONGPRESS_POPUP_ONCE &&
2787 pressed_window_context->popup_type != POPUP_TYPE_AUTO_POPUP &&
2788 pressed_window_context->popup_type != POPUP_TYPE_BTN_PRESS_POPUP_DRAG)
2790 skip_window = pressed_window;
2795 windows->close_all_popups(skip_window);
2797 /* Destroy key related timers */
2798 events->destroy_timer(SCL_TIMER_AUTOPOPUP);
2799 events->destroy_timer(SCL_TIMER_SHORT_LONGKEY);
2800 events->destroy_timer(SCL_TIMER_LONGKEY);
2801 events->destroy_timer(SCL_TIMER_REPEATKEY);
2803 /* If there are more than 1 active multitouch ids, don't play button_delay trick */
2804 if (context->get_multi_touch_context_num() == 1) {
2805 /* To postpone some of the feedback for releasing */
2806 events->create_timer(SCL_TIMER_BUTTON_DELAY, m_button_delay_duration, 0);
2808 last_win = context->get_last_pressed_window();
2809 last_key = context->get_last_pressed_key();
2811 if (last_win != SCLWINDOW_INVALID && last_key != NOT_USED) {
2812 const SclLayoutKeyCoordinate* last_coordinate = cache->get_cur_layout_key_coordinate(last_win, last_key);
2813 if (last_coordinate) {
2814 windows->update_window(last_win,
2815 last_coordinate->x, last_coordinate->y, last_coordinate->width, last_coordinate->height);
2819 windows->hide_window(windows->get_magnifier_window());
2820 context->set_last_pressed_window(SCLWINDOW_INVALID);
2821 context->set_last_pressed_key(NOT_USED);
2826 if (touch_id == context->get_last_touch_device_id()) {
2827 context->set_last_touch_device_id(SCLTOUCHDEVICE_INVALID);
2829 context->destroy_multi_touch_context(touch_id);
2835 SCLDragState get_drag_state(sclint deltax, sclint deltay)
2837 SCLDragState ret = SCL_DRAG_STATE_MAX;
2839 sclfloat ratio = fabs((sclfloat)deltay / (deltax ? deltax : 1));
2840 /* If tan(theta) is smaller than our predefined value */
2841 if (ratio <= (1 / SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE)) {
2843 ret = SCL_DRAG_STATE_RIGHT;
2845 ret = SCL_DRAG_STATE_LEFT;
2847 } else if (ratio >= SCL_DRAG_CURVE_4_DIRECTION_ANGLE_VALUE) {
2848 /* If tan(theta) is bigger than our predefined value */
2850 ret = SCL_DRAG_STATE_DOWN;
2852 ret = SCL_DRAG_STATE_UP;
2855 ret = SCL_DRAG_STATE_INVALID;
2862 CSCLController::mouse_move(sclwindow window, sclint x, sclint y, scltouchdevice touch_id, sclboolean actual_event)
2865 sclboolean ret = FALSE;
2867 if (m_input_events_disabled) return FALSE;
2869 //utils->log("Controller::mouse_move : %d %d\n", x, y);
2871 /* Adjust x,y coordinate by touch offset */
2872 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
2874 CSCLContext *context = CSCLContext::get_instance();
2875 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
2876 CSCLActionState *state = CSCLActionState::get_instance();
2877 CSCLWindows *windows = CSCLWindows::get_instance();
2878 CSCLEvents *events = CSCLEvents::get_instance();
2879 CSCLUtils *utils = CSCLUtils::get_instance();
2880 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
2881 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
2883 if (!sclres_manager) return FALSE;
2885 PSclModifierDecoration sclres_modifier_decoration = sclres_manager->get_modifier_decoration_table();
2886 if (!sclres_modifier_decoration) return FALSE;
2888 if (cache && state && windows && context && utils && adjustment && sclres_manager) {
2889 const SclLayout *layout = cache->get_cur_layout(window);
2891 x += layout->mouse_manipulate_x;
2892 y += layout->mouse_manipulate_y;
2895 if (!(context->find_multi_touch_context(touch_id))) return FALSE;
2897 PSclDefaultConfigure default_configure = sclres_manager->get_default_configure();
2898 if (default_configure) {
2899 SCLDisplayMode display_mode = context->get_display_mode();
2900 adjustment->apply_touch_offset(default_configure->touch_offset_level[display_mode], &x, &y);
2903 //SclWindowContext *window_context = windows->get_window_context(window, FALSE);
2904 SclWindowContext *window_context = windows->get_window_context(window);
2905 /* Adjust event x and y positions as relative position to the virtual window */
2906 if (window_context) {
2907 /*if (window_context->isVirtual) {
2908 SclWindowContext *base_window_context = windows->get_window_context(windows->get_base_window());
2909 if (base_window_context) {
2910 x -= (window_context->x - base_window_context->x);
2911 y -= (window_context->y - base_window_context->y);
2914 /* If the dim window is virtual and currently active, let's just skip this event */
2915 if (windows->is_base_window(window)) {
2916 SclWindowContext *dim_window_context = windows->get_window_context(windows->get_dim_window());
2917 if (dim_window_context) {
2918 if (dim_window_context->is_virtual && !(dim_window_context->hidden)) {
2923 /* If the pressed event was occured in dim window, let's just skip this move event */
2924 if (context->get_last_pressed_window() == windows->get_dim_window()) {
2929 sclwindow pressed_window = context->get_cur_pressed_window(touch_id);
2930 scl8 pressed_key = context->get_cur_pressed_key(touch_id);
2931 SclButtonContext *button_context = cache->get_cur_button_context(pressed_window, pressed_key);
2932 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(pressed_window, pressed_key);
2934 /* If the multitouch type is SETTLE_PREVIOUS and is not the last touch device, let's ignore move events */
2936 if (coordinate->multitouch_type == SCL_MULTI_TOUCH_TYPE_SETTLE_PREVIOUS) {
2937 if (context->get_last_touch_device_id() != touch_id) {
2943 context->set_cur_moving_point(touch_id, x, y);
2944 context->set_cur_moving_window(touch_id, window);
2946 /* If in longkey state, do not process, just return */
2947 if (state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
2948 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
2949 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
2950 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY) {
2953 /* FIXME : The rule below would not be a general requirement. A policy is needed regarding this. */
2954 /* And if the event occured in popup window, don't come back to base window */
2955 if (state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
2956 state->get_cur_action_state() == ACTION_STATE_POPUP_PRESS ||
2957 state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
2958 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
2959 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY ||
2960 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY) {
2961 if (windows->is_base_window(window)) {
2966 SclUIEventDesc desc;
2967 SCLShiftState shift_index = context->get_shift_state();
2968 if (context->get_caps_lock_mode()) {
2969 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
2972 desc.key_type = coordinate->key_type;
2973 desc.key_value = coordinate->key_value[shift_index][0];
2974 desc.key_event = coordinate->key_event[shift_index][0];
2976 desc.event_type = EVENT_TYPE_MOVE;
2977 desc.mouse_pressed_point = context->get_cur_pressed_point(touch_id);
2978 desc.mouse_current_point = context->get_cur_moving_point(touch_id);
2979 desc.mouse_farthest_point = context->get_farthest_move_point(touch_id);
2981 if (handler && handler->on_event_drag_state_changed(desc) != SCL_EVENT_PASS_ON) {
2985 /* FIXME : Add a condition to skip this code if longkey timer is not active */
2986 /* If the mouse has moved out of threshold value of longkey keypress area, destroy longkey timer */
2987 if (m_long_key_cancel_distance > 0) {
2988 sclfloat dist = utils->get_distance(x, y,
2989 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
2990 if (m_long_key_cancel_distance < dist) {
2991 events->destroy_timer(SCL_TIMER_LONGKEY);
2995 if (windows->is_base_window(window)) {
2996 state->set_cur_action_state(ACTION_STATE_BASE_MOVING);
2998 state->set_cur_action_state(ACTION_STATE_POPUP_MOVING);
3001 /* Iterate all the buttons and inform the event */
3002 sclboolean ended = FALSE;
3004 /* Check farthest move point and update it */
3007 if (pressed_window != window) {
3008 //SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window, FALSE);
3009 SclWindowContext *pressed_window_context = windows->get_window_context(pressed_window);
3010 if (window_context && pressed_window_context) {
3011 originx = (window_context->geometry.x - pressed_window_context->geometry.x) + x;
3012 originy = (window_context->geometry.y - pressed_window_context->geometry.y) + y;
3015 sclint startx = originx;
3016 sclint starty = originy;
3018 /* Check if we should recognize drag curve */
3020 startx = context->get_cur_pressed_point(touch_id).x;
3021 starty = context->get_cur_pressed_point(touch_id).y;
3022 sclint deltax = originx - startx;
3023 sclint deltay = originy - starty;
3024 sclfloat approximate_dist = utils->get_approximate_distance(originx, originy, startx, starty);
3026 sclboolean update_magnifier = FALSE;
3027 sclboolean drag_state_changed = FALSE;
3028 SCLDragState cur_drag_state = context->get_cur_drag_state(touch_id);
3029 SCLDragState next_drag_state = SCL_DRAG_STATE_NONE;
3030 sclfloat direction_recog_dist = SCL_DIRECTION_RECOG_DIST * utils->get_smallest_scale_rate();
3031 if (coordinate->is_side_button) {
3032 direction_recog_dist = SCL_DIRECTION_RECOG_DIST_SIDE * utils->get_smallest_scale_rate();
3035 if (coordinate->button_type == BUTTON_TYPE_DIRECTION) {
3036 /* Do not check farthest move point if current drag state is SCL_DRAG_STATE_RETURN */
3037 if (context->get_cur_drag_state(touch_id) != SCL_DRAG_STATE_RETURN) {
3038 if (approximate_dist > context->get_farthest_move_dist(touch_id)) {
3039 context->set_farthest_move_point(touch_id, originx, originy);
3043 if (cur_drag_state == SCL_DRAG_STATE_RETURN) {
3044 direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_RETURN;
3045 } else if (cur_drag_state != SCL_DRAG_STATE_NONE) {
3046 direction_recog_dist *= SCL_DRAG_RETURN_RECOG_THRESHOLD_OTHER;
3048 if (approximate_dist > direction_recog_dist) {
3049 next_drag_state = get_drag_state(deltax, deltay);
3050 /* Disable longkey if dragging is recognized */
3051 events->destroy_timer(SCL_TIMER_LONGKEY);
3053 if (cur_drag_state != next_drag_state) {
3054 drag_state_changed = TRUE;
3056 if (cur_drag_state == SCL_DRAG_STATE_NONE) {
3057 //if (nextDragState != SCL_DRAG_STATE_INVALID) {
3058 cur_drag_state = next_drag_state;
3060 } else if (cur_drag_state != next_drag_state) {
3061 if (next_drag_state == SCL_DRAG_STATE_NONE) {
3062 cur_drag_state = SCL_DRAG_STATE_RETURN;
3064 cur_drag_state = next_drag_state;
3068 context->set_cur_drag_state(touch_id, cur_drag_state);
3069 sclboolean check_farthest = FALSE;
3070 sclshort display = context->get_display_mode();
3071 if (!scl_check_arrindex(display, DISPLAYMODE_MAX)) display = 0;
3072 sclfloat dist = utils->get_distance(originx, originy,
3073 context->get_cur_pressed_point(touch_id).x, context->get_cur_pressed_point(touch_id).y);
3074 if (dist < direction_recog_dist && context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_RETURN) {
3075 if (coordinate->extra_option == DIRECTION_EXTRA_OPTION_8_DIRECTIONS_WITH_RETURN ||
3076 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN ||
3077 coordinate->extra_option == DIRECTION_EXTRA_OPTION_4_DIRECTIONS_WITH_RETURN_AND_CURVE) {
3078 deltax = context->get_farthest_move_point(touch_id).x -
3079 context->get_cur_pressed_point(touch_id).x;
3080 deltay = context->get_farthest_move_point(touch_id).y -
3081 context->get_cur_pressed_point(touch_id).y;
3082 dist = utils->get_distance(context->get_farthest_move_point(touch_id),
3083 context->get_cur_pressed_point(touch_id));
3084 check_farthest = TRUE;
3087 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist,
3088 check_farthest, touch_id, coordinate->extra_option);
3089 if (dist > direction_recog_dist) {
3090 context->set_cur_key_modifier(touch_id, key_modifier);
3092 /* If this button needs to be decorated when dragged */
3093 if (coordinate->modifier_decorator) {
3094 const SclModifierDecoration *decoration = NULL;
3096 /*if (scl_check_arrindex(coordinate->modifier_decorator,
3097 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
3098 scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
3099 if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
3100 if (sclres_modifier_decoration[decoration_id].valid) {
3101 decoration = &(sclres_modifier_decoration[decoration_id]);
3104 /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
3106 if (decoration->bg_image_path[display][key_modifier]) {
3107 windows->update_window(window,
3108 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3112 if (dist > direction_recog_dist) {
3113 if (context->get_magnifier_enabled()) {
3114 update_magnifier = TRUE;
3117 } else if (coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
3118 if (cur_drag_state != SCL_DRAG_STATE_NONE) {
3119 startx = context->get_prev_moving_point(touch_id).x;
3120 starty = context->get_prev_moving_point(touch_id).y;
3121 approximate_dist = utils->get_approximate_distance(originx, originy, startx, starty);
3122 direction_recog_dist = SCL_DIRECTION_RELATIVE_RECOG_DIST * utils->get_smallest_scale_rate();
3124 deltax = originx - startx;
3125 deltay = originy - starty;
3126 //printf("DIST : %f, RECOG : %f\n", dist, direction_recog_dist);
3127 if (approximate_dist > direction_recog_dist) {
3128 next_drag_state = get_drag_state(deltax, deltay);
3129 /* Disable longkey if dragging is recognized */
3130 events->destroy_timer(SCL_TIMER_LONGKEY);
3132 if (cur_drag_state != next_drag_state) {
3133 drag_state_changed = TRUE;
3135 if (next_drag_state != SCL_DRAG_STATE_NONE) {
3136 cur_drag_state = next_drag_state;
3138 context->set_cur_drag_state(touch_id, cur_drag_state);
3140 startx = context->get_farthest_move_point(touch_id).x;
3141 starty = context->get_farthest_move_point(touch_id).y;
3142 deltax = originx - startx;
3143 deltay = originy - starty;
3144 sclfloat dist_farthest = utils->get_approximate_distance(originx, originy, startx, starty);
3145 //printf("%d %d %d %d %f, %d %d\n", originx, originy, startx, starty, dist_farthest, cur_drag_state, next_drag_state);
3146 /* Let's see how much we are away from the last farthest point */
3147 sclfloat diffdir_recog_dist = SCL_DIRECTION_RELATIVE_DIFFDIR_RECOG_DIST * utils->get_smallest_scale_rate();
3148 /* If we moved certain amount from the point where direction changed, process drag state change routine */
3149 if (dist_farthest > diffdir_recog_dist || context->get_cur_drag_state(touch_id) == SCL_DRAG_STATE_NONE) {
3150 sclshort display = context->get_display_mode();
3151 SCLKeyModifier key_modifier = get_drag_key_modifier(deltax, deltay, dist_farthest,
3152 FALSE, touch_id, coordinate->extra_option);
3153 context->set_cur_key_modifier(touch_id, key_modifier);
3154 /* If this button needs to be decorated when dragged */
3155 if (coordinate->modifier_decorator) {
3156 const SclModifierDecoration *decoration = NULL;
3158 /*if (scl_check_arrindex(coordinate->modifier_decorator,
3159 sizeof(sclres_modifier_decoration) / sizeof(SclModifierDecoration ))) {*/
3160 scl8 decoration_id = sclres_manager->get_modifier_decoration_id(coordinate->modifier_decorator);
3161 if (scl_check_arrindex(decoration_id, MAX_SCL_MODIFIER_DECORATION_NUM)) {
3162 if (sclres_modifier_decoration[decoration_id].valid) {
3163 decoration = &(sclres_modifier_decoration[decoration_id]);
3166 /* Check if the button really needs to be redrawn (whether it has non-null bg_image_path information */
3168 if (decoration->bg_image_path[display][key_modifier]) {
3169 windows->update_window(window,
3170 coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3175 if (context->get_magnifier_enabled()) {
3176 update_magnifier = TRUE;
3179 context->set_prev_moving_point(touch_id, originx, originy);
3181 if (drag_state_changed) {
3182 /* When the dragging direction changes, save the current position as farthest point for future comparison */
3183 context->set_farthest_move_point(touch_id, originx, originy);
3184 LOGD("SET_FARTHEST : %d %d %d", originx, originy, context->get_cur_drag_state(touch_id));
3188 if (update_magnifier) {
3189 PSclMagnifierWndConfigure magnifier_configure = NULL;
3190 if (sclres_manager) {
3191 magnifier_configure = sclres_manager->get_magnifier_configure();
3194 const SclLayout *base_layout = cache->get_cur_layout(windows->get_base_window());
3195 if (base_layout && magnifier_configure) {
3196 SclPoint zoomwinpos = {0, 0};
3197 /* calculates x position to be set */
3198 zoomwinpos.x = (coordinate->x + (coordinate->width / 2)) -
3199 (magnifier_configure->width * utils->get_custom_scale_rate_x() / 2);
3201 /* calculates y position to be set */
3202 sclint scnWidth, scnHeight;
3203 utils->get_screen_resolution(&scnWidth, &scnHeight);
3205 zoomwinpos.y = coordinate->y - magnifier_configure->height * utils->get_custom_scale_rate_y();
3206 if (window_context) {
3207 zoomwinpos.x += window_context->geometry.x;
3208 zoomwinpos.y += window_context->geometry.y;
3210 if (zoomwinpos.x < 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x()) {
3211 zoomwinpos.x = 0 - magnifier_configure->padding_x * utils->get_custom_scale_rate_x();
3213 if (zoomwinpos.x > scnWidth +
3214 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
3215 magnifier_configure->width * utils->get_custom_scale_rate_x()) {
3216 zoomwinpos.x = scnWidth +
3217 magnifier_configure->padding_x * utils->get_custom_scale_rate_x() -
3218 magnifier_configure->width * utils->get_custom_scale_rate_x();
3220 zoomwinpos.y += magnifier_configure->padding_y * utils->get_custom_scale_rate_y();
3222 zoomwinpos.x += coordinate->magnifier_offset_x;
3223 zoomwinpos.y += coordinate->magnifier_offset_y;
3224 windows->move_window(windows->get_magnifier_window(), zoomwinpos.x, zoomwinpos.y, WINDOW_MAGNIFIER);
3225 windows->show_window(windows->get_magnifier_window(), 0);
3230 sclboolean grab_event = FALSE;
3232 if (layout->style == LAYOUT_STYLE_POPUP_GRAB) {
3235 /* If the topmost window has the POPUP_GRAB style, find the nearest button to the mouse pointer */
3236 if (grab_event && window_context) {
3237 /* If the layout's addGrab* values are defined, process this event only if the event occured inside grab area */
3238 sclboolean in_grab_area = TRUE;
3239 if (layout->add_grab_left != NOT_USED && x < -(layout->add_grab_left)) {
3240 in_grab_area = FALSE;
3242 if (layout->add_grab_right != NOT_USED && x >
3243 (window_context->geometry.width + layout->add_grab_right)) {
3244 in_grab_area = FALSE;
3246 if (layout->add_grab_top != NOT_USED && y < -(layout->add_grab_top)) {
3247 in_grab_area = FALSE;
3249 if (layout->add_grab_bottom != NOT_USED && y >
3250 (window_context->geometry.height + layout->add_grab_bottom)) {
3251 in_grab_area = FALSE;
3254 float min_dist = (float)((unsigned int)(-1));
3255 int min_dist_index = NOT_USED;
3256 for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
3257 button_context = cache->get_cur_button_context(window, loop);
3258 const SclLayoutKeyCoordinate *cur_coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3259 if (button_context && cur_coordinate) {
3260 if (!(button_context->used)) {
3262 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3263 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
3264 float dist = utils->get_approximate_distance(x, y,
3265 cur_coordinate->x + (cur_coordinate->width / 2),
3266 cur_coordinate->y + (cur_coordinate->height / 2));
3267 if (dist < min_dist) {
3268 min_dist_index = loop;
3274 /* When we found the nearest button, generate this event on the button */
3275 if (min_dist_index != NOT_USED) {
3276 const SclLayoutKeyCoordinate *min_coordinate =
3277 cache->get_cur_layout_key_coordinate(window, min_dist_index);
3278 if (min_coordinate) {
3279 x = min_coordinate->x + (min_coordinate->width / 2);
3280 y = min_coordinate->y + (min_coordinate->height / 2);
3281 if (process_button_move_event(window, x, y, min_dist_index, touch_id, actual_event)) {
3288 MultiTouchContext *multi_touch_context = context->find_multi_touch_context(touch_id);
3289 if (multi_touch_context) {
3290 sclint button_index = NOT_USED;
3291 if (!(multi_touch_context->is_sub_event)) {
3292 sclboolean process_finished = FALSE;
3294 /* First check if the event occured in pressed key's threshold area */
3295 if (button_context && coordinate) {
3296 if (pressed_window == window) { // Check only when the window is the one initally pressed
3297 if (button_context->used && button_context->state != BUTTON_STATE_DISABLED) {
3298 if (process_button_move_event(pressed_window, x, y, pressed_key, touch_id, actual_event)) {
3300 x = coordinate->x + (coordinate->width / 2);
3301 y = coordinate->y + (coordinate->height / 2);
3302 button_index = pressed_key;
3307 for (int loop = 0;loop < MAX_KEY && !ended && !ret;loop++) {
3308 button_context = cache->get_cur_button_context(window, loop);
3309 const SclLayoutKeyCoordinate *cur_coordinate =
3310 cache->get_cur_layout_key_coordinate(window, loop);
3311 if (button_context && cur_coordinate) {
3312 if (!(button_context->used)) {
3314 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3315 cur_coordinate->button_type != BUTTON_TYPE_UIITEM) {
3316 if (window != pressed_window || loop != pressed_key) {
3317 if (process_button_move_event(window, x, y, loop, touch_id, actual_event)) {
3319 button_index = loop;
3326 if (windows->is_base_window(window)) {
3327 process_finished = TRUE;
3328 } else if (button_index != NOT_USED) {
3329 process_finished = TRUE;
3331 const SclLayout *cur_layout = cache->get_cur_layout(window);
3332 if (cur_layout && cur_layout->use_sw_background && cur_layout->bg_color.a == 0) {
3333 /* If we could not find appropriate button in this popup window and the popup is transparent */
3334 SclWindowContext *base_window_context =
3335 windows->get_window_context(windows->get_base_window());
3336 if (base_window_context && window_context) {
3337 x = (window_context->geometry.x + x - base_window_context->geometry.x);
3338 y = (window_context->geometry.y + y - base_window_context->geometry.y);
3340 window = windows->get_base_window();
3342 process_finished = TRUE;
3345 } while (!process_finished);
3356 CSCLController::mouse_over(sclwindow window, sclint x, sclint y)
3359 sclboolean ret = FALSE;
3361 if (m_input_events_disabled)
3364 /* Adjust x,y coordinate by touch offset */
3365 CSCLErrorAdjustment *adjustment = CSCLErrorAdjustment::get_instance();
3366 /* Iterate all the buttons and inform the event */
3368 CSCLContext *context = CSCLContext::get_instance();
3369 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3370 CSCLActionState *state = CSCLActionState::get_instance();
3371 CSCLWindows *windows = CSCLWindows::get_instance();
3372 CSCLUtils *utils = CSCLUtils::get_instance();
3373 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3375 if (cache && state && windows && context && utils && adjustment && sclres_manager) {
3376 const SclLayout *layout = cache->get_cur_layout(window);
3378 x += layout->mouse_manipulate_x;
3379 y += layout->mouse_manipulate_y;
3382 SCLDisplayMode cur_display_mode = context->get_display_mode();
3384 const SclDefaultConfigure *default_configure = sclres_manager->get_default_configure();
3385 if (default_configure) {
3386 adjustment->apply_touch_offset(default_configure->touch_offset_level[cur_display_mode], &x, &y);
3389 /* Iterate all the buttons and inform the event */
3390 sclboolean ended = FALSE;
3392 for (int loop = 0; loop < MAX_KEY && !ended && !ret; loop++) {
3393 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
3394 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3395 if (button_context && coordinate) {
3396 if (!(button_context->used)) {
3398 } else if (button_context->state != BUTTON_STATE_DISABLED &&
3399 coordinate->button_type != BUTTON_TYPE_UIITEM) {
3400 if (process_button_over_event(window, x, y, loop)) {
3413 * Processes a timer event
3414 * If return FALSE, the current timer will be stop
3415 * ID : SCL_LOWORD(data)
3416 * value : SCL_HIWORD(data)
3419 CSCLController::timer_event(const scl32 data)
3422 CSCLWindows *windows = CSCLWindows::get_instance();
3423 CSCLContext *context = CSCLContext::get_instance();
3424 CSCLEvents* events = CSCLEvents::get_instance();
3425 CSCLActionState *state = CSCLActionState::get_instance();
3426 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3427 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3429 scl16 id = SCL_LOWORD(data); /* Timer ID */
3430 scl16 value = SCL_HIWORD(data); /* event unique ID */
3432 if (!windows || !context || !events || !state || !cache || !handler)
3436 case SCL_TIMER_AUTOPOPUP: {
3437 /* Checks whether my event id is availble */
3438 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3439 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3440 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3441 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3442 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3443 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3444 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3445 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3446 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3447 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3448 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3450 /* Ignores if the event id is different */
3451 events->destroy_timer(id);
3455 SclRectangle rect = {0, 0, 0, 0};
3456 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3457 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3459 if (configure_autopopup_window(window, key_index, &rect)) {
3460 /* Let's change out pressed button's state back to normal */
3461 SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
3462 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3464 if (button_context) {
3465 if (button_context->state == BUTTON_STATE_PRESSED) {
3466 button_context->state = BUTTON_STATE_NORMAL;
3468 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3472 /* Hide magnifier window when opening autopopup window */
3473 windows->hide_window(windows->get_magnifier_window());
3475 sclwindow popup_window = SCLWINDOW_INVALID;
3477 SclNotiPopupOpeningDesc desc;
3478 desc.ui_event_desc = NULL;
3479 desc.input_mode = SCL_LAYOUT_AUTOPOPUP_NAME;
3480 if (SCL_EVENT_PASS_ON ==
3481 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENING, &desc)) {
3482 /* Currently, window does not support virtual window */
3483 SclWindowOpener opener;
3484 opener.window = window;
3485 opener.key = key_index;
3487 popup_window = windows->open_popup(
3491 SCL_LAYOUT_AUTOPOPUP, POPUP_TYPE_AUTO_POPUP,
3495 SclNotiPopupOpenedDesc opened_desc;
3496 opened_desc.ui_event_desc = NULL;
3497 opened_desc.input_mode = desc.input_mode;
3498 opened_desc.window = popup_window;
3499 handler->on_event_notification(SCL_UINOTITYPE_POPUP_OPENED, &opened_desc);
3502 windows->hide_window(windows->get_magnifier_window());
3503 _play_tts_for_layout_autopopup_name();
3505 sclwindow moving_window = context->get_cur_moving_window(context->get_last_touch_device_id());
3506 SclPoint moving_point = context->get_cur_moving_point(context->get_last_touch_device_id());
3507 SclWindowContext *moving_window_context = windows->get_window_context(moving_window);
3508 SclWindowContext *popup_window_context = windows->get_window_context(popup_window);
3509 if (moving_window_context && popup_window_context) {
3510 moving_point.x = (moving_window_context->geometry.x - popup_window_context->geometry.x) + moving_point.x;
3511 moving_point.y = (moving_window_context->geometry.y - popup_window_context->geometry.y) + moving_point.y;
3513 //printf("AUTOPOPUP : %d %d\n", moving_point.x, moving_point.y);
3516 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3519 events->destroy_timer(id);
3525 case SCL_TIMER_LONGKEY: {
3526 /* Checks whether my event id is availble */
3527 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3528 state->get_cur_action_state() == ACTION_STATE_BASE_INIT ||
3529 //state->get_cur_action_state() == ACTION_STATE_BASE_MOVING ||
3530 state->get_cur_action_state() == ACTION_STATE_BASE_RELEASE ||
3531 state->get_cur_action_state() == ACTION_STATE_BASE_LONGKEY ||
3532 state->get_cur_action_state() == ACTION_STATE_BASE_REPEATKEY ||
3533 state->get_cur_action_state() == ACTION_STATE_POPUP_INIT ||
3534 //state->get_cur_action_state() == ACTION_STATE_POPUP_MOVING ||
3535 state->get_cur_action_state() == ACTION_STATE_POPUP_RELEASE ||
3536 state->get_cur_action_state() == ACTION_STATE_POPUP_LONGKEY ||
3537 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
3539 /* Ignores if the event id is different */
3540 events->destroy_timer(id);
3543 /* Ignores if the event id is different */
3544 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3545 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3546 if (process_button_long_pressed_event(window, key_index, context->get_last_touch_device_id())) {
3547 /* The button processed long key event, now enter longkey mode not to fire any events before releasing */
3548 handle_engine_signal(SCL_SIG_MOUSE_LONG_PRESS, window);
3549 windows->update_window(windows->get_magnifier_window());
3551 SclButtonContext *button_context = cache->get_cur_button_context(window, key_index);
3552 if (button_context->state == BUTTON_STATE_PRESSED) {
3553 button_context->state = BUTTON_STATE_NORMAL;
3554 CSCLWindows *windows = CSCLWindows::get_instance();
3556 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3557 windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
3560 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3561 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3564 /* Start the repeat key timer for NORMAL or GRAB buttons if longkey is not supported */
3565 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3568 /* This is for enabling backspace key in search layout*/
3569 //if (coordinate->use_repeat_key) {
3570 if (coordinate->use_repeat_key
3571 || coordinate->key_event[0][0] == MVK_BackSpace) {
3572 if (coordinate->button_type == BUTTON_TYPE_NORMAL ||
3573 coordinate->button_type == BUTTON_TYPE_GRAB ||
3574 coordinate->button_type == BUTTON_TYPE_SELFISH ||
3575 coordinate->button_type == BUTTON_TYPE_DIRECTION ||
3576 coordinate->button_type == BUTTON_TYPE_RELATIVE_DIRECTION) {
3577 m_key_repeated_num = 0;
3578 events->create_timer(SCL_TIMER_REPEATKEY, m_repeat_key_duration, value);
3579 if (windows->is_base_window(window)) {
3580 state->set_cur_action_state(ACTION_STATE_BASE_REPEATKEY);
3582 state->set_cur_action_state(ACTION_STATE_POPUP_REPEATKEY);
3588 events->destroy_timer(id);
3593 case SCL_TIMER_REPEATKEY: {
3594 /* Checks whether my event id is availble */
3595 if (context->get_cur_pressed_event_id(context->get_last_touch_device_id()) != value ||
3596 (state->get_cur_action_state() != ACTION_STATE_BASE_REPEATKEY &&
3597 state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY)
3599 /* Ignores if the event id is different */
3600 events->destroy_timer(id);
3603 sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
3604 sclbyte key_index = context->get_cur_pressed_key(context->get_last_touch_device_id());
3605 scllong interval = m_repeat_key_duration - (m_key_repeated_num * SCL_REPEATKEY_ACCELERATION);
3606 if (interval < SCL_REPEATKEY_MIN_DURATION) {
3607 interval = SCL_REPEATKEY_MIN_DURATION;
3609 process_button_repeat_pressed_event(window, key_index, context->get_last_touch_device_id());
3610 events->destroy_timer(id);
3611 events->create_timer(SCL_TIMER_REPEATKEY, interval, value);
3612 m_key_repeated_num++;
3616 case SCL_TIMER_BUTTON_DELAY: {
3617 /* If there is postponed update of button, update it now */
3618 sclwindow last_window = context->get_last_pressed_window();
3619 scl8 last_key = context->get_last_pressed_key();
3621 if (last_window != SCLWINDOW_INVALID && last_key != NOT_USED) {
3622 const SclLayoutKeyCoordinate* coords = cache->get_cur_layout_key_coordinate(last_window, last_key);
3624 windows->update_window(last_window, coords->x, coords->y, coords->width, coords->height);
3628 windows->hide_window(windows->get_magnifier_window());
3629 context->set_last_pressed_window(SCLWINDOW_INVALID);
3630 context->set_last_pressed_key(NOT_USED);
3631 events->destroy_timer(id);
3635 case SCL_TIMER_POPUP_TIMEOUT: {
3636 windows->close_all_popups(SCLWINDOW_INVALID, TRUE);
3637 events->destroy_timer(id);
3642 case SCL_TIMER_MULTITAP: {
3643 SclUIEventDesc key_event_desc;
3644 key_event_desc.event_type = EVENT_TYPE_RELEASE;
3645 key_event_desc.key_modifier = KEY_MODIFIER_MULTITAP_RELEASE;
3646 handler->on_event_key_clicked(key_event_desc);
3648 events->destroy_timer(id);
3650 /* We have to reset multitap button state when MULTITAP timer expired */
3651 sclboolean ended = FALSE;
3652 sclwindow window = windows->get_nth_window_in_Z_order_list(SCL_WINDOW_Z_TOP);
3653 for (int loop = 0;loop < MAX_KEY && !ended;loop++) {
3654 SclButtonContext *button_context = cache->get_cur_button_context(window, loop);
3655 if (button_context) {
3656 if (!(button_context->used)) {
3659 const SclLayoutKeyCoordinate *coordinate = cache->get_cur_layout_key_coordinate(window, loop);
3660 if (coordinate && coordinate->button_type == BUTTON_TYPE_MULTITAP) {
3661 button_context->multitap_index = 0;
3670 case SCL_TIMER_AUTOTEST: {
3673 unsigned int seed = 0;
3674 sclint rnd = rand_r(&seed) % 100;
3676 const SclLayout *layout = cache->get_cur_layout(windows->get_base_window());
3678 if (layout == NULL) {
3682 sclint x = (rand_r(&seed) % (layout->width));
3685 sclint y = (rand_r(&seed) % (layout->height));
3688 events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3689 events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3690 } else if (rnd < 90) {
3691 events->generate_mouse_event(SCL_MOUSE_EVENT_MOVE, x, y);
3692 } else if (rnd < 95) {
3693 events->generate_mouse_event(SCL_MOUSE_EVENT_PRESS, x, y);
3695 events->generate_mouse_event(SCL_MOUSE_EVENT_RELEASE, x, y);
3699 if (m_debug_variable < SCL_AUTOTEST_NUM) events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INTERVAL, 0, FALSE);
3700 else m_debug_mode = DEBUGMODE_DISABLED;
3704 case SCL_TIMER_ANIMATION: {
3705 CSCLAnimator *animator = CSCLAnimator::get_instance();
3707 return animator->animator_timer();
3713 events->destroy_timer(id);
3721 /* Handles signals to manage contexts mainly focusing on resetting variables and cleaning up states */
3722 void CSCLController::handle_engine_signal(SclInternalSignal signal, sclwindow targetWindow, SCLWindowType type)
3727 SIGACTION_RESIZE_RESOURCES,
3728 SIGACTION_DESTROY_TIMERS,
3729 SIGACTION_CLEAR_PRIVATEKEYS,
3730 SIGACTION_RECOMPUTE_LAYOUT,
3731 SIGACTION_FREE_IMAGES,
3732 SIGACTION_CLOSE_POPUP,
3733 SIGACTION_CLOSE_MAGNIFIER,
3734 SIGACTION_UNSET_SHIFT,
3735 SIGACTION_UNPRESS_KEYS,
3736 SIGACTION_INIT_DISPLAY,
3737 SIGACTION_INIT_INPUTMODE,
3741 const sclboolean SIGNAL_TABLE[SIGACTION_MAXNUM][SCL_SIG_MAXNUM] = {
3742 // START, SHOW, HIDE, INPCHNG, DISPCHNG, POPUPSHOW, POPUPHIDE, MOUSEPRES, M-LONGPRES, MOUSEREL, KEYEVT, FOCUSCHNG
3743 // SIGACTION_RESIZE_RESOURCES
3744 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3745 // SIGACTION_DESTROY_TIMERS
3746 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3747 // SIGACTION_CLEAR_PRIVATEKEYS
3748 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TRUE },
3749 // SIGACTION_RECOMPUTE_LAYOUT
3750 { 0, TRUE, 0, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, TRUE },
3751 // SIGACTION_FREE_IMAGES
3752 { TRUE, 0, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, 0 },
3753 // SIGACTION_CLOSE_POPUP
3754 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3755 // SIGACTION_CLOSE_MAGNIFIER
3756 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3757 // SIGACTION_UNSET_SHIFT
3758 { TRUE, 0 , 0 , TRUE, 0, 0, 0, 0, 0, 0, 0, TRUE },
3759 // SIGACTION_UNPRESS_KEYS
3760 { TRUE, TRUE, TRUE, TRUE, TRUE, 0, 0, 0, 0, 0, 0, TRUE },
3761 // SIGACTION_INIT_DISPLAY
3762 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 },
3763 // SIGACTION_INIT_INPUTMODE
3764 { TRUE, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, TRUE },
3767 scl_assert_return(signal >= 0 && signal < SCL_SIG_MAXNUM);
3769 CSCLEvents* events = CSCLEvents::get_instance();
3770 CSCLWindows *windows = CSCLWindows::get_instance();
3771 CSCLContext *context = CSCLContext::get_instance();
3772 CSCLImageProxy *proxy = CSCLImageProxy::get_instance();
3773 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3775 if (!events || !windows || !context || !proxy || !cache) return;
3781 context->set_hidden_state(FALSE);
3787 context->set_hidden_state(TRUE);
3790 windows->close_all_popups();
3794 case SCL_SIG_INPMODE_CHANGE:
3795 case SCL_SIG_DISP_CHANGE:
3796 case SCL_SIG_POPUP_SHOW:
3797 case SCL_SIG_POPUP_HIDE:
3798 case SCL_SIG_MOUSE_PRESS:
3799 case SCL_SIG_MOUSE_LONG_PRESS:
3800 case SCL_SIG_MOUSE_RELEASE:
3801 case SCL_SIG_KEYEVENT:
3807 for (loop = 0;loop < SIGACTION_MAXNUM;loop++) {
3808 if (SIGNAL_TABLE[loop][signal] == TRUE) {
3810 case SIGACTION_DESTROY_TIMERS:
3811 events->destroy_all_timer();
3813 case SIGACTION_RECOMPUTE_LAYOUT: {
3815 cache->recompute_layout(targetWindow, type);
3818 case SIGACTION_FREE_IMAGES:
3819 proxy->free_images();
3821 case SIGACTION_CLOSE_POPUP: {
3822 /* If there is a popup still opened, don't destroy POPUP_TIMEOUT timer */
3823 if (!(windows->close_all_popups(targetWindow))) {
3824 events->destroy_timer(SCL_TIMER_POPUP_TIMEOUT);
3828 case SIGACTION_CLOSE_MAGNIFIER: {
3829 if (signal == SCL_SIG_HIDE) {
3830 windows->hide_window(windows->get_magnifier_window(), TRUE);
3832 windows->hide_window(windows->get_magnifier_window());
3835 //events->create_timer(SCL_TIMER_BUTTON_DELAY, SCL_BUTTON_MIN_DURATION, 0);
3837 case SIGACTION_UNSET_SHIFT: {
3838 CSCLEventHandler *handler = CSCLEventHandler::get_instance();
3840 SclNotiShiftStateChangeDesc desc;
3841 desc.ui_event_desc = NULL;
3842 desc.shift_state = SCL_SHIFT_STATE_OFF;
3844 if (SCL_EVENT_PASS_ON ==
3845 handler->on_event_notification(SCL_UINOTITYPE_SHIFT_STATE_CHANGE, &desc)) {
3847 context->set_shift_state(SCL_SHIFT_STATE_OFF);
3852 case SIGACTION_UNPRESS_KEYS:
3854 context->set_cur_pressed_key(context->get_last_touch_device_id(), NOT_USED);
3855 context->set_cur_pressed_window(context->get_last_touch_device_id(), SCLWINDOW_INVALID);
3866 * Sets the duration value for longkey
3867 * If not set, it will use default longkey duration. see sclconfig
3870 CSCLController::set_longkey_duration(scllong msc)
3873 sclboolean ret = FALSE;
3875 m_long_key_duration = msc;
3882 * Sets the distance value for cancel longkey
3883 * If not set, it will use default longkey duration. see sclconfig
3886 CSCLController::set_longkey_cancel_dist(sclshort dist)
3889 sclboolean ret = FALSE;
3891 m_long_key_cancel_distance = dist;
3898 * Sets the duration value for repeatkey
3899 * If not set, it will use default repeatkey duration. see sclconfig
3902 CSCLController::set_repeatkey_duration(scllong msc)
3905 sclboolean ret = FALSE;
3907 m_repeat_key_duration = msc;
3914 * Sets the duration value for autopopup key
3915 * If not set, it will use default short longkey duration. see sclconfig
3918 CSCLController::set_autopopup_key_duration(scllong msc)
3921 sclboolean ret = FALSE;
3923 m_autopopup_key_duration = msc;
3930 * Sets the amount value for button delay
3931 * If not set, it will use default button delay amount. see sclconfig
3934 CSCLController::set_button_delay_duration(scllong msc)
3937 sclboolean ret = FALSE;
3939 m_button_delay_duration = msc;
3946 * Configures the variables for auto-popup window
3947 * It will return rectangle area
3948 * @return FALSE It's not available popup key
3951 CSCLController::configure_autopopup_window(sclwindow window, sclbyte key_index, SclRectangle* rect)
3954 scl_assert_return_false(window);
3955 scl_assert_return_false(key_index >= 0);
3957 sclboolean ret = TRUE;
3959 sclbyte num_keys, num_columns, num_rows;
3961 CSCLUtils *utils = CSCLUtils::get_instance();
3962 CSCLContext *context = CSCLContext::get_instance();
3963 CSCLWindows *windows = CSCLWindows::get_instance();
3964 CSCLResourceCache *cache = CSCLResourceCache::get_instance();
3966 const SclLayoutKeyCoordinate *coordinate = NULL;
3969 coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
3972 SclResParserManager *sclres_manager = SclResParserManager::get_instance();
3973 PSclAutoPopupConfigure autopopup_configure = NULL;
3974 if (sclres_manager) {
3975 autopopup_configure = sclres_manager->get_autopopup_configure();
3978 if (utils && context && windows && cache && coordinate && rect && autopopup_configure) {
3979 SCLShiftState shift_index = context->get_shift_state();
3980 if (!scl_check_arrindex(shift_index, SCL_SHIFT_STATE_MAX)) shift_index = SCL_SHIFT_STATE_OFF;
3981 if (context->get_caps_lock_mode()) {
3982 shift_index = (shift_index == SCL_SHIFT_STATE_OFF) ? SCL_SHIFT_STATE_ON : SCL_SHIFT_STATE_OFF;
3985 if (utils->get_autopopup_window_variables(coordinate->autopopup_key_labels[shift_index],
3986 &num_keys, &num_columns, &num_rows, &rect->width, &rect->height)) {
3987 /* There is no need for an autopopup window if number of keys are equal to or less than 0 */
3988 if (!(num_keys > 0)) {
3991 /* calculates y position to be set */
3992 SclRectangle baseWndRect;
3993 int scrwidth, scrheight;
3994 utils->get_screen_resolution(&scrwidth, &scrheight);
3996 windows->get_window_rect(windows->get_base_window(), &baseWndRect);
3997 /* Let the autopopup have its position right above the pressed button, with center alignment) */
3998 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) - (rect->width / 2);
3999 rect->y = baseWndRect.y + coordinate->y - rect->height +
4000 autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate();
4001 /* First check the growing direction of this autopopup window */
4002 if (coordinate->x < baseWndRect.width / 2) {
4003 /* We're growing left to right, calculate the left start point */
4004 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) -
4005 (autopopup_configure->button_width * utils->get_custom_scale_rate_x() / 2) -
4006 autopopup_configure->bg_padding * utils->get_smallest_custom_scale_rate();
4007 if (rect->x + rect->width > baseWndRect.x + baseWndRect.width) {
4008 sclint relocate_unit = autopopup_configure->button_width * utils->get_custom_scale_rate_x() +
4009 autopopup_configure->button_spacing * utils->get_smallest_custom_scale_rate();
4010 rect->x -= (((rect->x + rect->width - (baseWndRect.x + baseWndRect.width)) /
4011 relocate_unit) + 1) * relocate_unit;
4014 /* We're growing right to left, calculate the right end point */
4015 rect->x = baseWndRect.x + coordinate->x + (coordinate->width / 2) +
4016 (autopopup_configure->button_width * utils->get_custom_scale_rate_x() / 2) +
4017 autopopup_configure->bg_padding * utils->get_smallest_custom_scale_rate();
4018 rect->x -= rect->width;
4019 if (rect->x < baseWndRect.x) {
4020 sclint relocate_unit = autopopup_configure->button_width * utils->get_custom_scale_rate_x() +
4021 autopopup_configure->button_spacing * utils->get_smallest_custom_scale_rate();
4022 rect->x += (((baseWndRect.x - rect->x) /
4023 relocate_unit) + 1) * relocate_unit;
4026 //rect->y = (scrheight - layout->height) + coordinate->y - rect->height + autopopup_configure->decoration_size;
4027 /* Check if the window goes out of screen boundary */
4028 //if (rect->x + rect->width > scrwidth + utils->get_scale_x(scl_autopopup_configure.decoration_size)) rect->x = (scrwidth + utils->get_scale_x(scl_autopopup_configure.decoration_size)) - rect->width;
4029 if (rect->x + rect->width > scrwidth) rect->x = (scrwidth) - rect->width;
4030 if (rect->y + rect->height > scrheight) rect->y = scrheight - rect->height;
4031 if (rect->x < 0 - autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate())
4032 rect->x = 0 - autopopup_configure->decoration_size * utils->get_smallest_custom_scale_rate();
4034 if (rect->x < 0) rect->x = 0;
4035 if (rect->y < 0) rect->y = 0;
4044 * If the mouse was pressed on the button A and moved to B without releasing,
4045 * this function decides whether we should allow event transition, meaning
4046 * button A gets restored to its initial state and B gets pressed instead.
4049 CSCLController::check_event_transition_enabled(const SclLayoutKeyCoordinate *btn_from, const SclLayoutKeyCoordinate *btn_to)
4051 sclboolean ret = FALSE;
4052 sclbyte type_from = BUTTON_TYPE_NORMAL; /* To enable event transition even if no button is pressed currently */
4053 sclbyte type_to = MAX_BUTTON_TYPE;
4055 const sclboolean TRANSITION_TABLE[MAX_BUTTON_TYPE][MAX_BUTTON_TYPE] = {
4056 // NORMAL GRAB SELFISH DRAG MULTITAP ROTATION DIRECTION R_DIRECTION TOGGLE UIITEM
4058 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
4060 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
4062 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
4064 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
4066 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
4068 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
4070 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
4071 // From : R_DIRECTION
4072 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
4074 { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
4076 { TRUE, 0, 0, TRUE, TRUE, TRUE, 0, 0, TRUE, 0},
4079 if (btn_from) type_from = btn_from->button_type;
4080 if (btn_to) type_to = btn_to->button_type;
4082 scl_assert_return_false(type_from >= 0 && type_from < MAX_BUTTON_TYPE);
4083 scl_assert_return_false(type_to >= 0 && type_to < MAX_BUTTON_TYPE);
4085 if (type_from < MAX_BUTTON_TYPE && type_to < MAX_BUTTON_TYPE) {
4086 ret = TRANSITION_TABLE[type_from][type_to];
4093 CSCLController::get_debug_mode()
4096 return m_debug_mode;
4098 return m_debug_mode;
4099 return DEBUGMODE_DISABLED;
4104 CSCLController::set_debug_mode(SCLDebugMode mode)
4106 CSCLEvents *events = CSCLEvents::get_instance();
4107 CSCLUtils *utils = CSCLUtils::get_instance();
4109 m_debug_mode = mode;
4110 m_debug_variable = 0;
4112 if (m_debug_mode == DEBUGMODE_AUTOTEST) {
4114 if (events && utils) {
4115 events->create_timer(SCL_TIMER_AUTOTEST, SCL_AUTOTEST_TIMER_INITIAL_INTERVAL, 0, FALSE);
4116 utils->log("mode : %d\n", mode);
4122 CSCLController::disable_input_events(sclboolean disabled)
4124 m_input_events_disabled = disabled;