Implementation of key focus navigation on software. 87/22487/1
authorshoum.chen@samsung.com <shoum.chen@samsung.com>
Tue, 3 Jun 2014 23:45:07 +0000 (19:45 -0400)
committershoum.chen@samsung.com <shoum.chen@samsung.com>
Wed, 4 Jun 2014 21:49:51 +0000 (17:49 -0400)
Change-Id: I1b51fd578b7ace98a4f6dbbf2123c5550e736b5d

12 files changed:
CMakeLists.txt
scl/gwes/efl/sclevents-efl.cpp
scl/gwes/efl/sclevents-efl.h
scl/gwes/efl/sclwindows-efl.cpp
scl/gwes/gtk/sclevents-gtk.cpp
scl/include/sclkeyfocushandler.h [new file with mode: 0644]
scl/sclcontroller.cpp
scl/scleventhandler.cpp
scl/sclkeyfocushandler.cpp [new file with mode: 0644]
scl/sclresourcecache.cpp
scl/scluibuilder.cpp
scl/utils/linux/sclutils-linux.cpp

index c29241e..88758f9 100644 (file)
@@ -55,6 +55,7 @@ SET(SRCS
     scl/sclcontext.cpp
     scl/sclactionstate.cpp
     scl/sclresourcecache.cpp
+    scl/sclkeyfocushandler.cpp
     res/sclresource.cpp
     res/simple_debug.cpp
 )
index 8f6c25b..25d7626 100644 (file)
 
 #include <Elementary.h>
 #include <Ecore_X.h>
+#include <dlog.h> /*CHK_MRUNAL*/
+#include <utilX.h>
+
+#include "sclkeyfocushandler.h"
 
 using namespace scl;
 
@@ -43,6 +47,8 @@ Eina_Bool mouse_release (void *data, int type, void *event_info);
 
 Eina_Bool client_message_cb(void *data, int type, void *event);
 
+Eina_Bool key_pressed(void *data, int type, void *event_info);/*CHK_MRUNAL*/
+
 /**
  * Constructor
  */
@@ -55,6 +61,7 @@ CSCLEventsImplEfl::CSCLEventsImplEfl()
     m_mouse_up_handler = NULL;
 
     m_xclient_msg_handler = NULL;
+    m_key_pressed_handler = NULL;
 }
 
 /**
@@ -75,6 +82,7 @@ void CSCLEventsImplEfl::init()
     m_mouse_up_handler = ecore_event_handler_add(ECORE_EVENT_MOUSE_BUTTON_UP, mouse_release, NULL);
 
     m_xclient_msg_handler = ecore_event_handler_add(ECORE_X_EVENT_CLIENT_MESSAGE, client_message_cb, NULL);
+    m_key_pressed_handler = ecore_event_handler_add(ECORE_EVENT_KEY_DOWN, key_pressed, NULL);/*CHK_MRUNAL*/
 }
 
 void CSCLEventsImplEfl::fini()
@@ -87,6 +95,9 @@ void CSCLEventsImplEfl::fini()
     m_mouse_up_handler = NULL;
     if (m_xclient_msg_handler) ecore_event_handler_del(m_xclient_msg_handler);
     m_xclient_msg_handler = NULL;
+    if (m_key_pressed_handler) ecore_event_handler_del(m_key_pressed_handler);
+    m_key_pressed_handler = NULL;
+
 }
 
 sclboolean get_window_rect(const sclwindow window, SclRectangle *rect)
@@ -432,6 +443,91 @@ Eina_Bool mouse_release (void *data, int type, void *event_info)
     //controller->mouse_release((sclwindow)data, (int)ev->x, (int)ev->y);
 }
 
+/*CHK_MRUNAL*/
+Eina_Bool key_pressed(void *data, int type, void *event_info)
+{
+    LOGD("=-=-=-=- key_pressed \n");
+    CSCLController *controller = CSCLController::get_instance();
+    Ecore_Event_Key *ev = (Ecore_Event_Key *)event_info;
+    const char *ckey_val = ev->key;
+    LOGD("=-=-=-=- ev->key(char) = %c \n",ev->key);
+    LOGD("=-=-=-=- ev->key(string) = %s \n",ev->key);
+    LOGD("=-=-=-=- ev->keyname(char) = %c \n",ev->keyname);
+    LOGD("=-=-=-=- ev->keyname(string) = %s \n",ev->keyname);
+    LOGD("=-=-=-=- ev->string(char) = %c \n",ev->string);
+    LOGD("=-=-=-=- ev->string(string) = %s \n",ev->string);
+
+    CSCLResourceCache *cache = CSCLResourceCache::get_instance();
+    SclButtonContext *prevbtncontext = NULL;
+    const SclLayoutKeyCoordinate *prevcoordinate = NULL;
+    SclButtonContext *btncontext = NULL;
+    const SclLayoutKeyCoordinate *coordinate = NULL;
+
+    CSCLWindows *windows = CSCLWindows::get_instance();
+    sclwindow window = windows->get_base_window();
+    CSCLKeyFocusHandler* focus_handler = CSCLKeyFocusHandler::get_instance();
+
+    sclbyte current_key_index = focus_handler->get_current_key_index();
+    sclbyte key_index = current_key_index;
+
+    if (strcmp(ev->keyname, "Right") == 0) {
+        key_index = focus_handler->get_next_key_index(NAVIGATE_RIGHT);
+    } else if (strcmp(ev->keyname, "Left") == 0) {
+        key_index = focus_handler->get_next_key_index(NAVIGATE_LEFT);
+    } else if (strcmp(ev->keyname, "Up") == 0) {
+        key_index = focus_handler->get_next_key_index(NAVIGATE_UP);
+    } else if (strcmp(ev->keyname, "Down") == 0) {
+        key_index = focus_handler->get_next_key_index(NAVIGATE_DOWN);
+    } else if ((strcmp(ev->keyname, "Return") == 0)||(strcmp(ev->keyname, "Enter") == 0)) {
+        btncontext = cache->get_cur_button_context(window, current_key_index);
+        coordinate = cache->get_cur_layout_key_coordinate(window, current_key_index);
+        btncontext->state = BUTTON_STATE_NORMAL;
+        controller->mouse_press(window, coordinate->x, coordinate->y, TRUE);
+        controller->mouse_release(window, coordinate->x, coordinate->y, TRUE);
+        btncontext->state = BUTTON_STATE_PRESSED;
+        windows->update_window(window, coordinate->x, coordinate->y, coordinate->width, coordinate->height);
+        return TRUE;
+    }
+
+    if (current_key_index != key_index) {
+        btncontext = cache->get_cur_button_context(window, key_index);
+        prevbtncontext = cache->get_cur_button_context(window, current_key_index);
+        prevcoordinate = cache->get_cur_layout_key_coordinate(window, current_key_index);
+        coordinate = cache->get_cur_layout_key_coordinate(window, key_index);
+        prevbtncontext->state = BUTTON_STATE_NORMAL;
+        btncontext->state = BUTTON_STATE_PRESSED;
+        sclshort x,y,width,height;
+        if (prevcoordinate->x < coordinate->x) {
+            x = prevcoordinate->x;
+        } else { 
+            x = coordinate->x;
+        }
+
+        if (prevcoordinate->y < coordinate->y) {
+            y = prevcoordinate->y;
+        } else { 
+            y = coordinate->y;
+        }
+
+        if (prevcoordinate->x + prevcoordinate->width > coordinate->x + coordinate->width) {
+            width = prevcoordinate->x + prevcoordinate->width - x;
+        } else { 
+            width = coordinate->x + coordinate->width - x;
+        }
+
+        if (prevcoordinate->y + prevcoordinate->height > coordinate->y + coordinate->height) {
+            height = prevcoordinate->y + prevcoordinate->height - y;
+        } else { 
+            height = coordinate->y + coordinate->height - y;
+        }
+        windows->update_window(window, x, y, width, height);
+
+    } else {
+    }
+    
+    return TRUE;
+}
+
 //int mouse_move (void *data, Evas *e, Evas_Object *object, void *event_info)
 Eina_Bool mouse_move (void *data, int type, void *event_info)
 {
@@ -599,8 +695,7 @@ client_message_cb(void *data, int type, void *event)
 Eina_Bool timer_event(void *data)
 {
     SCL_DEBUG();
-
-    scl32 sendData = static_cast<scl32>(reinterpret_cast<uintptr_t>(data) & 0xffffffff);
+    scl32 sendData = (scl32)data;
     CSCLController *controller;
     controller = CSCLController::get_instance();
     if (controller) {
index 5447fcc..dc3ca9b 100644 (file)
@@ -50,6 +50,7 @@ private:
     Ecore_Event_Handler *m_mouse_move_handler;
     Ecore_Event_Handler *m_mouse_up_handler;
     Ecore_Event_Handler *m_xclient_msg_handler;
+    Ecore_Event_Handler *m_key_pressed_handler;
 };
 } /* End of scl namespace */
 #endif
index c2fde7b..e0ae75c 100644 (file)
 #include <malloc.h>
 #include <X11/Xlib.h>
 #include <X11/Xatom.h>
+#include <X11/Xutil.h>
+#include <utilX.h>
+#include <dlog.h>/*CHK_MRUNAL*/
+#include "sclkeyfocushandler.h"
 
 using namespace scl;
 
@@ -73,6 +77,33 @@ CSCLWindowsImplEfl::~CSCLWindowsImplEfl()
     SCL_DEBUG();
 }
 
+static Ecore_Event_Handler *_candidate_show_handler         = NULL;
+
+static Eina_Bool x_event_window_show_cb (void *data, int ev_type, void *event)
+{
+    CSCLWindows *windows = CSCLWindows::get_instance();
+    Evas_Object *window = (Evas_Object *)windows->get_base_window();
+    Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
+    CSCLKeyFocusHandler* focus_handler = CSCLKeyFocusHandler::get_instance();
+
+    if(e->win == elm_win_xwindow_get(window)) {
+        LOGD("INSIDE =-=-=-=- x_event_window_show_cb, Trying to Grab Key Board : \n");
+        focus_handler->grab_keyboard(windows->get_base_window());
+        focus_handler->init_key_index();
+    }
+    return ECORE_CALLBACK_RENEW;
+}
+
+
+void CSCLWindowsImplEfl::init()
+{
+
+}
+
+void CSCLWindowsImplEfl::fini()
+{
+
+}
 
 /**
  * Create a content window and binds it into given parent window as a child
@@ -87,6 +118,10 @@ CSCLWindowsImplEfl::create_base_window(const sclwindow parent, SclWindowContext
     if (winctx) {
         winctx->etc_info = NULL;
         winctx->window = parent;
+    
+    //Adding window show event handler:mrunal.s
+    _candidate_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_window_show_cb, NULL);
+
 
 #ifndef APPLY_WINDOW_MANAGER_CHANGE
         ecore_x_icccm_name_class_set(elm_win_xwindow_get(static_cast<Evas_Object*>(parent)), "Virtual Keyboard", "ISF" );
@@ -146,6 +181,8 @@ CSCLWindowsImplEfl::create_window(const sclwindow parent, SclWindowContext *winc
     ecore_x_e_window_rotation_geometry_set(elm_win_xwindow_get(win),
         rotation_values_EFL[ROTATION_90_CCW], 0, 0, new_width, new_height);
 
+    int rots[4] = {0, 90, 180, 270};
+    elm_win_wm_rotation_available_rotations_set(win, rots, 4);
 #ifndef FULL_SCREEN_TEST
     //evas_object_resize(win, width, height);
 #endif
@@ -371,46 +408,52 @@ CSCLWindowsImplEfl::destroy_window(sclwindow window)
 
     if (windows && utils && winctx) {
         if (winctx->etc_info) {
-            while ((Eina_List*)(winctx->etc_info)) {
-                EFLObject *object = (EFLObject*)eina_list_data_get((Eina_List*)(winctx->etc_info));
-                if (object) {
-                    Evas_Object* eo = object->object;
-                    if (object->extracted) {
-                        //evas_object_image_data_set(eo, NULL);
-                        void *data = evas_object_image_data_get(eo, 1);
-                        if (data) {
-                            free(data);
+            Eina_List *list = (Eina_List*)(winctx->etc_info);
+            Eina_List *iter = NULL;
+            Eina_List *iter_next = NULL;
+            void *data = NULL;
+
+            EINA_LIST_FOREACH_SAFE(list, iter, iter_next, data) {
+                if (data) {
+                    EFLObject *object = (EFLObject*)(data);
+                    if (object) {
+                        Evas_Object* eo = object->object;
+                        if (object->extracted) {
+                            //evas_object_image_data_set(eo, NULL);
+                            void *data = evas_object_image_data_get(eo, 1);
+                            if (data) {
+                                free(data);
+                            }
                         }
-                    }
-                    if (eo) {
-                        evas_object_del(eo);
-                        object->object = NULL;
-                    }
-                    if (object->type == EFLOBJECT_TEXTBLOCK) {
-                        Evas_Textblock_Style *st = (Evas_Textblock_Style*)(object->data);
-                        if (st) {
-                            evas_textblock_style_free(st);
+                        if (eo) {
+                            evas_object_del(eo);
+                            object->object = NULL;
                         }
+                        if (object->type == EFLOBJECT_TEXTBLOCK) {
+                            Evas_Textblock_Style *st = (Evas_Textblock_Style*)(object->data);
+                            if (st) {
+                                evas_textblock_style_free(st);
+                            }
 #ifdef TEST_NEWBACKEND
-                        for(sclint loop = 0;loop < g_TextCache.size();loop++) {
-                            if (g_TextCache[loop].text == object->object) {
-                                g_TextCache[loop].used = FALSE;
+                            for(sclint loop = 0;loop < g_TextCache.size();loop++) {
+                                if (g_TextCache[loop].text == object->object) {
+                                    g_TextCache[loop].used = FALSE;
+                                }
                             }
-                        }
 #endif
-                    } else if (object->type == EFLOBJECT_IMAGE) {
+                        } else if (object->type == EFLOBJECT_IMAGE) {
 #ifdef TEST_NEWBACKEND
-                        for(sclint loop = 0;loop < g_ImageCache.size();loop++) {
-                            if (g_ImageCache[loop].image == object->object) {
-                                g_ImageCache[loop].used = FALSE;
+                            for(sclint loop = 0;loop < g_ImageCache.size();loop++) {
+                                if (g_ImageCache[loop].image == object->object) {
+                                    g_ImageCache[loop].used = FALSE;
+                                }
                             }
-                        }
 #endif
+                        }
+                        delete object;
                     }
                 }
-                winctx->etc_info = eina_list_remove_list((Eina_List*)(winctx->etc_info), (Eina_List*)(winctx->etc_info));
-                if (object)
-                    delete object;
+                list = eina_list_remove_list(list, iter);
             }
             winctx->etc_info = NULL;
         }
@@ -480,7 +523,8 @@ CSCLWindowsImplEfl::show_window(const sclwindow window, sclboolean queue)
                 }
             }
         }
-        if (windows->get_magnifier_window() == window) {
+        scl8 popup_index = windows->find_popup_window_index(window);
+        if (windows->get_magnifier_window() == window || popup_index != NOT_USED) {
             /*
              * FIXME a solution to make magnifier window always on top
              * N_SE-17689: magnifier window showing behind of candidate window
@@ -510,6 +554,12 @@ CSCLWindowsImplEfl::hide_window(const sclwindow window,  sclboolean fForce)
     SclWindowContext *winctx = NULL;
 
     if (windows && window) {
+               /*CHK_MRUNAL*/
+        if (window == windows->get_base_window()) {
+                   CSCLKeyFocusHandler* focus_handler = CSCLKeyFocusHandler::get_instance();
+                   focus_handler->ungrab_keyboard(window);
+        }
+
         winctx = windows->get_window_context(window);
         if (winctx) {
             if (!(winctx->is_virtual)) {
index 7cfae2c..60408f7 100644 (file)
@@ -380,7 +380,7 @@ gboolean
 timer_event(gpointer data)
 {
     SCL_DEBUG();
-    scl32 sendData = static_cast<scl32>(reinterpret_cast<uintptr_t>(data) & 0xffffffff);
+    scl32 sendData = (scl32)data;
     CSCLController *controller;
     controller = CSCLController::get_instance();
     if (controller) {
diff --git a/scl/include/sclkeyfocushandler.h b/scl/include/sclkeyfocushandler.h
new file mode 100644 (file)
index 0000000..8bed631
--- /dev/null
@@ -0,0 +1,107 @@
+/*
+ * Copyright 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "scltypes.h"
+#include "sclres_type.h"
+#ifndef __SCL_KEY_FOCUS_HANDLER_H__
+#define __SCL_KEY_FOCUS_HANDLER_H__
+
+//#define TARGET_EMULATOR
+//SCL_BEGIN_DECLS
+
+namespace scl
+{
+typedef enum _SclKeyFocusNavigationDirection {
+       NAVIGATE_LEFT,
+       NAVIGATE_RIGHT,
+       NAVIGATE_UP,
+       NAVIGATE_DOWN
+}SclKeyFocusNavigationDirection;
+
+typedef struct _SclKeyboardRowInfo {
+       sclbyte start_index;
+       sclbyte size;
+       sclchar *sub_layout;
+       sclshort col_coord[20];
+}SclKeyboardRowInfo;
+
+typedef struct _SclKeyFocusNavigationInfo {
+       sclbyte total_rows;
+       sclbyte current_row;
+       sclbyte current_column;
+       sclshort row_coord;
+       SclKeyboardRowInfo* rows[20];
+}SclKeyFocusNavigationInfo;
+
+/**
+* @brief The class to store key focus navigation information
+*
+* This class implements functions to support key focus navigation on the software keyboard
+* using remote controller input. It generates navigation information for the currently loaded 
+* keyboard layout and provides the index of next key depending upon the navigation direction.
+* The key information can be retrieved from the array of key coordinates from Resource Cache.
+* 
+* Apart from key navigation information, this class also provides functions to grab and ungrab
+* the remote controller keys.
+*
+* The public interface can be divided in three categories :
+* 1. Focus grab/ungrab API : Invoked while showing and hiding the software keyboard
+* - Client class: CSCLWindowsImplEfl
+* 2. Focus navigation info buildig API : Invoked while computing layout of the current keyboard
+* - Client class/function: CSCLResourceCache::recompute_layout
+* 3. Focus navigation API: Invoked while handling remote controller key press events
+* - Client class: CSCLEventsImplEfl
+*/
+class CSCLKeyFocusHandler
+{
+public:
+    ~CSCLKeyFocusHandler();
+
+    static CSCLKeyFocusHandler* get_instance();
+
+       /*Focus grab/ungrab API*/
+       bool grab_keyboard(const sclwindow parent);
+       void ungrab_keyboard(const sclwindow parent);
+
+       /*Focus navigation info buildig API*/
+    void reset_key_navigation_info(void);
+    void update_key_navigation_info(SclLayoutKeyCoordinatePointer p_next_key, sclbyte index);
+    void finalize_key_navigation_info(void);
+
+       /*Focus navigation API*/
+       void    init_key_index(void);
+    sclbyte get_current_key_index(void);
+    sclbyte get_next_key_index(SclKeyFocusNavigationDirection direction);
+
+private:
+    SclKeyFocusNavigationInfo m_key_navi_info;
+       bool m_keyboard_grabbed;
+       bool sub_layout_match(sclchar *layout1,sclchar *layout2);
+
+    CSCLKeyFocusHandler();
+#ifdef TARGET_EMULATOR
+    sclwindow m_sniffer;
+    void create_sniffer_window(void);
+       void set_window_accepts_focus(const sclwindow window, sclboolean acceptable);
+#endif
+
+};
+
+}
+
+//SCL_END_DECLS
+
+#endif
index 4e09245..67e0cbc 100644 (file)
@@ -3178,6 +3178,7 @@ CSCLController::timer_event(const scl32 data)
                 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
            ) {
             /* Ignores if the event id is different */
+            events->destroy_timer(id);
             return FALSE;
         }
 
@@ -3252,6 +3253,7 @@ CSCLController::timer_event(const scl32 data)
                 state->get_cur_action_state() == ACTION_STATE_POPUP_REPEATKEY
            ) {
             /* Ignores if the event id is different */
+            events->destroy_timer(id);
             return FALSE;
         }
         /* Ignores if the event id is different */
@@ -3311,6 +3313,7 @@ CSCLController::timer_event(const scl32 data)
                  state->get_cur_action_state() != ACTION_STATE_POPUP_REPEATKEY)
            ) {
             /* Ignores if the event id is different */
+            events->destroy_timer(id);
             return FALSE;
         }
         sclwindow window = context->get_cur_pressed_window(context->get_last_touch_device_id());
index 9ef2da7..cce3d14 100644 (file)
@@ -290,6 +290,7 @@ CSCLEventHandler::pre_process_ui_event(SclUIEventDesc &ui_event_desc)
         {"Right",       MVK_Right       },
         {"Up",          MVK_Up          },
         {"Down",        MVK_Down        },
+        {"Escape",      MVK_Escape      },
     };
 
     /* Translate key_values only when key_event is 0 and key_value is not NULL */
diff --git a/scl/sclkeyfocushandler.cpp b/scl/sclkeyfocushandler.cpp
new file mode 100644 (file)
index 0000000..080d460
--- /dev/null
@@ -0,0 +1,566 @@
+/*
+ * Copyright 2012-2013 Samsung Electronics Co., Ltd.
+ *
+ * Licensed under the Flora License, Version 1.1 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://floralicense.org/license/
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+#include "sclkeyfocushandler.h"
+#include <Elementary.h>
+#include <Evas.h>
+#include <dlog.h>
+#include <Ecore_X.h>
+#include <utilX.h>
+#include "sclres_type.h"
+#include "scldebug.h"
+#include "sclcontext.h"
+using namespace scl;
+
+/**
+ * Constructor
+ */
+CSCLKeyFocusHandler::CSCLKeyFocusHandler()
+{
+    SCL_DEBUG();
+    m_keyboard_grabbed = FALSE;
+    m_key_navi_info.total_rows = 0;
+    m_key_navi_info.current_row = 0;
+    m_key_navi_info.current_column = 0;
+    m_key_navi_info.row_coord = 0;
+    int i = 0;
+    for(i = 0;i < 20; i++) {
+        m_key_navi_info.rows[i] = NULL;
+    }
+#ifdef TARGET_EMULATOR
+    create_sniffer_window();
+#endif
+}
+
+/**
+ * Destructor
+ */
+CSCLKeyFocusHandler::~CSCLKeyFocusHandler()
+{
+    SCL_DEBUG();
+    for(int counter = 0; counter < m_key_navi_info.total_rows; counter++) {
+        if (m_key_navi_info.rows[counter]) {
+            if (m_key_navi_info.rows[counter]->sub_layout) {
+                delete m_key_navi_info.rows[counter]->sub_layout;
+                m_key_navi_info.rows[counter]->sub_layout = NULL;
+            }
+            delete m_key_navi_info.rows[counter];
+            m_key_navi_info.rows[counter] = NULL;
+        }
+    }
+}
+
+CSCLKeyFocusHandler*
+CSCLKeyFocusHandler::get_instance()
+{
+    static CSCLKeyFocusHandler instance;
+    return &instance;
+}
+
+/**
+ * Grabs the navigation and Return keys
+ */
+bool
+CSCLKeyFocusHandler::grab_keyboard(const sclwindow parent)
+{
+    Evas_Object *window = (Evas_Object *)parent;
+    Ecore_X_Window x_window = elm_win_xwindow_get(window);
+
+    Display *x_display = (Display *)ecore_x_display_get();
+    int grab_result;
+    grab_result = utilx_grab_key(x_display, x_window, "Right", EXCLUSIVE_GRAB);
+    if (0 == grab_result) {
+        LOGD("Right Key Grabbed successfully\n");
+    } else if (EXCLUSIVE_GRABBED_ALREADY == grab_result) {
+        LOGD("Right Key already grabbed in Exclusiv mode\n");
+    } else {
+        LOGD("Failed to Grab Right key\n");
+    }
+
+    grab_result = utilx_grab_key(x_display, x_window, "Left", EXCLUSIVE_GRAB);
+    if(0 == grab_result) {
+        LOGD("Left Key Grabbed successfully\n");
+    } else if (EXCLUSIVE_GRABBED_ALREADY == grab_result) {
+        LOGD("Left Key already grabbed in Exclusiv mode\n");
+    } else {
+        LOGD("Failed to Grab Left key\n");
+    }
+
+    grab_result = utilx_grab_key(x_display, x_window, "Up", EXCLUSIVE_GRAB);
+    if (0 == grab_result) {
+        LOGD("Up Key Grabbed successfully\n");
+    } else if (EXCLUSIVE_GRABBED_ALREADY == grab_result) {
+        LOGD("Up Key already grabbed in Exclusiv mode\n");
+    } else {
+        LOGD("Failed to Grab Up key\n");
+    }
+
+    grab_result = utilx_grab_key(x_display, x_window, "Down", EXCLUSIVE_GRAB);
+    if (0 == grab_result) {
+        LOGD("Down Key Grabbed successfully\n");
+    } else if (EXCLUSIVE_GRABBED_ALREADY == grab_result) {
+        LOGD("Down Key already grabbed in Exclusiv mode\n");
+    } else {
+        LOGD("Failed to Grab Down key\n");
+    }
+
+
+
+    grab_result = utilx_grab_key(x_display, x_window, "Return", EXCLUSIVE_GRAB);
+    if (0 == grab_result) {
+        LOGD("Return Key Grabbed successfully\n");
+    } else if (EXCLUSIVE_GRABBED_ALREADY == grab_result) {
+        LOGD("Return Key already grabbed in Exclusiv mode\n");
+    } else {
+        LOGD("Failed to Grab Return key\n");
+    }
+/*
+       grab_result = utilx_grab_key(x_display, x_window, KEY_VOLUMEUP, EXCLUSIVE_GRAB);
+       if( 0 == grab_result ) {
+               LOGD("KEY_VOLUMEUP Grabbed successfully\n");
+       } else if(EXCLUSIVE_GRABBED_ALREADY == grab_result) {
+               LOGD("KEY_VOLUMEUP already grabbed in Exclusiv mode\n");
+       } else {
+               LOGD("Failed to Grab KEY_VOLUMEUP\n");
+       }
+
+
+       grab_result = utilx_grab_key(x_display, x_window, KEY_VOLUMEDOWN, EXCLUSIVE_GRAB);
+       if( 0 == grab_result ) {
+               LOGD("KEY_VOLUMEDOWN Grabbed successfully\n");
+       } else if(EXCLUSIVE_GRABBED_ALREADY == grab_result) {
+               LOGD("KEY_VOLUMEDOWN already grabbed in Exclusiv mode\n");
+       } else {
+               LOGD("Failed to Grab KEY_VOLUMEDOWN\n");
+       }
+*/
+    m_keyboard_grabbed = TRUE;
+    return TRUE;
+}
+
+/**
+ * UnGrabs the navigation and Return keys
+ */
+void
+CSCLKeyFocusHandler::ungrab_keyboard(const sclwindow parent)
+{
+    Evas_Object *window = (Evas_Object *)parent;
+    Ecore_X_Window x_window = elm_win_xwindow_get(window);
+    Display *x_display = (Display *)ecore_x_display_get();
+    int grab_result;
+    grab_result = utilx_ungrab_key(x_display, x_window, "Right");
+    if (0 == grab_result) {
+        LOGD("Right Key UnGrabbed successfully\n");
+    } else {
+        LOGD("Failed to UnGrab Right key\n");
+    }
+
+    grab_result = utilx_ungrab_key(x_display, x_window, "Left");
+    if (0 == grab_result) {
+        LOGD("Left Key UnGrabbed successfully\n");
+    } else {
+        LOGD("Failed to UnGrab Left key\n");
+    }
+
+    grab_result = utilx_ungrab_key(x_display, x_window, "Up");
+    if (0 == grab_result) {
+        LOGD("Up Key UnGrabbed successfully\n");
+    } else {
+        LOGD("Failed to UnGrab Up key\n");
+    }
+
+    grab_result = utilx_ungrab_key(x_display, x_window, "Down");
+    if (0 == grab_result) {
+        LOGD("Down Key UnGrabbed successfully\n");
+    } else {
+        LOGD("Failed to UnGrab Down key\n");
+    }
+
+    grab_result = utilx_ungrab_key(x_display, x_window, "Return");
+    if(0 == grab_result) {
+        LOGD("Return Key UnGrabbed successfully\n");
+    } else {
+        LOGD("Failed to UnGrab Return key\n");
+    }
+/*
+       grab_result = utilx_ungrab_key(x_display, x_window, "Enter");
+       if( 0 == grab_result ) {
+               LOGD("Enter Key UnGrabbed successfully\n");
+       } else {
+               LOGD("Failed to UnGrab Enter key\n");
+       }
+
+       grab_result = utilx_ungrab_key(x_display, x_window, KEY_VOLUMEUP);
+       if( 0 == grab_result ) {
+               LOGD("KEY_VOLUMEUP UnGrabbed successfully\n");
+       } else {
+               LOGD("Failed to UnGrab KEY_VOLUMEUP\n");
+       }
+
+       grab_result = utilx_ungrab_key(x_display, x_window, KEY_VOLUMEDOWN);
+       if( 0 == grab_result ) {
+               LOGD("KEY_VOLUMEDOWN UnGrabbed successfully\n");
+       } else {
+               LOGD("Failed to UnGrab KEY_VOLUMEDOWN\n");
+       }
+*/
+    m_keyboard_grabbed = FALSE;
+}
+
+/**
+ * Resets the navigation info
+ */
+void
+CSCLKeyFocusHandler::reset_key_navigation_info(void)
+{
+    LOGD("Inside reset_key_navigation_info");
+    LOGD("Total rows = %d \n",m_key_navi_info.total_rows);
+    for(int counter = 0; counter < m_key_navi_info.total_rows; counter++) {
+        if (m_key_navi_info.rows[counter]) {
+            if (m_key_navi_info.rows[counter]->sub_layout) {
+                delete m_key_navi_info.rows[counter]->sub_layout;
+                m_key_navi_info.rows[counter]->sub_layout = NULL;
+            }
+            delete m_key_navi_info.rows[counter];
+            m_key_navi_info.rows[counter] = NULL;
+        }
+    }
+
+    m_key_navi_info.total_rows = 0;
+    m_key_navi_info.current_row = 0;
+    m_key_navi_info.current_column = 0;
+    m_key_navi_info.row_coord = 0;
+
+    LOGD("reset_key_navigation_info executed succesfully \n");
+}
+
+/**
+ * Compares the sub-layout values
+ */
+inline bool
+CSCLKeyFocusHandler::sub_layout_match(sclchar *layout1,sclchar *layout2)
+{
+    if (layout1) {
+        if (layout2) {
+            if (strcmp(layout1, layout2) == 0) {
+                return TRUE;
+            }
+        }
+    } else if (layout2) {
+        return FALSE;
+    } else {
+        return TRUE;
+    }
+    return FALSE;
+}
+
+/**
+ * Builds the key navigation info
+ */
+void
+CSCLKeyFocusHandler::update_key_navigation_info(SclLayoutKeyCoordinatePointer p_next_key, sclbyte index)
+{
+    //LOGD("Inside update_key_navigation_info for index = %d \n",index);
+    //check for new row..
+    //LOGD("y coordinate = %d \n",p_next_key->y);
+    bool allocate_row = FALSE;
+    if (!m_key_navi_info.total_rows || m_key_navi_info.row_coord != p_next_key->y) {
+        allocate_row = TRUE;
+    } else {
+        if (!sub_layout_match(m_key_navi_info.rows[m_key_navi_info.current_row]->sub_layout,p_next_key->sub_layout)) {
+            allocate_row = TRUE;
+        }
+    }
+
+    if (allocate_row) {
+        //allocate new row..
+        //LOGD("allocate new row.. = \n");
+        m_key_navi_info.rows[m_key_navi_info.total_rows++] = new SclKeyboardRowInfo;
+        //preserving the y-coordinate temprorily in row_coord for comparision in next call..
+        m_key_navi_info.row_coord = p_next_key->y;
+        //update the current_row to keep updating the size in next calls
+        m_key_navi_info.current_row = m_key_navi_info.total_rows - 1;
+        //set up the start index of row
+        m_key_navi_info.rows[m_key_navi_info.current_row]->start_index = index;
+        //update sub_layout info if any..
+        if (p_next_key->sub_layout) {
+            int size = strlen(p_next_key->sub_layout);
+            m_key_navi_info.rows[m_key_navi_info.current_row]->sub_layout = new sclchar[size + 1];
+            strcpy(m_key_navi_info.rows[m_key_navi_info.current_row]->sub_layout,p_next_key->sub_layout);
+        } else {
+            m_key_navi_info.rows[m_key_navi_info.current_row]->sub_layout = NULL;
+        }
+        //reset size, will be increamented afterwards..
+        m_key_navi_info.rows[m_key_navi_info.current_row]->size = 0;
+    }
+    //update the start of this column
+    m_key_navi_info.rows[m_key_navi_info.current_row]->col_coord[m_key_navi_info.rows[m_key_navi_info.current_row]->size] = p_next_key->x;
+    //update the row size..
+    m_key_navi_info.rows[m_key_navi_info.current_row]->size++;
+    //LOGD("update_key_navigation_info executed succesfully for index = %d \n",index);
+}
+
+/**
+ * Finalize the navigation info
+ */
+void
+CSCLKeyFocusHandler::finalize_key_navigation_info(void)
+{
+    LOGD("Inside finalize_key_navigation_info");
+
+    m_key_navi_info.current_row = 0;
+    m_key_navi_info.current_column = 0;
+    LOGD("Total rows = %d \n",m_key_navi_info.total_rows);
+    LOGD("finalize_key_navigation_info executed succesfully \n");
+}
+
+/**
+ * Initializes the key index to first key of first row
+ */
+void
+CSCLKeyFocusHandler::init_key_index(void)
+{
+    CSCLContext *context = CSCLContext::get_instance();
+    sclchar* current_sub_layout = context->get_cur_sublayout();
+    int row = 0;
+    for(row = 0; row <= m_key_navi_info.total_rows - 1; row++) {
+        if (m_key_navi_info.rows[row]->sub_layout) {
+            if (strcmp(m_key_navi_info.rows[row]->sub_layout, current_sub_layout) == 0) {
+                break;
+            }
+        } else {
+            break;
+        }
+    }
+    if (row > m_key_navi_info.total_rows - 1) {
+        row = 0;
+    }
+    m_key_navi_info.current_row = row;
+    m_key_navi_info.current_column = 0;
+    LOGD("Inside init_key_index m_key_navi_info.current_row = %d \n",m_key_navi_info.current_row);
+}
+
+/**
+ * Returns the currently focussed key index
+ */
+sclbyte
+CSCLKeyFocusHandler::get_current_key_index(void)
+{
+    LOGD("Inside get_current_key_index m_key_navi_info.current_row = %d \n",m_key_navi_info.current_row);
+    sclbyte index = m_key_navi_info.rows[m_key_navi_info.current_row]->start_index + m_key_navi_info.current_column;
+    LOGD("Inside get_current_key_index index = %d \n",index);
+    return index;
+}
+
+/**
+ * Computes and Returns the key index for next focussed key depending upon the navigation direction
+ */
+sclbyte
+CSCLKeyFocusHandler::get_next_key_index(SclKeyFocusNavigationDirection direction)
+{
+    LOGD("Inside get_next_key_index m_key_navi_info.current_row = %d \n",m_key_navi_info.current_row);
+    sclbyte index = 0;
+    bool row_found = FALSE;
+    int row = 0;
+    int col = 0;       
+    switch(direction) {
+        case NAVIGATE_LEFT:
+            if (m_key_navi_info.current_column) {
+                m_key_navi_info.current_column--;
+            } else {
+                m_key_navi_info.current_column = m_key_navi_info.rows[m_key_navi_info.current_row]->size - 1;
+            }
+        break;
+        case NAVIGATE_RIGHT:
+            if (m_key_navi_info.current_column < m_key_navi_info.rows[m_key_navi_info.current_row]->size - 1) {
+                m_key_navi_info.current_column++;
+            } else {
+                m_key_navi_info.current_column = 0;
+            }
+            LOGD("Inside get_next_key_index m_key_navi_info.current_column = %d \n",m_key_navi_info.current_column);
+        break;
+        case NAVIGATE_UP:
+            if (m_key_navi_info.current_row) {
+                CSCLContext *context = CSCLContext::get_instance();
+                sclchar* current_sub_layout = context->get_cur_sublayout();
+                for(row = m_key_navi_info.current_row - 1; row >= 0; row--) {
+                    if (m_key_navi_info.rows[row]->sub_layout) {
+                        if (strcmp(m_key_navi_info.rows[row]->sub_layout, current_sub_layout) == 0) {
+                            row_found = TRUE;
+                            break;
+                        }
+                    } else {
+                        row_found = TRUE;
+                        break;
+                    }
+                }
+            }
+        break;
+        case NAVIGATE_DOWN:
+            if (m_key_navi_info.current_row < m_key_navi_info.total_rows - 1) {
+                CSCLContext *context = CSCLContext::get_instance();
+                sclchar* current_sub_layout = context->get_cur_sublayout();
+                for(row = m_key_navi_info.current_row + 1; row <= m_key_navi_info.total_rows - 1; row++) {
+                    if (m_key_navi_info.rows[row]->sub_layout) {
+                        if (strcmp(m_key_navi_info.rows[row]->sub_layout, current_sub_layout) == 0) {
+                            row_found = TRUE;
+                            break;
+                        }
+                    } else {
+                        row_found = TRUE;
+                        break;
+                    }
+                }
+            }
+        break;
+        default:
+        break;
+    }
+
+    if (row_found) {
+        //get x xoordinate of the currently focused key
+        int cur_row = m_key_navi_info.current_row;
+        int cur_col = m_key_navi_info.current_column;
+        sclshort cur_col_coodinate = m_key_navi_info.rows[cur_row]->col_coord[cur_col];
+        //check if the current colum is within the size range of target row
+        if (cur_col <= m_key_navi_info.rows[row]->size - 1) {
+            //check if the x coordinate of current column is greater than the same column in the target row
+            if (m_key_navi_info.rows[row]->col_coord[cur_col] <= cur_col_coodinate) {
+                //check for a match from current column to last column
+                for(col = cur_col; col <= m_key_navi_info.rows[row]->size - 1; col++) {
+                    if (m_key_navi_info.rows[row]->col_coord[col] == cur_col_coodinate) {
+                        break;
+                    } else if (m_key_navi_info.rows[row]->col_coord[col] > cur_col_coodinate) {
+                        col--;
+                        break;
+                    }
+                }
+            } else {
+                //check for a match from current column to first column
+                for(col = cur_col - 1; col >= 0; col--) {
+                    if (m_key_navi_info.rows[row]->col_coord[col] <= cur_col_coodinate) {
+                        break;
+                    }
+                }
+            }
+        } else {
+            for(col = m_key_navi_info.rows[row]->size - 1; col >= 0; col--) {
+                if (m_key_navi_info.rows[row]->col_coord[col] <= cur_col_coodinate) {
+                    break;
+                }
+            }
+        }
+        if (col < 0) {
+            col = 0;
+        } else if (col > m_key_navi_info.rows[row]->size - 1) {
+            col = m_key_navi_info.rows[row]->size - 1;
+        } else {
+        }
+        m_key_navi_info.current_row = row;             
+        m_key_navi_info.current_column = col;
+    }
+    index = m_key_navi_info.rows[m_key_navi_info.current_row]->start_index + m_key_navi_info.current_column;
+    LOGD("Inside get_next_key_index index = %d \n",index);
+    return index;
+}
+
+#ifdef TARGET_EMULATOR
+
+static Ecore_Event_Handler *_sniffer_win_show_handler         = NULL;
+
+/**
+ * ecore event handler deletion
+ */
+static void delete_sniffer_win_show_handler (void)
+{
+    if (_sniffer_win_show_handler) {
+        ecore_event_handler_del (_sniffer_win_show_handler);
+        _sniffer_win_show_handler = NULL;
+    }
+}
+
+/**
+ * callback for window show event (sniffer window)
+ */
+static Eina_Bool x_event_sniffer_window_show_cb (void *data, int ev_type, void *event)
+{
+
+    Evas_Object *evas_window = (Evas_Object *)data;
+    Ecore_X_Window x_window = elm_win_xwindow_get(evas_window);
+    Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
+
+    if (e->win == x_window) {
+
+        LOGD("INSIDE =-=-=-=- x_event_sniffer_window_show_cb, Trying to Grab Key Board : \n");
+        Eina_Bool ret = ecore_x_keyboard_grab(x_window);
+
+        if (EINA_TRUE == ret) {
+            LOGD("Keyboard Grabbed successfully by sniffer\n");
+        } else {
+            LOGD("Failed to Grab keyboard by sniffer\n");
+        }
+        ecore_event_handler_del(_sniffer_win_show_handler);
+        return ECORE_CALLBACK_CANCEL;
+    }
+    LOGD("Wrong window .. renewing callback\n");
+    return ECORE_CALLBACK_RENEW;
+}
+
+/**
+ * sniffer window creation function, the keyboard would be grabbed by this window in case of Tizen Emulator
+ */
+void
+CSCLKeyFocusHandler::create_sniffer_window(void)
+{
+    LOGD("CSCLKeyFocusHandler : INSIDE =-=-=-=- create_sniffer_window : \n");  
+    Evas_Object *win = NULL;
+
+    win = elm_win_add(NULL, "KEY_SNIFFER", ELM_WIN_UTILITY);
+
+    elm_win_borderless_set(win, EINA_TRUE);
+    elm_win_alpha_set(win, EINA_FALSE);
+    elm_win_title_set(win, "KEY_SNIFFER");
+    elm_win_fullscreen_set(win,EINA_FALSE);
+    set_window_accepts_focus(win, FALSE);
+    evas_object_show(win);
+    evas_object_resize(win, 100, 100);
+    m_sniffer = win;
+    _sniffer_win_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_sniffer_window_show_cb, m_sniffer);
+}
+
+void
+CSCLKeyFocusHandler::set_window_accepts_focus(const sclwindow window, sclboolean acceptable)
+{
+    Eina_Bool accepts_focus;
+    Ecore_X_Window_State_Hint initial_state;
+    Ecore_X_Pixmap icon_pixmap;
+    Ecore_X_Pixmap icon_mask;
+    Ecore_X_Window icon_window;
+    Ecore_X_Window window_group;
+    Eina_Bool is_urgent;
+
+    if (window) {
+        ecore_x_icccm_hints_get(elm_win_xwindow_get(static_cast<Evas_Object*>(window)),
+            &accepts_focus, &initial_state, &icon_pixmap, &icon_mask, &icon_window, &window_group, &is_urgent);
+        ecore_x_icccm_hints_set(elm_win_xwindow_get(static_cast<Evas_Object*>(window)),
+            acceptable, initial_state, icon_pixmap, icon_mask, icon_window, window_group, is_urgent);
+    }
+}
+
+
+#endif
+
+
index 5a1220a..1c5d0ae 100644 (file)
@@ -26,6 +26,9 @@
 #include "scluibuilder.h"
 #include "sclres_manager.h"
 #include <assert.h>
+
+//Includes for CSCLKeyFocusHandler
+#include "sclkeyfocushandler.h"
 using namespace scl;
 
 CSCLResourceCache::CSCLResourceCache()
@@ -946,9 +949,15 @@ CSCLResourceCache::recompute_layout(sclwindow window)
                     }
                     memset(pCurButtonContext, 0x00, sizeof(SclButtonContext) * MAX_KEY);
 
+                    CSCLKeyFocusHandler* focus_handler = CSCLKeyFocusHandler::get_instance();
+                    //reset navigation info:mrunal.s
+                    focus_handler->reset_key_navigation_info();
                     for (loop = 0;loop < MAX_KEY;loop++) {
                         SclLayoutKeyCoordinatePointer p = sclres_layout_key_coordinate_pointer_frame[layout][loop];
                         if (p && p->valid) {
+                            //BUILDING KEY NAVIGATION INFO:mrunal.s
+                            focus_handler->update_key_navigation_info(p,loop);
+                            //BUILDING KEY NAVIGATION INFO COMPLETED:mrunal.s
                             (*pCurButtonContext)[loop].used = TRUE;
                             if (popupindex != NOT_USED) {
                                 change_by_privatekey(inputmode, layout, loop, &(mCurPopupLayoutKeyCoordinates[popupindex][loop]));
@@ -989,6 +998,8 @@ CSCLResourceCache::recompute_layout(sclwindow window)
                             (*pCurLayoutKeyCoordinate)[loop].magnifier_offset_y *= utils->get_custom_scale_rate_y();
                         }
                     }
+                    //finalize navigation info:mrunal.s
+                    focus_handler->finalize_key_navigation_info();
                 }
             }
 
index a3ccdbf..15bf49e 100644 (file)
@@ -549,7 +549,7 @@ CSCLUIBuilder::draw_button_label(const sclwindow window, const scldrawctx draw_c
                             label,
                             NULL,
                             (sclint)coordinate->x + deltax + targetaddx,
-                            (sclint)coordinate->y + deltay + targetaddy,
+                            (sclint)coordinate->y + deltax + targetaddy,
                             (sclint)coordinate->width,
                             (sclint)coordinate->height,
                             labelproperties->alignment,
index 98e7c85..b316426 100644 (file)
@@ -91,7 +91,7 @@ void accessibility_changed_cb(keynode_t *key, void* data)
                 if (TTS_ERROR_NONE != r) {
                     LOGD("tts_create FAILED : result(%d)", r);
                 } else {
-                    tts_set_mode (tts, TTS_MODE_SCREEN_READER);
+                    r = tts_set_mode (tts, TTS_MODE_SCREEN_READER);
                 }
                 if (TTS_ERROR_NONE != r) {
                     LOGD("tts_set_mode FAILED : result(%d)", r);