7471e5d0d93c921dd7c0f5536ef6464285cccdd5
[platform/core/uifw/isf.git] / ism / extras / efl_panel / isf_panel_efl.cpp
1 /*
2  * ISF(Input Service Framework)
3  *
4  * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
5  * Copyright (c) 2012-2015 Samsung Electronics Co., Ltd.
6  *
7  * Contact: Haifeng Deng <haifeng.deng@samsung.com>, Jihoon Kim <jihoon48.kim@samsung.com>
8  *
9  * This library is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU Lesser General Public License as published by the
11  * Free Software Foundation; either version 2.1 of the License, or (at your option)
12  * any later version.
13  *
14  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
15  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
16  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17  * License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public License
20  * along with this library; if not, write to the Free Software Foundation, Inc., 51
21  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
22  *
23  */
24
25 #define Uses_SCIM_CONFIG_PATH
26 #define Uses_SCIM_HELPER_MODULE
27 #define Uses_SCIM_PANEL_AGENT
28 #define Uses_SCIM_COMPOSE_KEY
29 #define Uses_SCIM_IMENGINE_MODULE
30 #define WAIT_WM
31
32 #include <sys/wait.h>
33 #include <sys/types.h>
34 #include <sys/time.h>
35 #include <sys/times.h>
36 #include <signal.h>
37 #include <unistd.h>
38 #include <stdlib.h>
39 #include <string.h>
40 #include <malloc.h>
41
42 #include <Eina.h>
43 #include <Ecore.h>
44 #include <glib.h>
45 #include <tzplatform_config.h>
46 #include <system_info.h>
47 #include <cpu-boosting.h>
48
49 #include "scim_private.h"
50 #include "scim.h"
51 #include "scim_stl_map.h"
52 #if ISF_BUILD_CANDIDATE_UI
53 #include <Elementary.h>
54 #include <Evas.h>
55 #ifdef HAVE_ECOREWL
56 #include <Ecore_Wayland.h>
57 #endif /* HAVE_ECOREWL */
58 #ifdef HAVE_FEEDBACK
59 #include <feedback.h>
60 #endif /* HAVE_FEEDBACK */
61 #endif /* CANDIDATE */
62 #ifdef HAVE_VCONF
63 #include <vconf.h>
64 #include <vconf-keys.h>
65 #endif
66 #include <dlog.h>
67 #ifdef HAVE_NOTIFICATION
68 #include <notification.h>
69 #include <notification_internal.h>
70 #endif
71 #ifdef HAVE_PKGMGR_INFO
72 #include <package_manager.h>
73 #include <pkgmgr-info.h>
74 #endif
75 #include <app_control.h>
76 #include <aul.h>
77
78 #include "isf_panel_efl.h"
79 #include "isf_panel_utility.h"
80 #include "isf_query_utility.h"
81 #include "isf_pkg.h"
82 #include "privilege_checker.h"
83 #include "remote_input.h"
84 #include "tizen_profile.h"
85
86 using namespace scim;
87
88
89 /////////////////////////////////////////////////////////////////////////////
90 // Declaration of macro.
91 /////////////////////////////////////////////////////////////////////////////
92 #define EFL_CANDIDATE_THEME1                            (SCIM_DATADIR "/isf_candidate_theme1.edj")
93
94 #define ISF_CANDIDATE_TABLE                             0
95
96 #define ISF_EFL_AUX                                     1
97 #define ISF_EFL_CANDIDATE_0                             2
98 #define ISF_EFL_CANDIDATE_ITEMS                         3
99
100 #define ISE_DEFAULT_HEIGHT_PORTRAIT                     444
101 #define ISE_DEFAULT_HEIGHT_LANDSCAPE                    316
102
103 #define ISF_CANDIDATE_DESTROY_DELAY                     3
104 #define ISF_ISE_HIDE_DELAY                              0.15
105
106 #define ISF_PREEDIT_BORDER                              16
107 #define ISE_LAUNCH_TIMEOUT                              2.0
108
109 #define ISF_POP_PLAY_ICON_FILE                          (SCIM_ICONDIR "/pop_play.png")
110 #define ISF_KEYBOARD_ICON_FILE                          (SCIM_ICONDIR "/noti_keyboard_connected.png")
111 #define ISF_ISE_SELECTOR_ICON_FILE                      "/noti_keyboard.png"
112
113 #define E_PROP_DEVICEMGR_INPUTWIN                       "DeviceMgr Input Window"
114
115
116 /////////////////////////////////////////////////////////////////////////////
117 // Declaration of external variables.
118 /////////////////////////////////////////////////////////////////////////////
119 extern MapStringVectorSizeT         _groups;
120 extern std::vector<ImeInfoDB>       _ime_info;
121
122 #if ISF_BUILD_CANDIDATE_UI
123 CommonLookupTable       g_isf_candidate_table;
124 #endif
125
126 /////////////////////////////////////////////////////////////////////////////
127 // Declaration of internal data types.
128 /////////////////////////////////////////////////////////////////////////////
129 typedef enum _WINDOW_STATE {
130     WINDOW_STATE_HIDE = 0,
131     WINDOW_STATE_WILL_HIDE,
132     WINDOW_STATE_WILL_SHOW,
133     WINDOW_STATE_SHOW,
134     WINDOW_STATE_ON,
135 } WINDOW_STATE;
136
137 typedef struct NotiData
138 {
139     String title;
140     String content;
141     String icon;
142     String launch_app;
143     int noti_id;
144 } NotificationData;
145
146 typedef std::vector < std::pair <String, uint32> >    VectorPairStringUint32;
147
148 /////////////////////////////////////////////////////////////////////////////
149 // Declaration of internal functions.
150 /////////////////////////////////////////////////////////////////////////////
151
152 #ifdef HAVE_ECOREX
153 static void       efl_set_transient_for_app_window     (Ecore_X_Window window);
154 #endif
155
156 static int        efl_get_ise_window_angle             (void);
157 static void       set_soft_candidate_geometry(int x, int y, int width, int height);
158
159 #if ISF_BUILD_CANDIDATE_UI
160 static Evas_Object *efl_create_window(const char *strWinName, const char *strEffect);
161 static int        efl_get_app_window_angle(void);
162
163 #ifdef HAVE_ECOREX
164 static int        efl_get_quickpanel_window_angle      (void);
165 #endif /* HAVE_ECOREX */
166
167 static int        ui_candidate_get_valid_height        (void);
168 static void       ui_candidate_hide                    (bool bForce, bool bSetVirtualKbd = true, bool will_hide = false);
169 static void       ui_destroy_candidate_window          (void);
170 static void       ui_settle_candidate_window           (void);
171 static void       ui_candidate_show                    (bool bSetVirtualKbd = true);
172 static void       ui_create_candidate_window           (void);
173 static void       update_table                         (int table_type, const LookupTable &table);
174 static void       ui_candidate_window_close_button_cb  (void *data, Evas *e, Evas_Object *button, void *event_info);
175
176 static void       set_highlight_color                  (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack);
177 static void       ui_tts_focus_rect_hide               (void);
178
179 static Evas_Object *get_candidate                      (const String& str, Evas_Object *parent, int *total_width, uint32 ForeGround, uint32 BackGround, bool HighLight, bool SetBack, int item_num, int item);
180 static bool       tokenize_tag                         (const String& str, struct image *image_data);
181 #endif /* CANDIDATE */
182
183 static void       launch_default_soft_keyboard         (keynode_t *key = NULL, void* data = NULL);
184
185 /* PanelAgent related functions */
186 static bool       initialize_panel_agent               (const ConfigPointer& config, const String &display, bool resident);
187
188 static void       slot_focus_in                        (void);
189 static void       slot_focus_out                       (void);
190 static void       slot_expand_candidate                (void);
191 static void       slot_contract_candidate              (void);
192 static void       slot_set_candidate_style             (int portrait_line, int mode);
193 static void       slot_update_input_context            (int type, int value);
194 static void       slot_update_ise_geometry             (int x, int y, int width, int height);
195 static void       slot_update_spot_location            (int x, int y, int top_y);
196 static void       slot_update_factory_info             (const PanelFactoryInfo &info);
197 #if ISF_BUILD_CANDIDATE_UI
198 static void       slot_show_preedit_string             (void);
199 static void       slot_show_aux_string                 (void);
200 #endif
201 static void       slot_show_candidate_table            (void);
202 static void       slot_hide_preedit_string             (void);
203 static void       slot_hide_aux_string                 (void);
204 static void       slot_hide_candidate_table            (void);
205 static void       slot_update_preedit_string           (const String &str, const AttributeList &attrs, int caret);
206 static void       slot_update_preedit_caret            (int caret);
207 static void       slot_update_aux_string               (const String &str, const AttributeList &attrs);
208 static void       slot_update_candidate_table          (const LookupTable &table);
209 static void       slot_select_candidate                (int index);
210 static void       slot_set_active_ise                  (const String &uuid, bool changeDefault);
211 static bool       slot_get_ise_list                    (std::vector<String> &list);
212 static bool       slot_get_all_helper_ise_info         (HELPER_ISE_INFO &info);
213 static void       slot_set_has_option_helper_ise_info  (const String &appid, bool has_option);
214 static void       slot_set_enable_helper_ise_info      (const String &appid, bool is_enabled);
215 static void       slot_show_helper_ise_list            (void);
216 static void       slot_show_helper_ise_selector        (void);
217 static bool       slot_is_helper_ise_enabled           (String appid, int &enabled);
218 static bool       slot_get_ise_information             (String uuid, String &name, String &language, int &type, int &option, String &module_name);
219 static bool       slot_get_keyboard_ise_list           (std::vector<String> &name_list);
220 static void       slot_get_language_list               (std::vector<String> &name);
221 static void       slot_get_all_language                (std::vector<String> &lang);
222 static void       slot_get_ise_language                (char *name, std::vector<String> &list);
223 static bool       slot_get_ise_info                    (const String &uuid, ISE_INFO &info);
224 static void       slot_get_candidate_geometry          (struct rectinfo &info);
225 static void       slot_get_input_panel_geometry        (struct rectinfo &info);
226 static void       slot_get_recent_ise_geometry         (int angle, struct rectinfo &info);
227 static bool       slot_check_privilege_by_sockfd       (int client_id, String privilege);
228 static void       slot_set_keyboard_ise                (const String &uuid);
229 static void       slot_get_keyboard_ise                (String &ise_name, String &ise_uuid);
230 static void       slot_accept_connection               (int fd);
231 static void       slot_close_connection                (int fd);
232 static void       slot_exit                            (void);
233
234 static void       slot_register_helper                 (int id, const HelperInfo& info);
235 static void       slot_register_helper_properties      (int id, const PropertyList &props);
236 static void       slot_show_ise                        (void);
237 static void       slot_hide_ise                        (void);
238
239 static void       slot_will_hide_ack                   (void);
240 static void       slot_candidate_will_hide_ack         (void);
241
242 static void       slot_set_keyboard_mode               (int mode);
243 static void       slot_get_ise_state                   (int &state);
244 static void       slot_start_default_ise               (void);
245 static void       slot_stop_default_ise                (bool is_exist);
246 static void       slot_run_helper                      (const String &uuid, const String &config, const String &display);
247 static bool       slot_launch_option_application       (String ime_appid);
248 static bool       slot_get_ise_setting_appid           (String ime_appid, String &ime_setting_appid);
249 static void       slot_set_preloading_ise              (bool preloading);
250
251 #if ENABLE_REMOTE_INPUT
252 static void       slot_send_remote_input_message       (const String &msg, bool len);
253 static void       slot_recv_remote_surrounding_text    (int cursor, const String &text);
254 #endif
255
256 #ifdef HAVE_ECOREX
257 static Eina_Bool  efl_create_control_window            (void);
258 static Ecore_X_Window efl_get_app_window               (void);
259 static Ecore_X_Window efl_get_quickpanel_window        (void);
260 static Ecore_X_Window efl_get_global_navigation_window (void);
261 #endif
262
263 static void       change_keyboard_mode                 (TOOLBAR_MODE_T mode);
264 static unsigned int get_ise_index                      (const String uuid);
265 static bool       set_active_ise                       (const String &uuid, bool launch_ise);
266 static bool       update_ise_list                      (std::vector<String> &list);
267 static void       update_ise_locale                    (const char *lang = NULL);
268 #ifdef HAVE_NOTIFICATION
269 static void       delete_notification                  (NotificationData *noti_data);
270 static void       create_notification                  (NotificationData *noti_data);
271 static void       show_ime_selector_notification       (void);
272 #endif
273 static void       set_language_and_locale              (const char *lang_str);
274 static bool       app_control_launch                   (const char *app_id);
275 static void       terminate_active_ise                 (const String uuid);
276 static void       set_cpu_boosting                     (void);
277 static void       clear_cpu_boosting                   (void);
278
279 /////////////////////////////////////////////////////////////////////////////
280 // Declaration of internal variables.
281 /////////////////////////////////////////////////////////////////////////////
282 #if ISF_BUILD_CANDIDATE_UI
283 static Evas_Object       *_candidate_window                 = 0;
284 static Evas_Object       *_candidate_area_1                 = 0;
285 static Evas_Object       *_candidate_area_2                 = 0;
286 static Evas_Object       *_candidate_bg                     = 0;
287 static Evas_Object       *_candidate_0_scroll               = 0;
288 static Evas_Object       *_candidate_scroll                 = 0;
289 static Evas_Object       *_scroller_bg                      = 0;
290 static Evas_Object       *_candidate_0_table                = 0;
291 static Evas_Object       *_candidate_table                  = 0;
292 static Evas_Object       *_candidate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
293 static Evas_Object       *_candidate_text [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
294 static Evas_Object       *_candidate_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
295 static Evas_Object       *_candidate_pop_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
296 static Evas_Object       *_seperate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
297 static Evas_Object       *_seperate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
298 static Evas_Object       *_line_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
299 static Evas_Object       *_line_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
300 static Evas_Object       *_more_btn                         = 0;
301 static Evas_Object       *_close_btn                        = 0;
302 static bool               _candidate_show_requested         = false;
303 #endif /* CANDIDATE */
304 static bool               _updated_hide_state_geometry      = false;
305 #if ISF_BUILD_CANDIDATE_UI
306 static int                _candidate_x                      = 0;
307 static int                _candidate_y                      = 0;
308 static int                _candidate_width                  = 0;
309 static int                _candidate_height                 = 0;
310 static int                _soft_candidate_width             = 0;
311 static int                _soft_candidate_height            = 0;
312 static int                _candidate_valid_height           = 0;
313
314 static bool               _candidate_area_1_visible         = false;
315 static bool               _candidate_area_2_visible         = false;
316 static bool               _aux_area_visible                 = false;
317 #endif /* CANDIDATE */
318
319 static ISF_CANDIDATE_MODE_T          _candidate_mode        = SOFT_CANDIDATE_WINDOW;
320 static ISF_CANDIDATE_PORTRAIT_LINE_T _candidate_port_line   = ONE_LINE_CANDIDATE;
321
322 #if ISF_BUILD_CANDIDATE_UI
323 static int                _candidate_port_width             = 480;
324 static int                _candidate_port_height_min        = 76;
325 static int                _candidate_port_height_min_2      = 150;
326 static int                _candidate_port_height_max        = 286;
327 static int                _candidate_port_height_max_2      = 350;
328 static int                _candidate_land_width             = 784;
329 static int                _candidate_land_height_min        = 84;
330 static int                _candidate_land_height_min_2      = 168;
331 static int                _candidate_land_height_max        = 150;
332 static int                _candidate_land_height_max_2      = 214;
333 static int                _candidate_area_1_pos [2]         = {0, 2};
334 static int                _more_btn_pos [4]                 = {369, 11, 689, 11};
335 static int                _close_btn_pos [4]                = {362, 211, 682, 75};
336 static int                _more_btn_width                   = 80;
337 static int                _more_btn_height                  = 64;
338
339 static int                _h_padding                        = 4;
340 static int                _v_padding                        = 2;
341 static int                _item_min_width                   = 99;
342 static int                _item_min_height                  = 82;
343
344 static int                _candidate_scroll_0_width_min     = 350;
345 static int                _candidate_scroll_0_width_max     = 670;
346
347 static int                _candidate_scroll_width           = 453;
348 static int                _candidate_scroll_width_min       = 453;
349 static int                _candidate_scroll_width_max       = 663;
350 static int                _candidate_scroll_height_min      = 124;
351 static int                _candidate_scroll_height_max      = 190;
352
353 const  int                MORE_BUTTON_INDEX                 = -1;
354 const  int                CLOSE_BUTTON_INDEX                = -2;
355 static uint32             _candidate_display_number         = 0;
356 static std::vector<uint32> _candidate_row_items;
357 static Evas_Object       *_tts_focus_rect                   = 0;
358 static bool               _wait_stop_event                  = false;
359
360 static Evas_Object       *_preedit_window                   = 0;
361 static Evas_Object       *_preedit_text                     = 0;
362 static int                _preedit_width                    = 100;
363 static int                _preedit_height                   = 54;
364
365 static Evas_Object       *_aux_area                         = 0;
366 static Evas_Object       *_aux_line                         = 0;
367 static Evas_Object       *_aux_table                        = 0;
368 static int                _aux_height                       = 0;
369 static int                _aux_port_width                   = 444;
370 static int                _aux_land_width                   = 764;
371 static std::vector<Evas_Object *> _aux_items;
372 static std::vector<Evas_Object *> _aux_seperates;
373
374 static Evas_Object       *_tmp_preedit_text                 = 0;
375 static Evas_Object       *_tmp_aux_text                     = 0;
376 static Evas_Object       *_tmp_candidate_text               = 0;
377
378 static int                _spot_location_x                  = -1;
379 static int                _spot_location_y                  = -1;
380 static int                _spot_location_top_y              = -1;
381 static int                _candidate_angle                  = 0;
382 static int                _ise_width = 0;
383 static int                _ise_height = 0;
384 #endif /* CANDIDATE */
385
386 static int                _ise_angle                        = -1;
387 static int                _ise_x                            = 0;
388 static int                _ise_y                            = 0;
389 static WINDOW_STATE       _ise_state                        = WINDOW_STATE_HIDE;
390 static WINDOW_STATE       _candidate_state                  = WINDOW_STATE_HIDE;
391
392 #if ISF_BUILD_CANDIDATE_UI
393 static int                _indicator_height                 = 0;//24;
394 static int                _screen_width                     = 720;
395 static int                _screen_height                    = 1280;
396 static float              _width_rate                       = 1.0;
397 static float              _height_rate                      = 1.0;
398 static int                _blank_width                      = 30;
399
400 static String             _candidate_name                   = String ("candidate");
401 static String             _candidate_edje_file              = String (EFL_CANDIDATE_THEME1);
402
403 static String             _candidate_font_name              = String ("Tizen");
404 static int                _candidate_font_size              = 38;
405 static int                _aux_font_size                    = 38;
406 static int                _click_object                     = 0;
407 static int                _click_down_pos [2]               = {0, 0};
408 static int                _click_up_pos [2]                 = {0, 0};
409 static bool               _is_click                         = true;
410 #endif /* CANDIDATE */
411 static String             _initial_ise_uuid                 = String ("");
412 static String             _locale_string                    = String ("");
413 static ConfigPointer      _config;
414 static Connection         _config_connection;
415
416 static InfoManager       *_info_manager                      = 0;
417
418 static clock_t            _clock_start;
419
420 #if ISF_BUILD_CANDIDATE_UI
421 static Ecore_Timer       *_check_size_timer                 = NULL;
422 static Ecore_Timer       *_longpress_timer                  = NULL;
423 static Ecore_Timer       *_destroy_timer                    = NULL;
424 #endif /* CANDIDATE */
425 #if ISF_BUILD_CANDIDATE_UI
426 static Ecore_Timer       *_candidate_hide_timer             = NULL;
427 #endif /* CANDIDATE */
428 static Ecore_Timer       *_ise_hide_timer                   = NULL;
429
430 #ifdef HAVE_ECOREX
431 static Ecore_X_Window     _ise_window                       = 0;
432 static Ecore_X_Window     _app_window                       = 0;
433 static Ecore_X_Window     _control_window                   = 0;
434 static Ecore_X_Window     _input_win                        = 0;
435 #endif
436
437 #ifdef HAVE_PKGMGR_INFO
438 static package_manager_h    pkgmgr                          = NULL;
439 static VectorPairStringUint32   g_pkgids_to_be_uninstalled;
440 static Ecore_Timer    *g_release_uninstalled_ime_info_timer = NULL;
441 static String               g_stopped_helper_pkgid          = "";
442 static Ecore_Timer          *g_start_default_helper_timer   = NULL;
443 static VectorPairStringUint32   g_pkgids_to_be_updated_and_installed;
444 static String               g_updated_helper_pkgid          = "";
445 #endif
446
447 static bool               _launch_ise_on_request            = false;
448 static bool               _auto_destroy_ise                 = false;
449 static bool               _soft_keyboard_launched           = false;
450 static bool               _focus_in                         = false;
451 static bool               _enable_auto_restart              = true;
452 static bool               _preloading_ise                   = true;
453
454 #if ISF_BUILD_CANDIDATE_UI
455 static bool               candidate_expanded                = false;
456 static int                _candidate_image_count            = 0;
457 static int                _candidate_text_count             = 0;
458 static int                _candidate_pop_image_count        = 0;
459 static int                candidate_image_height            = 38;
460 static int                candidate_play_image_width_height = 19;
461
462 static const int          CANDIDATE_TEXT_OFFSET             = 2;
463
464 static double             _app_scale                        = 1.0;
465 static double             _system_scale                     = 1.0;
466 #endif /* CANDIDATE */
467
468 #ifdef HAVE_NOTIFICATION
469 static NotificationData hwkbd_module_noti                   = {"Input detected from hardware keyboard", "Tap to use virtual keyboard", ISF_KEYBOARD_ICON_FILE, "", 0};
470 static NotificationData ise_selector_module_noti            = {"Select input method", "", "", "", 0};
471 #endif
472
473 #if ISF_BUILD_CANDIDATE_UI
474
475 #ifdef HAVE_FEEDBACK
476 static bool               feedback_initialized              = false;
477 #endif
478 #endif /* CANDIDATE */
479
480 #if ENABLE_REMOTE_INPUT
481 static Remote_Input*      remote_input_impl                 = NULL;
482 static bool               launch_remote_input               = false;
483 #endif
484
485 #if ISF_BUILD_CANDIDATE_UI
486 #ifdef HAVE_ECOREX
487 static Ecore_Event_Handler *_candidate_show_handler         = NULL;
488 #endif
489 #endif /* CANDIDATE */
490
491 static String ime_selector_app = "";
492 static String ime_list_app = "";
493
494 static Ecore_Timer       *_ise_check_pid_alive_timer            = NULL;
495 static const double      _ise_check_pid_alive_time              = 3.0f;
496 static String            _ise_check_pid_alive_uuid;
497
498 static Ecore_Timer       *g_monitor_user_data_path_timer = NULL;
499
500 #if ISF_BUILD_CANDIDATE_UI
501 enum {
502     EMOJI_IMAGE_WIDTH = 0,
503     EMOJI_IMAGE_HEIGHT,
504     EMOJI_IMAGE_KIND,
505     EMOJI_IMAGE_TAG_FLAG,
506     EMOJI_IMAGE_POP_FLAG,
507     EMOJI_IMAGE_END
508 };
509
510 struct image
511 {
512     String path;
513     int emoji_option[EMOJI_IMAGE_END];
514 };
515 #endif
516
517 /* This structure stores the geometry information reported by ISE */
518 struct GeometryCache
519 {
520     bool valid;                /* Whether this information is currently valid */
521     int angle;                 /* For which angle this information is useful */
522     struct rectinfo geometry;  /* Geometry information */
523 };
524
525 static struct GeometryCache _ise_reported_geometry          = {0, 0, {0, 0, 0, 0}};
526 static struct GeometryCache _portrait_recent_ise_geometry   = {0, 0, {0, 0, 0, 0}};
527 static struct GeometryCache _landscape_recent_ise_geometry  = {0, 0, {0, 0, 0, 0}};
528
529 #ifdef HAVE_ECOREX
530 static void get_input_window (void)
531 {
532     int win_ret = -1;
533     Ecore_X_Atom atom = 0;
534
535     if (_input_win == 0) {
536         atom = ecore_x_atom_get (E_PROP_DEVICEMGR_INPUTWIN);
537         win_ret = ecore_x_window_prop_window_get (ecore_x_window_root_first_get (), atom, &_input_win, 1);
538         if (_input_win == 0 || win_ret < 1) {
539             LOGW ("Input window is NULL!");
540         } else {
541             ecore_x_event_mask_set (_input_win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
542         }
543     }
544 }
545 #endif
546
547 static int pkgmgr_get_appinfo (const char *appid, pkgmgrinfo_appinfo_h *handle)
548 {
549     int ret = 0;
550     /* Try to get in global packages */
551     ret = pkgmgrinfo_appinfo_get_appinfo (appid, handle);
552     if (ret != PMINFO_R_OK) {
553         LOGW ("[pkgmgrinfo_appinfo_get_appinfo] appid : '%s', ret : %d, uid : %d", appid, ret, getuid ());
554         /* Try to get in user packages */
555         ret = pkgmgrinfo_appinfo_get_usr_appinfo (appid, getuid (), handle);
556         if (ret != PMINFO_R_OK)
557             LOGW ("[pkgmgrinfo_appinfo_get_usr_appinfo] appid : '%s', ret : %d", appid, ret);
558     }
559
560     return ret;
561 }
562
563 #ifdef HAVE_NOTIFICATION
564 static void delete_notification (NotificationData *noti_data)
565 {
566     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
567
568     if (!_MOBILE && !_COMMON) return;
569
570     if (noti_data->noti_id != 0) {
571         notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
572         LOGD ("deleted notification : %s", noti_data->launch_app.c_str ());
573         noti_data->noti_id = 0;
574     }
575 }
576
577 static void create_notification (NotificationData *noti_data)
578 {
579     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
580
581     notification_h notification = NULL;
582     int ret;
583
584     if (!_MOBILE && !_COMMON) return;
585
586     if (noti_data->noti_id != 0) {
587         notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
588         noti_data->noti_id = 0;
589     }
590
591     notification = notification_create (NOTIFICATION_TYPE_ONGOING);
592     if (notification != NULL) {
593         notification_set_pkgname (notification, "isf-panel-efl");
594         notification_set_layout (notification, NOTIFICATION_LY_ONGOING_EVENT);
595         notification_set_image (notification, NOTIFICATION_IMAGE_TYPE_ICON, noti_data->icon.c_str());
596         notification_set_text (notification, NOTIFICATION_TEXT_TYPE_TITLE, _(noti_data->title.c_str()), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
597         notification_set_text (notification, NOTIFICATION_TEXT_TYPE_CONTENT, _(noti_data->content.c_str ()), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
598         notification_set_display_applist (notification, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
599
600         app_control_h service = NULL;
601         if (app_control_create (&service) == APP_CONTROL_ERROR_NONE) {
602             app_control_set_operation (service, APP_CONTROL_OPERATION_DEFAULT);
603             app_control_set_app_id (service, noti_data->launch_app.c_str ());
604
605             ret = notification_set_launch_option (notification, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)service);
606             if (ret != NOTIFICATION_ERROR_NONE) {
607                 LOGW ("Failed to set launch option. error code : %d", ret);
608             }
609             ret = notification_insert (notification, &noti_data->noti_id);
610             if (ret != NOTIFICATION_ERROR_NONE) {
611                 LOGW ("Failed to insert notification. error code : %d", ret);
612             }
613             app_control_destroy (service);
614         }
615         else {
616             LOGW ("Failed to create appcontrol");
617         }
618         notification_free (notification);
619     }
620     else {
621         LOGW ("Failed to create notification");
622     }
623 }
624 #endif /* HAVE_NOTIFICATION */
625
626 #if ISF_BUILD_CANDIDATE_UI
627 static bool tokenize_tag (const String& str, struct image *image_token)
628 {
629     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
630     if (str.length () <= 0) {
631         LOGW ("str is empty!!!");
632         return false;
633     }
634
635     char **tag_str = NULL;
636     int i = 0;
637     tag_str = eina_str_split (str.c_str (), "\u3013", 0);
638
639     if (!tag_str)
640         return false;
641
642     for (i = 0; tag_str [i]; i++) {
643         if (i == 0) {
644             if (str.length () == strlen (tag_str[i])) {
645                 if (tag_str) {
646                     if (tag_str[0])
647                         free (tag_str[0]);
648
649                     free (tag_str);
650                 }
651                 return false;
652             }
653
654             image_token->path = String (tag_str[i]);
655         } else {
656             if (i - 1 < EMOJI_IMAGE_END)
657                 image_token->emoji_option [i - 1] = atoi (tag_str[i]);
658             else
659                 LOGW ("emoji option is more than EMOJI_IMAGE_END!!!");
660         }
661     }
662
663     if (tag_str[0])
664         free (tag_str[0]);
665
666     free (tag_str);
667
668     return true;
669 }
670
671 static Evas_Object* get_candidate (const String& str, Evas_Object *parent, int *total_width, uint32 ForeGround, uint32 BackGround, bool HighLight, bool SetBack, int item_num, int item_index)
672 {
673     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
674
675     struct image image_data;
676     int object_width = 0, text_width = 0, image_width = 0, image_height = 0, max_width = 0, button_width = 0;
677     int i = 0, j = 0;
678     int image_get_width = 0, image_get_height = 0;
679     char image_key [10] = {0, };
680     char **splited_string = NULL;
681     char **sub_splited_string = NULL;
682     double image_rate = 0.0;
683     bool tokenize_result = false;
684     bool candidate_is_long = false;
685
686     Evas_Object *candidate_object_table = NULL;
687     Evas_Object *candidate_object_table_bg_rect = NULL;
688     Evas_Object *candidate_left_padding = NULL;
689
690     candidate_object_table = elm_table_add (parent);
691
692     candidate_left_padding = evas_object_rectangle_add (evas_object_evas_get (parent));
693     evas_object_size_hint_weight_set (candidate_left_padding, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
694     evas_object_size_hint_align_set (candidate_left_padding, EVAS_HINT_FILL, EVAS_HINT_FILL);
695     evas_object_size_hint_min_set (candidate_left_padding, _blank_width, 1);
696     evas_object_color_set (candidate_left_padding, 0, 0, 0, 0);
697     elm_table_pack (candidate_object_table, candidate_left_padding, 0, 0, _blank_width, 1);
698     evas_object_show (candidate_left_padding);
699
700     object_width += _blank_width;
701     if (item_num > 1 && item_index == 0)
702         button_width = 92 * _width_rate;
703     else
704         button_width = 0;
705
706     splited_string = eina_str_split (str.c_str (), "\uE000", 0);
707     if (splited_string) {
708         for (i = 0; splited_string [i]; i++) {
709             if (candidate_is_long)
710                 break;
711             sub_splited_string = eina_str_split (splited_string [i], "\uE001", 0);
712             if (sub_splited_string) {
713                 for (j = 0; sub_splited_string [j]; j++) {
714                     if (candidate_is_long)
715                         break;
716                     tokenize_result = tokenize_tag (sub_splited_string [j], &image_data);
717                     if (tokenize_result && _candidate_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
718                         _candidate_image [_candidate_image_count] = elm_image_add (parent);
719                         snprintf (image_key, sizeof (image_key), "%d", _candidate_image_count);
720                         elm_image_file_set (_candidate_image [_candidate_image_count], image_data.path.c_str (), image_key);
721                         elm_image_animated_set (_candidate_image [_candidate_image_count], EINA_TRUE);
722                         elm_image_animated_play_set (_candidate_image [_candidate_image_count], EINA_TRUE);
723                         elm_image_object_size_get (_candidate_image [_candidate_image_count], &image_get_width, &image_get_height);
724                         LOGD ("image_path=%s, key=%s", image_data.path.c_str (), image_key);
725
726                         if (image_get_height > image_get_width)
727                             image_rate = ((double)candidate_image_height / (double)image_get_width);
728                         else
729                             image_rate = ((double)candidate_image_height / (double)image_get_height);
730
731                         image_width = (int)((double)image_get_width * image_rate);
732                         image_height = candidate_image_height;
733
734                         if (_candidate_angle == 90 || _candidate_angle == 270)
735                             max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
736                         else
737                             max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
738
739                         if (image_width > max_width) {
740                             Evas_Object *candidate_end = edje_object_add (evas_object_evas_get (parent));
741                             edje_object_file_set (candidate_end, _candidate_edje_file.c_str (), _candidate_name.c_str ());
742                             evas_object_show (candidate_end);
743                             edje_object_part_text_set (candidate_end, "candidate", "...");
744                             edje_object_scale_set (_candidate_text [_candidate_text_count], _height_rate);
745
746                             text_width = max_width;
747                             evas_object_size_hint_min_set (candidate_end, text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
748                             if (HighLight || SetBack) {
749                                 set_highlight_color (candidate_end, ForeGround, BackGround, SetBack);
750                             }
751                             elm_table_pack (candidate_object_table, candidate_end, object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
752                             object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
753
754                             if (_candidate_image [_candidate_image_count]) {
755                                 evas_object_del (_candidate_image [_candidate_image_count]);
756                                 _candidate_image [_candidate_image_count] = NULL;
757                             }
758                             candidate_is_long = true;
759                             break;
760                         }
761
762                         evas_object_resize (_candidate_image [_candidate_image_count], image_width, image_height);
763                         evas_object_show (_candidate_image [_candidate_image_count]);
764                         evas_object_size_hint_min_set (_candidate_image [_candidate_image_count], image_width, image_height);
765
766                         elm_table_pack (candidate_object_table, _candidate_image [_candidate_image_count], object_width, 1, image_width, image_height);
767                         object_width += image_width;
768                         _candidate_image_count++;
769
770                         if (image_data.emoji_option [EMOJI_IMAGE_POP_FLAG] == 1 && image_width > 0 &&  _candidate_pop_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
771                             _candidate_pop_image [_candidate_pop_image_count] = elm_image_add (parent);
772                             elm_image_file_set (_candidate_pop_image [_candidate_pop_image_count], ISF_POP_PLAY_ICON_FILE, image_key);
773                             evas_object_resize (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
774                             evas_object_show (_candidate_pop_image [_candidate_pop_image_count]);
775                             evas_object_size_hint_min_set (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
776
777                             elm_table_pack (candidate_object_table, _candidate_pop_image [_candidate_pop_image_count],
778                                     object_width - candidate_play_image_width_height, image_height - candidate_play_image_width_height - 2,
779                                     candidate_play_image_width_height, candidate_play_image_width_height);
780
781                             _candidate_pop_image_count++;
782                         }
783
784                     } else if (strlen (sub_splited_string [j]) > 0 && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
785                         _candidate_text [_candidate_text_count] = edje_object_add (evas_object_evas_get (parent));
786                         edje_object_file_set (_candidate_text [_candidate_text_count], _candidate_edje_file.c_str (), _candidate_name.c_str ());
787                         evas_object_show (_candidate_text [_candidate_text_count]);
788                         edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", sub_splited_string [j]);
789                         edje_object_text_class_set (_candidate_text [_candidate_text_count], "tizen",
790                                 _candidate_font_name.c_str (), _candidate_font_size);
791                         evas_object_text_text_set (_tmp_candidate_text, sub_splited_string [j]);
792                         evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &text_width, NULL);
793
794                         if (_candidate_angle == 90 || _candidate_angle == 270)
795                             max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
796                         else
797                             max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
798
799                         if (text_width > max_width) {
800                             candidate_is_long = true;
801                             /* In order to avoid overlap issue, calculate show_string */
802                             String show_string = String (sub_splited_string [j]);
803                             int    show_length = text_width;
804                             while (show_length > max_width && show_string.length () > 1) {
805                                 show_string = show_string.substr (0, show_string.length () - 1);
806                                 evas_object_text_text_set (_tmp_candidate_text, (show_string + String ("...")).c_str ());
807                                 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &show_length, NULL);
808                             }
809                             edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", (show_string + String ("...")).c_str ());
810                             text_width = max_width;
811                         }
812
813                         evas_object_size_hint_min_set (_candidate_text [_candidate_text_count], text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
814                         if (HighLight || SetBack) {
815                             set_highlight_color (_candidate_text [_candidate_text_count], ForeGround, BackGround, SetBack);
816                         }
817                         elm_table_pack (candidate_object_table, _candidate_text [_candidate_text_count], object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
818                         object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
819                         _candidate_text_count++;
820                     }
821                 }
822             }
823         }
824
825         if (splited_string [0])
826             free (splited_string [0]);
827
828         free (splited_string);
829     }
830
831     if (sub_splited_string) {
832         if (sub_splited_string [0])
833             free (sub_splited_string [0]);
834
835         free (sub_splited_string);
836     }
837
838     *total_width = object_width + _blank_width;
839
840     candidate_object_table_bg_rect = edje_object_add (evas_object_evas_get (parent));
841     edje_object_file_set (candidate_object_table_bg_rect, _candidate_edje_file.c_str (), "candidate_object_table");
842     evas_object_size_hint_weight_set (candidate_object_table_bg_rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
843     evas_object_size_hint_align_set (candidate_object_table_bg_rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
844     evas_object_size_hint_min_set (candidate_object_table_bg_rect, *total_width, _item_min_height);
845     elm_table_pack (candidate_object_table, candidate_object_table_bg_rect, 0, 0, *total_width, _item_min_height);
846     evas_object_show (candidate_object_table_bg_rect);
847
848     evas_object_size_hint_align_set (candidate_object_table, EVAS_HINT_FILL, EVAS_HINT_FILL);
849     evas_object_size_hint_weight_set (candidate_object_table, EVAS_HINT_EXPAND, 0.0);
850
851     return candidate_object_table;
852 }
853 #endif /* CANDIDATE */
854
855 /////////////////////////////////////////////////////////////////////////////
856 // Implementation of internal functions.
857 /////////////////////////////////////////////////////////////////////////////
858 /**
859  * @brief Print system time point for panel performance.
860  *
861  * @param strInfo The output information.
862  */
863 static void check_time (const char *strInfo)
864 {
865     gettime (_clock_start, strInfo);
866     ISF_LOG ("%s ppid=%d pid=%d\n", strInfo, getppid (), getpid ());
867 }
868
869 /**
870  * @brief Flush memory for elm.
871  *
872  * @return void
873  */
874 static void flush_memory (void)
875 {
876 #if ISF_BUILD_CANDIDATE_UI
877     elm_cache_all_flush ();
878 #endif
879     malloc_trim (0);
880 }
881
882 #if ISF_BUILD_CANDIDATE_UI
883 /**
884  * @brief Get ISE geometry information.
885  *        Returns the "expected" ISE geometry when kbd_state is ON, otherwise w/h set to 0
886  *
887  * @param info The data is used to store ISE position and size.
888  * @param kbd_state The keyboard state.
889  */
890 static struct rectinfo get_ise_geometry ()
891 {
892     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
893
894     struct rectinfo info = {0, 0, 0, 0};
895
896 #ifdef HAVE_ECOREX
897     int w = 0, h = 0;
898     Ecore_X_Window gnb_win = efl_get_global_navigation_window ();
899     if (gnb_win > 0)
900         ecore_x_window_size_get (gnb_win, &w, &h);
901 #endif
902
903     int win_w = _screen_width, win_h = _screen_height;
904     int angle = (_ise_angle == -1) ? efl_get_app_window_angle () : _ise_angle;
905
906 #ifdef HAVE_ECOREX
907     /* The height of global navigation bar */
908     int gnb_height = h;
909
910     if (angle == 90 || angle == 270) {
911         win_w = _screen_height;
912         win_h = _screen_width;
913         gnb_height = w;
914     }
915 #endif
916
917     /* If we have geometry reported by ISE, use the geometry information */
918     if (_ise_reported_geometry.valid && _ise_reported_geometry.angle == angle) {
919         info = _ise_reported_geometry.geometry;
920         /* But still, if the current ISE is not in SHOW state, set w/h to 0 */
921         if (_ise_state != WINDOW_STATE_SHOW) {
922             info.pos_y = (win_h > win_w) ? win_h : win_w;
923             info.width = 0;
924             info.height = 0;
925         }
926     } else {
927         /* READ ISE's SIZE HINT HERE */
928 #ifdef HAVE_ECOREX
929         /*
930         int pos_x, pos_y, width, height;
931         if (ecore_x_e_window_rotation_geometry_get (_ise_window, angle,
932                 &pos_x, &pos_y, &width, &height)) {
933             info.pos_x = pos_x;
934             info.pos_y = pos_y;
935
936             if (angle == 90 || angle == 270) {
937                 info.width = height;
938                 info.height = width;
939             } else {
940                 info.width = width;
941                 info.height = height;
942             }
943
944             info.pos_x = (int)info.width > win_w ? 0 : (win_w - info.width) / 2;
945             if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
946                 info.pos_x = 0;
947                 info.pos_y = (win_h > win_w) ? win_h : win_w;
948                 info.width = 0;
949                 info.height = 0;
950             } else {
951                 if (_ise_state == WINDOW_STATE_SHOW) {
952                     info.pos_y = win_h - info.height - gnb_height;
953                 } else {
954                     info.pos_y = (win_h > win_w) ? win_h : win_w;
955                     info.width = 0;
956                     info.height = 0;
957                 }
958             }
959
960             LOGD ("angle : %d, w_angle : %d, mode : %d, Geometry : %d %d %d %d",
961                     angle, _ise_angle,
962                     _info_manager->get_current_toolbar_mode (),
963                     info.pos_x, info.pos_y, info.width, info.height);
964         } else {
965             pos_x = 0;
966             pos_y = 0;
967             width = 0;
968             height = 0;
969         }
970         */
971 #else
972         // FIXME: Get the ISE's SIZE.
973         info.pos_x = 0;
974         info.pos_y = 0;
975         info.width = 0;
976         info.height = 0;
977 #endif
978     }
979
980     _ise_width  = info.width;
981     _ise_height = info.height;
982
983     return info;
984 }
985 #endif /* CANDIDATE */
986
987 #ifdef HAVE_ECOREX
988 /**
989  * @brief Set keyboard geometry for autoscroll.
990  *        This includes the ISE geometry together with candidate window
991  *
992  * @param kbd_state The keyboard state.
993  */
994 static void set_keyboard_geometry_atom_info (Ecore_X_Window window, struct rectinfo ise_rect)
995 {
996     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
997
998     if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
999         ise_rect.pos_x = 0;
1000
1001         if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1002             if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1003                 ise_rect.width  = _candidate_width;
1004                 ise_rect.height = _candidate_height;
1005             }
1006         } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
1007             ise_rect.width  = _soft_candidate_width;
1008             ise_rect.height = _soft_candidate_height;
1009         }
1010
1011         int angle = efl_get_app_window_angle ();
1012         if (angle == 90 || angle == 270)
1013             ise_rect.pos_y = _screen_width - ise_rect.height;
1014         else
1015             ise_rect.pos_y = _screen_height - ise_rect.height;
1016     } else {
1017         if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1018             if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1019                 _candidate_valid_height = ui_candidate_get_valid_height ();
1020                 if ((_candidate_height - _candidate_valid_height) > _ise_height) {
1021                     _candidate_valid_height = _candidate_height;
1022                     ise_rect.pos_y  = ise_rect.pos_y + ise_rect.height - _candidate_height;
1023                     ise_rect.height = _candidate_height;
1024                 } else {
1025                     ise_rect.pos_y  -= _candidate_valid_height;
1026                     ise_rect.height += _candidate_valid_height;
1027                 }
1028             }
1029         }
1030     }
1031
1032     ecore_x_e_illume_keyboard_geometry_set (window, ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1033     LOGD ("KEYBOARD_GEOMETRY_SET : %d %d %d %d", ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1034     SCIM_DEBUG_MAIN (3) << "    KEYBOARD_GEOMETRY x=" << ise_rect.pos_x << " y=" << ise_rect.pos_y
1035         << " width=" << ise_rect.width << " height=" << ise_rect.height << "\n";
1036
1037     /* even the kbd_state is OFF, consider the keyboard is still ON if we have candidate opened */
1038     if (ise_rect.width == 0 && ise_rect.height == 0) {
1039         ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1040     } else {
1041         ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1042
1043         if (_ise_angle == 0 || _ise_angle == 180) {
1044             _portrait_recent_ise_geometry.valid = true;
1045             _portrait_recent_ise_geometry.geometry = ise_rect;
1046         }
1047         else {
1048             _landscape_recent_ise_geometry.valid = true;
1049             _landscape_recent_ise_geometry.geometry = ise_rect;
1050         }
1051     }
1052 }
1053 #endif
1054
1055 /**
1056  * @brief Get ISE index according to uuid.
1057  *
1058  * @param uuid The ISE uuid.
1059  *
1060  * @return The ISE index
1061  */
1062 static unsigned int get_ise_index (const String uuid)
1063 {
1064     unsigned int index = 0;
1065     if (uuid.length () > 0) {
1066         for (unsigned int i = 0; i < _ime_info.size (); i++) {
1067             if (uuid == _ime_info[i].appid) {
1068                 index = i;
1069                 break;
1070             }
1071         }
1072     }
1073
1074     return index;
1075 }
1076
1077 static void set_keyboard_engine (String active_uuid)
1078 {
1079     String IMENGINE_KEY  = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
1080     String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
1081     if (active_uuid != keyboard_uuid) {
1082         _info_manager->change_factory (active_uuid);
1083         _config->write (IMENGINE_KEY, active_uuid);
1084         _config->flush ();
1085     }
1086 }
1087
1088 static void _update_ime_info(void)
1089 {
1090     std::vector<String> ise_langs;
1091
1092     _ime_info.clear();
1093     isf_pkg_select_all_ime_info_db(_ime_info);
1094
1095     /* Update _groups */
1096     _groups.clear();
1097     for (size_t i = 0; i < _ime_info.size (); ++i) {
1098         scim_split_string_list(ise_langs, _ime_info[i].languages);
1099         for (size_t j = 0; j < ise_langs.size (); j++) {
1100             if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
1101                 _groups[ise_langs[j]].push_back (i);
1102         }
1103         ise_langs.clear ();
1104     }
1105 }
1106
1107 static void _initialize_ime_info (void)
1108 {
1109     std::vector<ImeInfoDB>::iterator iter;
1110     VectorPairStringUint32   ime_on_off;
1111     // Store is_enabled values of each keyboard
1112     for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1113         if (iter->mode == TOOLBAR_HELPER_MODE) {
1114             ime_on_off.push_back (std::make_pair (iter->appid, iter->is_enabled));
1115         }
1116     }
1117     // Delete the whole ime_info DB and reload
1118     isf_db_delete_ime_info ();
1119     _update_ime_info ();
1120     // Restore is_enabled value to valid keyboards
1121     for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1122         if (iter->mode == TOOLBAR_HELPER_MODE) {
1123             for (VectorPairStringUint32::iterator it = ime_on_off.begin (); it != ime_on_off.end (); it++) {
1124                 if (it->first.compare (iter->appid) == 0) {
1125                     if (it->second != iter->is_enabled) {
1126                         iter->is_enabled = it->second;
1127                         isf_db_update_is_enabled_by_appid (iter->appid.c_str (), static_cast<bool>(iter->is_enabled));
1128                     }
1129                     ime_on_off.erase (it);
1130                     break;
1131                 }
1132             }
1133         }
1134     }
1135 }
1136
1137 #ifdef HAVE_PKGMGR_INFO
1138 /**
1139  * @brief Insert or update ime_info data with pkgid.
1140  *
1141  * @param pkgid pkgid to insert/update ime_info table.
1142  *
1143  * @return 1 on successful insert, 2 on successful update, -1 if pkgid is not IME package, otherwise return 0.
1144  */
1145 static int _isf_insert_ime_info_by_pkgid(const char *pkgid)
1146 {
1147     int ret = -1;
1148     pkgmgrinfo_pkginfo_h handle = NULL;
1149     int result = 0;  // 0: not IME, 1: Inserted, 2: Updated (because of the same appid)
1150     uid_t uid = getuid ();
1151     bool user = false;
1152
1153     if (!pkgid) {
1154         LOGW ("pkgid is null.");
1155         return 0;
1156     }
1157
1158     /* Try to get in global packages */
1159     ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &handle);
1160     if (ret != PMINFO_R_OK) {
1161         /* Try to get in user packages */
1162         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, uid, &handle);
1163         if (ret != PMINFO_R_OK) {
1164             LOGW ("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", pkgid, ret, getuid ());
1165             return 0;
1166         }
1167         else {
1168             user = true;
1169         }
1170     }
1171
1172     if (user) {
1173         /* Try to get in user packages */
1174         ret = pkgmgrinfo_appinfo_get_usr_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result, uid);
1175     }
1176     else {
1177         /* Try to get in global packages */
1178         ret = pkgmgrinfo_appinfo_get_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result);
1179     }
1180
1181     if (ret != PMINFO_R_OK) {
1182         LOGW ("Failed to call %s failed(%d)", user ? "pkgmgrinfo_appinfo_get_usr_list" : "pkgmgrinfo_appinfo_get_list", ret);
1183
1184         ret = 0;
1185     }
1186     else if (result)
1187         ret = result;
1188
1189     pkgmgrinfo_pkginfo_destroy_pkginfo (handle);
1190
1191     return ret;
1192 }
1193
1194 /**
1195  * @brief Timer to start initial Helper ISE if the active (selected) 3rd party keyboard is uninstalled.
1196  *
1197  * @param data User data
1198  *
1199  * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1200  * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1201  */
1202 static Eina_Bool _start_default_helper_timer(void *data)
1203 {
1204     std::vector<String> total_appids;
1205     std::vector<ImeInfoDB>::iterator it;
1206     VectorPairStringUint32::iterator iter;
1207
1208     /* Let panel know that ISE is deleted... */
1209     for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1210         total_appids.push_back(it->appid);
1211     }
1212     if (total_appids.size() > 0)
1213         _info_manager->update_ise_list (total_appids);
1214
1215     LOGD ("Try to start the initial helper");
1216     set_active_ise(_initial_ise_uuid, true);
1217
1218     for (iter = g_pkgids_to_be_uninstalled.begin (); iter != g_pkgids_to_be_uninstalled.end (); iter++) {
1219         if (iter->first.compare(g_stopped_helper_pkgid) == 0) {
1220             g_pkgids_to_be_uninstalled.erase (iter);
1221             break;
1222         }
1223     }
1224     g_stopped_helper_pkgid = "";
1225
1226     g_start_default_helper_timer = NULL;
1227     return ECORE_CALLBACK_CANCEL;
1228 }
1229
1230 /**
1231  * @brief Timer to release uninstalled IME related info; g_pkgids_to_be_uninstalled has appid and is_enabled.
1232  *
1233  * @param data User data
1234  *
1235  * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1236  * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1237  */
1238 static Eina_Bool _release_uninstalled_pkginfo_timer(void *data)
1239 {
1240     g_pkgids_to_be_uninstalled.clear ();
1241     g_release_uninstalled_ime_info_timer = NULL;
1242     return ECORE_CALLBACK_CANCEL;
1243 }
1244
1245 /**
1246  * @brief Called when the package is installed, uninstalled or updated, and the progress of the request to the package manager changes.
1247  * @since_tizen 2.3
1248  * @param[in] type The type of the package to be installed, uninstalled or updated
1249  * @param[in] package The name of the package to be installed, uninstalled or updated
1250  * @param[in] event_type The type of the request to the package manager
1251  * @param[in] event_state The current state of the request to the package manager
1252  * @param[in] progress The progress for the request that is being processed by the package manager \n
1253  *            The range of progress is from 0 to 100
1254  * @param[in] error The error code when the package manager failed to process the request
1255  * @param[in] user_data The user data passed from package_manager_set_event_cb()
1256  * @see package_manager_set_event_cb()
1257  * @see package_manager_unset_event_cb()
1258
1259 INFO: Package install/update/uninstall scenario
1260 Install and Uninstall are obviously simple.
1261    Install: just INSTALL
1262    Uninstall: just UNINSTALL
1263 Update package (change the source codes in IME project and Run As again), there are four scenarios:
1264 1. UPDATE
1265    Source code change
1266 2. UNINSTALL -> INSTALL
1267    This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1268    and change Application ID in tizen-manifest.xml file and Run As.
1269 3. UPDATE -> INSTALL
1270    This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1271    and change Application ID in tizen-manifest.xml file and Run As.
1272    At UPDATE event, pkgid (package parameter) is invalid...
1273 4. UPDATE
1274    Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1275    At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1276
1277 If multiple packages (including non-IME pkgs) are uninstalled and installed; Z300H UPS (ultra power saving) mode scenario.
1278 For example, A and B packages are uninstalled and installed, the package manager works in this order: A UNINSTALL -> B UNINSTALL -> A INSTALL -> B INSTALL
1279
1280 Assuming IMEngine won't be changed through this. IMEngine might have multiple appids for one pkgid.
1281 Assuming preinstalled IME won't be changed through this.
1282  */
1283 static void _package_manager_event_cb (const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data)
1284 {
1285     String current_ime_appid; // now appid is uuid.
1286     std::vector<String> appids;
1287     std::vector<String> total_appids;
1288     std::vector<ImeInfoDB>::iterator it;
1289     std::vector<String>::iterator it2;
1290     VectorPairStringUint32::iterator it3;
1291     int ret = 0;
1292
1293     if (!package || !type)
1294         return;
1295
1296     if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
1297         if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1298             LOGD ("type=%s package=%s event_type=UPDATE event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1299
1300             ret = _isf_insert_ime_info_by_pkgid (package);   // If package is not IME, -1 would be returned.
1301             if (ret == 1) { // In case the package is updated with the changed appid. In this case, there will be two IMEs
1302                 ret = isf_db_select_appids_by_pkgid (package, appids);
1303                 if (ret > 1) {
1304                     if (_ime_info.size () > 0 && _ime_info [get_ise_index (appids.front ())].is_enabled)
1305                         isf_db_update_is_enabled_by_appid (appids.back ().c_str (), true);
1306                     isf_db_delete_ime_info_by_appid (appids.front ().c_str ());
1307                 }
1308
1309                 _update_ime_info ();
1310
1311                 /* Let panel know that ise list is changed... */
1312                 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1313                     total_appids.push_back(it->appid);
1314                 }
1315                 if (total_appids.size() > 0)
1316                     _info_manager->update_ise_list (total_appids);
1317
1318                 if (ret > 1 && _soft_keyboard_launched) { // If the previous appid of pkgid is the current IME, restart it with new appid.
1319                     current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1320                     if (current_ime_appid.compare (appids.front ()) == 0) {
1321                         LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1322                         _info_manager->hide_helper (current_ime_appid);
1323                         _info_manager->stop_helper (current_ime_appid);
1324                         LOGD ("Start IME(%s)", appids.back ().c_str ());
1325                         scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids.back ());
1326                         set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1327                         _info_manager->start_helper (appids.back ());
1328                     }
1329                 }
1330             }
1331             else if (ret == 2) {  // In case IME package is just updated...
1332                 _update_ime_info ();
1333
1334                 if (_soft_keyboard_launched) { // If package is the current IME, restart it.
1335                     current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1336                     if (isf_db_select_appids_by_pkgid(package, appids)) {
1337                         if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the current ISE package is updated, restart it.
1338                             for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1339                                 if (it->mode == TOOLBAR_HELPER_MODE && it->appid.compare(current_ime_appid) == 0) { // Make sure it's Helper ISE...
1340                                     LOGD ("Restart IME(%s)", current_ime_appid.c_str ());
1341                                     _info_manager->hide_helper (current_ime_appid);
1342                                     _info_manager->stop_helper (current_ime_appid);
1343                                     _info_manager->start_helper (current_ime_appid);
1344                                     break;
1345                                 }
1346                             }
1347                         }
1348                     }
1349                 }
1350             }
1351             else if (ret == 0) {    // For example, this happens if appid is changed in IME project and Run As again. Assuming only Helper (3rd party) might be updated and there is one appid per each pkgid...
1352                 if (isf_db_select_appids_by_pkgid(package, appids) == 1) {
1353                     for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1354                         if (it->pkgid.compare(package) == 0) {
1355                             g_pkgids_to_be_updated_and_installed.push_back (std::make_pair (it->pkgid, it->is_enabled));
1356                             break;
1357                         }
1358                     }
1359                     if (it == _ime_info.end ()) // Probably not going to happen.
1360                         g_pkgids_to_be_updated_and_installed.push_back(std::make_pair (String(package), 0));
1361
1362                     current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1363                     if (_soft_keyboard_launched && std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the updated IME is the current ISE...
1364                         for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1365                             if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1366                                 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1367                                 _info_manager->hide_helper (current_ime_appid);
1368                                 _info_manager->stop_helper (current_ime_appid);
1369                                 _soft_keyboard_launched = false;
1370                                 g_updated_helper_pkgid = package;
1371                                 break;
1372                             }
1373                         }
1374                     }
1375
1376                     if (appids.size () > 0) // Probably appids size is 1.
1377                         LOGD ("Delete IME(%s)", appids[0].c_str ());
1378                     if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1379                         _update_ime_info();
1380
1381                        /* Let panel know that ise is deleted... */
1382                        for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1383                            total_appids.push_back(it->appid);
1384                        }
1385                        if (total_appids.size() > 0)
1386                            _info_manager->update_ise_list (total_appids);
1387                     }
1388                 }
1389                 else {
1390                     LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1391                 }
1392             }
1393         }
1394     }
1395     else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL) {
1396         if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1397             LOGD ("type=%s package=%s event_type=INSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1398
1399             ///////////////// UNINSTALL -> INSTALL and if the uninstalled IME is reinstalled /////////////////
1400             if (g_stopped_helper_pkgid.compare(package) == 0 && g_start_default_helper_timer) {
1401                 LOGD ("Cancel timer to start the default IME");
1402                 ecore_timer_del(g_start_default_helper_timer);
1403                 g_start_default_helper_timer = NULL;
1404                 g_stopped_helper_pkgid = "";
1405
1406                 ret = _isf_insert_ime_info_by_pkgid(package);
1407                 if (ret > 0) {
1408                     /* Find appid by pkgid. There might be multiple appid, but assume Helper always has one appid.
1409                        And appid can be changed, but pkgid won't be changed. */
1410                     ret = isf_db_select_appids_by_pkgid(package, appids);
1411                     if (ret == 1 && appids.size () == 1) {
1412                         for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1413                             if (it3->first.compare(package) == 0) {
1414                                 if (it3->second)
1415                                     isf_db_update_is_enabled_by_appid(appids[0].c_str (), (bool)it3->second);
1416
1417                                 _update_ime_info();
1418
1419                                 /* Let panel know that ise is added... */
1420                                 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1421                                     total_appids.push_back(it->appid);
1422                                 }
1423                                 if (total_appids.size() > 0)
1424                                     _info_manager->update_ise_list (total_appids);
1425
1426                                 LOGD ("Restart IME(%s)", appids[0].c_str ());
1427                                 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids[0]);
1428                                 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1429                                 _info_manager->start_helper (appids[0]);
1430                                 _soft_keyboard_launched = true;
1431
1432                                 g_pkgids_to_be_uninstalled.erase (it3);
1433                                 break;
1434                             }
1435                         }
1436                     }
1437                     else {
1438                         LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1439
1440                         _update_ime_info();
1441
1442                         /* Let panel know that ise is added... */
1443                         for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1444                             total_appids.push_back(it->appid);
1445                         }
1446                         if (total_appids.size() > 0)
1447                             _info_manager->update_ise_list (total_appids);
1448                     }
1449                 }
1450                 else {
1451                     LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1452                 }
1453             }
1454             else {  // If new package is installed...
1455                 ret = _isf_insert_ime_info_by_pkgid(package);   // If package is not IME, -1 would be returned.
1456                 if (ret > 0) { // In case package is IME...
1457                     ///////////////// INSTALL /////////////////
1458                     _update_ime_info();
1459
1460                     /* Let panel know that ise is added... */
1461                     for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1462                         total_appids.push_back(it->appid);
1463                     }
1464                     if (total_appids.size() > 0)
1465                        _info_manager->update_ise_list (total_appids);
1466                     ///////////////// END /////////////////
1467
1468                     /* For example, the following happens if appid is changed in IME project and Run As again. The appid would be changed this time.
1469                        Assuming only Helper (3rd party) might be installed after update or uninstall and there is one appid per each pkgid...*/
1470
1471                     ///////////////// UPDATE -> INSTALL /////////////////
1472                     for (it3 = g_pkgids_to_be_updated_and_installed.begin (); it3 != g_pkgids_to_be_updated_and_installed.end (); it3++) {
1473                         if (it3->first.compare(package) == 0) {
1474                             if (it3->second) {
1475                                 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1476                                     if (it->pkgid.compare(package) == 0) {
1477                                         it->is_enabled = it3->second;
1478                                         isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1479                                         break;
1480                                     }
1481                                 }
1482                             }
1483                             g_pkgids_to_be_updated_and_installed.erase (it3);
1484                             break;
1485                         }
1486                     }
1487                     if (g_updated_helper_pkgid.compare(package) == 0) {
1488                         for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1489                             if (it->mode == TOOLBAR_HELPER_MODE && it->pkgid.compare(package) == 0) {
1490                                 LOGD ("Start IME(%s)", it->appid.c_str ());
1491                                 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), it->appid);
1492                                 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1493                                 _info_manager->start_helper (it->appid);
1494                                 _soft_keyboard_launched = true;
1495                                 break;
1496                             }
1497                         }
1498                         g_updated_helper_pkgid = "";
1499                         return;
1500                     }
1501                     ///////////////// END /////////////////
1502
1503                     ///////////////// UNINSTALL -> INSTALL /////////////////
1504                     for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1505                         if (it3->first.compare(package) == 0) {
1506                             if (it3->second) {
1507                                 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1508                                     if (it->pkgid.compare(package) == 0) {
1509                                         it->is_enabled = it3->second;
1510                                         isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1511                                         break;
1512                                     }
1513                                 }
1514                             }
1515                             g_pkgids_to_be_uninstalled.erase (it3);
1516                             break;
1517                         }
1518                     }
1519                     ///////////////// END /////////////////
1520                 }
1521                 else if (ret == 0) {
1522                     LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1523                 }
1524             }
1525         }
1526     }
1527     else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL) {
1528         switch (event_state) {
1529             case PACKAGE_MANAGER_EVENT_STATE_STARTED:
1530                 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=STARTED progress=%d error=%d", type, package, progress, error);
1531                 {
1532                     // Need to check if there is "http://tizen.org/category/ime" category; it can be done by comparing pkgid with ime_info db.
1533                     int imeCnt = 0;
1534                     if (_ime_info.size() == 0)
1535                         _update_ime_info();
1536
1537                     for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1538                         if (it->pkgid.compare(package) == 0 && it->is_preinstalled == 0) {   // Ignore if it's preinstalled IME and IMEngine.
1539                             imeCnt++;
1540                             break;
1541                         }
1542                     }
1543
1544                     if (imeCnt > 0) {
1545                         // There might be more than one appid for one pkgid, but let's assume Helper always has one appid per a pkgid. Stop Helper ISE, but not delete it from ime_info db.
1546                         LOGD ("%s for pkgid(\"%s\") is about to be deleted", it->appid.c_str (), package);
1547                         g_pkgids_to_be_uninstalled.push_back(std::make_pair (String(package), it->is_enabled));
1548
1549                         if (_soft_keyboard_launched && isf_db_select_appids_by_pkgid(package, appids)) {
1550                             current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1551                             if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the uninstalled IME is the current ISE... appids size is probably 1.
1552                                 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1553                                     if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1554                                         LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1555                                         _info_manager->hide_helper (current_ime_appid);
1556                                         _info_manager->stop_helper (current_ime_appid);
1557                                         _soft_keyboard_launched = false;
1558                                         g_stopped_helper_pkgid = package;
1559                                         break;
1560                                     }
1561                                 }
1562                             }
1563                         }
1564                     }
1565                 }
1566                 break;
1567
1568             case PACKAGE_MANAGER_EVENT_STATE_COMPLETED:
1569                 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1570
1571                 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1572                     if (it3->first.compare(package) == 0) {
1573                         if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1574                             _update_ime_info();
1575                         }
1576
1577                         if (g_stopped_helper_pkgid.compare(package) == 0) { // If the uninstalled ISE is the current ISE, start the initial helper ISE by timer.
1578                             if (g_start_default_helper_timer)
1579                                 ecore_timer_del(g_start_default_helper_timer);
1580                             LOGD ("Add timer to start the default IME");
1581                             g_start_default_helper_timer = ecore_timer_add(3.0, _start_default_helper_timer, NULL);
1582                         }
1583                         else {  // Need to clean up g_pkgids_to_be_uninstalled info unless the same package is installed again; e.g., UNINSTALL -> INSTALL case.
1584                             if (g_release_uninstalled_ime_info_timer)
1585                                 ecore_timer_del(g_release_uninstalled_ime_info_timer);
1586                             LOGD ("Add timer to release uninstalled IME pkg info");
1587                             g_release_uninstalled_ime_info_timer = ecore_timer_add(7.0, _release_uninstalled_pkginfo_timer, NULL);
1588                         }
1589
1590                         /* Let panel know that ise is deleted... */
1591                         for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1592                             total_appids.push_back(it->appid);
1593                         }
1594                         if (total_appids.size() > 0)
1595                             _info_manager->update_ise_list (total_appids);
1596
1597                         break;
1598                     }
1599                 }
1600                 break;
1601
1602             case PACKAGE_MANAGER_EVENT_STATE_FAILED:
1603                 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=FAILED progress=%d error=%d", type, package, progress, error);
1604
1605                 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1606                     if (it3->first.compare(package) == 0) {
1607                         // Update _ime_info for sure...
1608                         _update_ime_info();
1609
1610                         if (g_stopped_helper_pkgid.compare(package) == 0) {
1611                             ret = isf_db_select_appids_by_pkgid(package, appids);
1612                             if (ret == 1 && appids.size () == 1) {
1613                                 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1614                                     if (it->appid.compare(appids[0]) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1615                                         LOGD ("Restart IME(%s)", appids[0].c_str ());
1616                                         set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1617                                         _info_manager->start_helper (appids[0]);
1618                                         _soft_keyboard_launched = true;
1619                                         break;
1620                                     }
1621                                 }
1622                             }
1623                             else {
1624                                 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1625                             }
1626                             g_stopped_helper_pkgid = "";
1627                         }
1628
1629                         g_pkgids_to_be_uninstalled.erase (it3);
1630                         break;
1631                     }
1632                 }
1633                 break;
1634
1635             default:
1636                 break;
1637         }
1638     }
1639 }
1640 #endif
1641
1642 /**
1643  * @brief Set keyboard ISE.
1644  *
1645  * @param uuid The keyboard ISE's uuid.
1646  *
1647  * @return false if keyboard ISE change is failed, otherwise return true.
1648  */
1649 static bool set_keyboard_ise (const String &uuid)
1650 {
1651     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1652
1653     TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1654
1655     if (TOOLBAR_HELPER_MODE == mode) {
1656         String pre_uuid = _info_manager->get_current_helper_uuid ();
1657         _info_manager->hide_helper (pre_uuid);
1658         _info_manager->stop_helper (pre_uuid);
1659         _soft_keyboard_launched = false;
1660     } else if (TOOLBAR_KEYBOARD_MODE == mode) {
1661         uint32 kbd_option = 0;
1662         String kbd_uuid, kbd_name;
1663         isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
1664         if (kbd_uuid == uuid)
1665             return false;
1666     }
1667
1668     _info_manager->change_factory (uuid);
1669
1670     String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
1671     _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
1672
1673     return true;
1674 }
1675
1676 /**
1677  * @brief Set helper ISE.
1678  *
1679  * @param uuid The helper ISE's uuid.
1680  * @param launch_ise The flag for launching helper ISE.
1681  *
1682  * @return false if helper ISE change is failed, otherwise return true.
1683  */
1684 static bool set_helper_ise (const String &uuid, bool launch_ise)
1685 {
1686     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1687
1688     TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1689     String pre_uuid = _info_manager->get_current_helper_uuid ();
1690     LOGD ("pre_appid=%s, appid=%s, launch_ise=%d, %d", pre_uuid.c_str(), uuid.c_str(), launch_ise, _soft_keyboard_launched);
1691     if (pre_uuid == uuid && _soft_keyboard_launched)
1692         return true;
1693
1694     if (TOOLBAR_HELPER_MODE == mode && pre_uuid.length () > 0 && _soft_keyboard_launched) {
1695         _info_manager->hide_helper (pre_uuid);
1696         _info_manager->stop_helper (pre_uuid);
1697         _soft_keyboard_launched = false;
1698         LOGD ("stop helper : %s", pre_uuid.c_str ());
1699     }
1700
1701     if (launch_ise) {
1702         LOGD ("Start helper (%s)", uuid.c_str ());
1703
1704         set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1705         if (_info_manager->start_helper (uuid))
1706             _soft_keyboard_launched = true;
1707     }
1708     _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), uuid);
1709
1710     return true;
1711 }
1712
1713 #ifdef HAVE_PKGMGR_INFO
1714 int get_ime_app_list_cb (const pkgmgrinfo_appinfo_h handle, void *user_data)
1715 {
1716     int ret = 0;
1717     char *appid = NULL, *pkgid = NULL, *pkgtype = NULL, *exec = NULL, *label = NULL, *path = NULL;
1718     pkgmgrinfo_pkginfo_h  pkginfo_handle = NULL;
1719     ImeInfoDB ime_db;
1720     int *result = static_cast<int*>(user_data);
1721
1722     if (result) /* in this case, need to check category */ {
1723         bool exist = true;
1724         ret = pkgmgrinfo_appinfo_is_category_exist (handle, "http://tizen.org/category/ime", &exist);
1725         if (ret != PMINFO_R_OK || !exist) {
1726             return 0;
1727         }
1728     }
1729
1730     /* appid */
1731     ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
1732     if (ret == PMINFO_R_OK)
1733         ime_db.appid = String (appid ? appid : "");
1734     else {
1735         LOGE ("pkgmgrinfo_appinfo_get_appid failed! error code=%d", ret);
1736         return 0;
1737     }
1738
1739     ime_db.iconpath = "";
1740
1741     /* pkgid */
1742     ret = pkgmgrinfo_appinfo_get_pkgid (handle, &pkgid);
1743     if (ret == PMINFO_R_OK)
1744         ime_db.pkgid = String (pkgid ? pkgid : "");
1745     else {
1746         LOGE ("pkgmgrinfo_appinfo_get_pkgid failed! error code=%d", ret);
1747         return 0;
1748     }
1749
1750     /* exec path */
1751     ret = pkgmgrinfo_appinfo_get_exec (handle, &exec);
1752     if (ret == PMINFO_R_OK)
1753         ime_db.exec = String (exec ? exec : "");
1754     else {
1755         LOGE ("pkgmgrinfo_appinfo_get_exec failed! error code=%d", ret);
1756         return 0;
1757     }
1758
1759     /* label */
1760     ret = pkgmgrinfo_appinfo_get_label (handle, &label);
1761     if (ret == PMINFO_R_OK)
1762         ime_db.label = String (label ? label : "");
1763
1764     /* get pkgmgrinfo_pkginfo_h */
1765     /* Try to get in global packages */
1766     ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &pkginfo_handle);
1767     if (ret != PMINFO_R_OK) {
1768         /* Try to get in user packages */
1769         ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, getuid (), &pkginfo_handle);
1770     }
1771
1772     if (ret == PMINFO_R_OK && pkginfo_handle) {
1773         /* pkgtype */
1774         ret = pkgmgrinfo_pkginfo_get_type (pkginfo_handle, &pkgtype);
1775
1776         if (ret == PMINFO_R_OK)
1777             ime_db.pkgtype = String (pkgtype ? pkgtype : "");
1778         else {
1779             ISF_SAVE_LOG ("pkgtype is not available!");
1780             pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1781             return 0;
1782         }
1783
1784         /* pkgrootpath */
1785         pkgmgrinfo_pkginfo_get_root_path (pkginfo_handle, &path);
1786     }
1787
1788     ime_db.languages = "en";
1789     ime_db.display_lang = "";
1790
1791     if (ime_db.pkgtype.compare ("rpm") == 0 &&   //1 Inhouse IMEngine ISE(IME)
1792         ime_db.exec.find ("scim-launcher") != String::npos)  // Some IMEngine's pkgid doesn't have "ise-engine" prefix.
1793     {
1794         ime_db.mode = TOOLBAR_KEYBOARD_MODE;
1795         ime_db.options = 0;
1796         ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1797             + String (SCIM_PATH_DELIM_STRING) + String ("IMEngine");
1798         ime_db.module_name = ime_db.pkgid;
1799         ime_db.is_enabled = 1;
1800         ime_db.is_preinstalled = 1;
1801         ime_db.has_option = 0; // It doesn't matter. No option for IMEngine...
1802     }
1803     else {
1804         ime_db.mode = TOOLBAR_HELPER_MODE;
1805         if (ime_db.pkgtype.compare ("rpm") == 0 && path) //1 Inhouse Helper ISE(IME)
1806         {
1807             if (_TV)
1808                 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1809             else
1810                 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART;
1811
1812             ime_db.module_name = ime_db.pkgid;
1813
1814             String module_path = String (path) + String ("/lib");
1815             String fullpath = module_path + String (SCIM_PATH_DELIM_STRING) + ime_db.module_name + String (".so");
1816             struct stat st;
1817             if (stat (fullpath.c_str (), &st) < 0) {
1818                 /* Not found in lib directory of package's root path */
1819                 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1820                     + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1821             }
1822             else {
1823                 ime_db.module_path = module_path;
1824             }
1825
1826             ime_db.is_enabled = 1;
1827             ime_db.is_preinstalled = 1;
1828             ime_db.has_option = 1;  // Let's assume the inhouse IME always has an option menu.
1829         }
1830         else if (ime_db.pkgtype.compare ("wgt") == 0)    //1 Download Web IME
1831         {
1832             ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1833                 | SCIM_HELPER_NEED_SPOT_LOCATION_INFO | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1834             ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1835                 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1836             ime_db.module_name = String ("ise-web-helper-agent");
1837             if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1838                 ime_db.is_enabled = 1;
1839                 ime_db.is_preinstalled = 1;
1840             }
1841             else {
1842                 if (_MOBILE || _COMMON)
1843                     ime_db.is_enabled = 0;
1844                 else
1845                     ime_db.is_enabled = 1;
1846
1847                 ime_db.is_preinstalled = 0;
1848             }
1849             ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1850         }
1851         else if (ime_db.pkgtype.compare ("tpk") == 0)    //1 Download Native IME
1852         {
1853             ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1854                 | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1855             if (path)
1856                 ime_db.module_path = String (path) + String ("/lib");
1857             else
1858                 ime_db.module_path = String (tzplatform_getenv(TZ_SYS_RW_APP)) + ime_db.pkgid + String ("/lib");
1859             ime_db.module_name = String ("lib") + ime_db.exec.substr (ime_db.exec.find_last_of (SCIM_PATH_DELIM) + 1);
1860             if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1861                 ime_db.is_enabled = 1;
1862                 ime_db.is_preinstalled = 1;
1863             }
1864             else {
1865                 if (_MOBILE || _COMMON)
1866                     ime_db.is_enabled = 0;
1867                 else
1868                     ime_db.is_enabled = 1;
1869
1870                 ime_db.is_preinstalled = 0;
1871             }
1872             ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1873         }
1874         else {
1875             LOGE ("Unsupported pkgtype(%s)", ime_db.pkgtype.c_str ());
1876             if (pkginfo_handle) {
1877                 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1878                 pkginfo_handle = NULL;
1879             }
1880             return 0;
1881         }
1882     }
1883
1884     _ime_info.push_back(ime_db);
1885
1886     if (pkginfo_handle) {
1887         pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1888         pkginfo_handle = NULL;
1889     }
1890
1891     return 0;
1892 }
1893 #endif
1894
1895 /**
1896  * @brief Set active ISE.
1897  *
1898  * @param uuid The ISE's uuid.
1899  * @param launch_ise The flag for launching helper ISE.
1900  *
1901  * @return false if ISE change is failed, otherwise return true.
1902  */
1903 static bool set_active_ise (const String &uuid, bool launch_ise)
1904 {
1905     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1906     LOGD ("set ISE (%s) %d", uuid.c_str(), launch_ise);
1907
1908     if (uuid.length () <= 0)
1909         return false;
1910
1911     bool ise_changed = false, valid = false;
1912
1913     int ime_num = -1; /* If we failed retrieving the number of IMEs installed, assume we need to clear IME related settings */
1914     pkgmgrinfo_appinfo_filter_h handle;
1915     int ret = pkgmgrinfo_appinfo_filter_create(&handle);
1916     if (ret == PMINFO_R_OK) {
1917         ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
1918         if (ret == PMINFO_R_OK) {
1919             ret = pkgmgrinfo_appinfo_filter_count(handle, &ime_num);
1920             if (ret != PMINFO_R_OK) {
1921                 LOGW("pkgmgrinfo_appinfo_filter_count failed(%d)", ret);
1922             }
1923         }
1924         pkgmgrinfo_appinfo_filter_destroy (handle);
1925     }
1926     else {
1927         LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
1928     }
1929
1930     /* If the ime_num and _ime_info.size() are different, it is likely that the isf-panel-efl was
1931        terminated abnormally while processing package manager's install / uninstall events */
1932     LOGD("Checking whether db file needs to be re-created : %d %zu", ime_num, _ime_info.size());
1933     if (ime_num != (int)_ime_info.size()) {
1934         _ime_info.clear();
1935         isf_db_delete_ime_info();
1936         isf_pkg_reload_ime_info_db();
1937         isf_pkg_select_all_ime_info_db(_ime_info);
1938     }
1939
1940     if (_ime_info.size () == 0) {
1941 #ifdef HAVE_PKGMGR_INFO
1942         int ret = pkgmgrinfo_appinfo_filter_create (&handle);
1943         if (ret == PMINFO_R_OK) {
1944             ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
1945             if (ret == PMINFO_R_OK)
1946                 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
1947             else {
1948                 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
1949             }
1950             pkgmgrinfo_appinfo_filter_destroy (handle);
1951         }
1952         else {
1953             LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
1954         }
1955 #endif
1956     }
1957
1958     for (unsigned int i = 0; i < _ime_info.size (); i++) {
1959         if (!uuid.compare (_ime_info[i].appid)) {
1960             if (TOOLBAR_KEYBOARD_MODE == _ime_info[i].mode)
1961                 ise_changed = set_keyboard_ise (_ime_info[i].appid);
1962             else if (TOOLBAR_HELPER_MODE == _ime_info[i].mode) {
1963                 if (_ime_info[i].is_enabled) {
1964                     if (_ime_info[i].exec == String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
1965                         /* If IME so is deleted somehow, main() in scim_helper_launcher.cpp will return -1.
1966                            Checking HelperModule validity seems necessary here. */
1967                         HelperModule helper_module (_ime_info[i].module_name);
1968                         if (helper_module.valid ())
1969                             valid = true;
1970                         helper_module.unload ();
1971                     }
1972                     else {
1973                         /* executable type */
1974                         valid = true;
1975                     }
1976
1977                     if (valid)
1978                         ise_changed = set_helper_ise (_ime_info[i].appid, launch_ise);
1979                     else
1980                         LOGW ("Helper ISE(appid=\"%s\",module_name=\"%s\") is not valid.", _ime_info[i].appid.c_str (), _ime_info[i].module_name.c_str ());
1981                 }
1982                 else {
1983                     LOGW ("Helper ISE(appid=\"%s\") is not enabled.", _ime_info[i].appid.c_str ());
1984                 }
1985             }
1986             _info_manager->set_current_toolbar_mode (_ime_info[i].mode);
1987             if (ise_changed) {
1988                 /* From Tizen 4.0 all the ISEs need to handle H/W keyboard events */
1989                 _ime_info[i].options |= ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1990                 _info_manager->set_current_helper_option (_ime_info[i].options);
1991                 _info_manager->set_current_ise_name (_ime_info[i].label);
1992                 _ise_state  = WINDOW_STATE_HIDE;
1993                 _candidate_mode      = SOFT_CANDIDATE_WINDOW;
1994                 _candidate_port_line = ONE_LINE_CANDIDATE;
1995 #if ISF_BUILD_CANDIDATE_UI
1996                 _ise_width = 0;
1997                 _ise_height = 0;
1998                 _soft_candidate_width = 0;
1999                 _soft_candidate_height = 0;
2000
2001                 if (_candidate_window)
2002                     ui_create_candidate_window ();
2003 #endif
2004
2005                 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _ime_info[i].appid);
2006                 scim_global_config_flush ();
2007
2008                 _config->flush ();
2009                 _config->reload ();
2010
2011 #ifdef HAVE_VCONF
2012                 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2013 #endif
2014             }
2015             else {
2016                 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2017             }
2018
2019             return ise_changed;
2020         }
2021     }
2022
2023     LOGW ("Failed to launch IME (%s), %zu", uuid.c_str (), _ime_info.size());
2024
2025     return false;
2026 }
2027
2028 /**
2029  * @brief Set temporary ISE.
2030  *
2031  * @param uuid The ISE's uuid.
2032  *
2033  * @return false if ISE change is failed, otherwise return true.
2034  */
2035 static bool set_temporary_ise (const String &uuid)
2036 {
2037     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2038     LOGD ("set temporary ISE (%s)", uuid.c_str ());
2039
2040     if (uuid.length () <= 0)
2041         return false;
2042
2043     if (_ime_info.size () == 0) {
2044 #ifdef HAVE_PKGMGR_INFO
2045         pkgmgrinfo_appinfo_filter_h handle;
2046         int ret = pkgmgrinfo_appinfo_filter_create (&handle);
2047         if (ret == PMINFO_R_OK) {
2048             /* Add the package info for the IME that matches with our uuid only */
2049             ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_ID, uuid.c_str ());
2050             if (ret == PMINFO_R_OK)
2051                 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
2052             else {
2053                 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
2054             }
2055             pkgmgrinfo_appinfo_filter_destroy (handle);
2056         } else {
2057             LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
2058         }
2059 #endif
2060     }
2061
2062 #ifdef HAVE_PKGMGR_INFO
2063     bool ise_changed = false;
2064
2065     pkgmgrinfo_appinfo_h handle = NULL;
2066     int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
2067     if (ret != PMINFO_R_OK) {
2068         LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
2069         return false;
2070     }
2071
2072     if (handle) {
2073         char *label = NULL;
2074         ret = pkgmgrinfo_appinfo_get_label (handle, &label);
2075         if (ret != PMINFO_R_OK) {
2076             LOGW ("Could not get label for appid '%s'", uuid.c_str ());
2077             pkgmgrinfo_appinfo_destroy_appinfo (handle);
2078             return false;
2079         }
2080
2081         ise_changed = set_helper_ise (uuid, true);
2082
2083         if (ise_changed) {
2084             _info_manager->set_current_toolbar_mode (TOOLBAR_HELPER_MODE);
2085             if (_TV)
2086                 _info_manager->set_current_helper_option (SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO |
2087                     SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT);
2088             else
2089                 _info_manager->set_current_helper_option (SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO |
2090                     SCIM_HELPER_AUTO_RESTART);
2091             String label_string = label;
2092             _info_manager->set_current_ise_name (label_string);
2093
2094 #ifdef HAVE_VCONF
2095             vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2096 #endif
2097         } else {
2098             LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2099         }
2100
2101         pkgmgrinfo_appinfo_destroy_appinfo (handle);
2102
2103         return ise_changed;
2104     }
2105 #endif
2106
2107     return false;
2108 }
2109
2110 /**
2111  * @brief Load ISF configuration and ISEs information.
2112  */
2113 static void load_config (void)
2114 {
2115     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2116
2117     /* Read configurations. */
2118     if (!_config.null ()) {
2119         bool shared_ise = _config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), false);
2120         _info_manager->set_should_shared_ise (shared_ise);
2121     }
2122     _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
2123     _auto_destroy_ise = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_ENABLE_AUTO_DESTROY_ISE), _auto_destroy_ise);
2124     _enable_auto_restart = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_ENABLE_AUTO_RESTART_ISE), _enable_auto_restart);
2125
2126     isf_load_ise_information (ALL_ISE, _config);
2127 }
2128
2129 /**
2130  * @brief Reload config callback function for ISF panel.
2131  *
2132  * @param config The config pointer.
2133  */
2134 static void config_reload_cb (const ConfigPointer &config)
2135 {
2136     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2137     /* load_config (); */
2138     _info_manager->reload_config ();
2139 }
2140
2141 #if ISF_BUILD_CANDIDATE_UI
2142 //////////////////////////////////////////////////////////////////////
2143 // Start of Candidate Functions
2144 //////////////////////////////////////////////////////////////////////
2145 /**
2146  * @brief Get candidate window valid height for autoscroll.
2147  *
2148  * @return The valid height.
2149  */
2150 static int ui_candidate_get_valid_height (void)
2151 {
2152     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2153
2154     int height = 0;
2155     int angle = 0;
2156
2157     if (_candidate_window) {
2158         if (_candidate_state == WINDOW_STATE_SHOW)
2159             angle = _candidate_angle;
2160         else
2161             angle = efl_get_app_window_angle ();
2162
2163         if (_aux_area_visible && _candidate_area_1_visible) {
2164             if (angle == 90 || angle == 270)
2165                 height = _candidate_land_height_min_2;
2166             else
2167                 height = _candidate_port_height_min_2;
2168         } else {
2169             if (angle == 90 || angle == 270)
2170                 height = _candidate_land_height_min;
2171             else
2172                 height = _candidate_port_height_min;
2173         }
2174     }
2175     return height;
2176 }
2177
2178 /**
2179  * @brief Resize candidate window size.
2180  *
2181  * @param new_width  New width for candidate window.
2182  * @param new_height New height for candidate window.
2183  */
2184 static void ui_candidate_window_resize (int new_width, int new_height)
2185 {
2186     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " width:" << new_width << " height:" << new_height << "\n";
2187
2188     if (!_candidate_window)
2189         return;
2190
2191     int height;
2192
2193     LOGD ("%s (w: %d, h: %d)", __func__, new_width, new_height);
2194     evas_object_resize (_aux_line, new_width, 2);
2195     _candidate_width  = new_width;
2196     _candidate_height = new_height;
2197     if (_candidate_state == WINDOW_STATE_SHOW)
2198         _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2199
2200     if (_candidate_state == WINDOW_STATE_SHOW && _candidate_mode == FIXED_CANDIDATE_WINDOW) {
2201         height = ui_candidate_get_valid_height ();
2202         if ((_ise_width == 0 && _ise_height == 0) ||
2203             (_ise_height > 0 && _candidate_valid_height != height) ||
2204             (_ise_height > 0 && (_candidate_height - height) > _ise_height) ||
2205             ((_candidate_angle == 90 || _candidate_angle == 270) && (_ise_width < _screen_height)) ||
2206             ((_candidate_angle == 0  || _candidate_angle == 180) && (_ise_width > _screen_width ))) {
2207 #ifdef HAVE_ECOREX
2208             set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2209 #endif
2210             _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2211         }
2212     }
2213
2214     /* Get height for portrait and landscape */
2215     int port_width  = _candidate_port_width;
2216     int port_height = _candidate_port_height_min;
2217     int land_width  = _candidate_land_width;
2218     int land_height = _candidate_land_height_min;
2219     if (_candidate_angle == 90 || _candidate_angle == 270) {
2220         land_height = new_height;
2221         if (land_height == _candidate_land_height_min_2) {
2222             port_height = _candidate_port_height_min_2;
2223         } else if (land_height == _candidate_land_height_max) {
2224             port_height = _candidate_port_height_max;
2225         } else if (land_height == _candidate_land_height_max_2) {
2226             port_height = _candidate_port_height_max_2;
2227         }
2228     } else {
2229         port_height = new_height;
2230         if (port_height == _candidate_port_height_min_2) {
2231             land_height = _candidate_land_height_min_2;
2232         } else if (port_height == _candidate_port_height_max) {
2233             land_height = _candidate_land_height_max;
2234         } else if (port_height == _candidate_port_height_max_2) {
2235             land_height = _candidate_land_height_max_2;
2236         }
2237     }
2238
2239     LOGD ("window_rotation_geometry_set (_candidate_window), port (%d, %d), land (%d, %d)",
2240             port_width, port_height, land_width, land_height);
2241
2242 #ifdef HAVE_ECOREX
2243     /*
2244     ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2245             0, 0, 0, port_width, port_height);
2246     ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2247             90, 0, 0, land_height, land_width);
2248     ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2249             180, 0, 0, port_width, port_height);
2250     ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2251             270, 0, 0, land_height, land_width);
2252     */
2253 #else
2254     ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2255             0, 0, 0, port_width, port_height);
2256     ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2257             90, 0, 0, land_height, land_width);
2258     ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2259             180, 0, 0, port_width, port_height);
2260     ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2261             270, 0, 0, land_height, land_width);
2262 #endif
2263 }
2264
2265 /**
2266  * @brief This function will show/hide widgets of candidate window,
2267  *        and resize candidate window size according to aux_area/candidate_area.
2268  */
2269 static void ui_candidate_window_adjust (void)
2270 {
2271     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2272     if (!_candidate_window)
2273         return;
2274
2275     int x = 0, y = 0, width = 0, height = 0;
2276
2277     /* Get candidate window size */
2278 #ifdef HAVE_ECOREX
2279     /*
2280     if (_candidate_angle == 90 || _candidate_angle == 270) {
2281         ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2282                 &x, &y, &height, &width);
2283     } else {
2284         ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2285                 &x, &y, &width, &height);
2286     }
2287     */
2288 #else
2289     if (_candidate_angle == 90 || _candidate_angle == 270)
2290         ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &height, &width);
2291     else
2292         ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
2293 #endif
2294
2295     if (_aux_area_visible && _candidate_area_2_visible) {
2296         evas_object_show (_aux_line);
2297         evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2298         if (_candidate_angle == 90 || _candidate_angle == 270) {
2299             if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2300                 _ise_height > _candidate_land_height_max_2 - _candidate_land_height_min_2)
2301                 ui_candidate_window_resize (width, _candidate_land_height_min_2 + _ise_height);
2302             else
2303                 ui_candidate_window_resize (width, _candidate_land_height_max_2);
2304             evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2305             evas_object_move (_candidate_area_2, 0, _candidate_land_height_min_2);
2306             evas_object_move (_scroller_bg, 0, _candidate_land_height_min_2);
2307             evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2308         } else {
2309             if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2310                 _ise_height > _candidate_port_height_max_2 - _candidate_port_height_min_2)
2311                 ui_candidate_window_resize (width, _candidate_port_height_min_2 + _ise_height);
2312             else
2313                 ui_candidate_window_resize (width, _candidate_port_height_max_2);
2314             evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2315             evas_object_move (_candidate_area_2, 0, _candidate_port_height_min_2);
2316             evas_object_move (_scroller_bg, 0, _candidate_port_height_min_2);
2317             evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2318         }
2319     } else if (_aux_area_visible && _candidate_area_1_visible) {
2320         evas_object_show (_aux_line);
2321         evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2322         if (_candidate_angle == 90 || _candidate_angle == 270) {
2323             ui_candidate_window_resize (width, _candidate_land_height_min_2);
2324             evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2325             evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2326         } else {
2327             ui_candidate_window_resize (width, _candidate_port_height_min_2);
2328             evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2329             evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2330         }
2331     } else if (_aux_area_visible) {
2332         evas_object_hide (_aux_line);
2333         ui_candidate_window_resize (width, _aux_height + 2);
2334         evas_object_resize (_candidate_bg, width, _aux_height + 2);
2335     } else if (_candidate_area_2_visible) {
2336         evas_object_hide (_aux_line);
2337         evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2338         if (_candidate_angle == 90 || _candidate_angle == 270) {
2339             if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2340                 _ise_height > _candidate_land_height_max - _candidate_land_height_min)
2341                 ui_candidate_window_resize (width, _candidate_land_height_min + _ise_height);
2342             else
2343                 ui_candidate_window_resize (width, _candidate_land_height_max);
2344             evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3]);
2345             evas_object_move (_candidate_area_2, 0, _candidate_land_height_min);
2346             evas_object_move (_scroller_bg, 0, _candidate_land_height_min);
2347             evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2348         } else {
2349             if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2350                 _ise_height > _candidate_port_height_max - _candidate_port_height_min)
2351                 ui_candidate_window_resize (width, _candidate_port_height_min + _ise_height);
2352             else
2353                 ui_candidate_window_resize (width, _candidate_port_height_max);
2354             evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
2355             evas_object_move (_candidate_area_2, 0, _candidate_port_height_min);
2356             evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
2357             evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2358         }
2359     } else {
2360         evas_object_hide (_aux_line);
2361         evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2362         if (_candidate_angle == 90 || _candidate_angle == 270) {
2363             ui_candidate_window_resize (width, _candidate_land_height_min);
2364             evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3]);
2365             evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2366         } else {
2367             ui_candidate_window_resize (width, _candidate_port_height_min);
2368             evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
2369             evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2370         }
2371     }
2372 }
2373
2374 /**
2375  * @brief Rotate candidate window.
2376  *
2377  * @param angle The angle of candidate window.
2378  */
2379 static void ui_candidate_window_rotate (int angle)
2380 {
2381     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2382     if (!_candidate_window)
2383         return;
2384
2385     ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
2386
2387     if (angle == 90 || angle == 270) {
2388         _candidate_scroll_width = _candidate_scroll_width_max;
2389         ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
2390         evas_object_resize (_aux_area, _aux_land_width, _aux_height);
2391         evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_max, _item_min_height);
2392         evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_min);
2393         evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_min + 6);
2394     } else {
2395         _candidate_scroll_width = _candidate_scroll_width_min;
2396         ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
2397         evas_object_resize (_aux_area, _aux_port_width, _aux_height);
2398         evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
2399         evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_max);
2400         evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
2401     }
2402
2403     evas_object_hide (_candidate_area_2);
2404     _candidate_area_2_visible = false;
2405     ui_candidate_window_adjust ();
2406     if (_candidate_area_1_visible) {
2407         update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2408         ui_tts_focus_rect_hide ();
2409     }
2410     flush_memory ();
2411 }
2412
2413 /**
2414  * @brief This function is used to judge whether candidate window should be hidden.
2415  *
2416  * @return true if candidate window should be hidden, otherwise return false.
2417  */
2418 static bool ui_candidate_can_be_hide (void)
2419 {
2420     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2421
2422     if (_aux_area_visible || _candidate_area_1_visible || _candidate_area_2_visible)
2423         return false;
2424     else
2425         return true;
2426 }
2427
2428 /**
2429  * @brief Delete check candidate window size timer.
2430  *
2431  * @return void
2432  */
2433 static void ui_candidate_delete_check_size_timer (void)
2434 {
2435     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2436
2437     if (_check_size_timer != NULL) {
2438         ecore_timer_del (_check_size_timer);
2439         _check_size_timer = NULL;
2440     }
2441 }
2442
2443 /**
2444  * @brief Callback function for check candidate window size timer.
2445  *
2446  * @param data Data to pass when it is called.
2447  *
2448  * @return ECORE_CALLBACK_CANCEL
2449  */
2450 static Eina_Bool ui_candidate_check_size_timeout (void *data)
2451 {
2452     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2453
2454     ui_candidate_delete_check_size_timer ();
2455     ui_candidate_window_resize (_candidate_width, _candidate_height);
2456     ui_settle_candidate_window ();
2457     return ECORE_CALLBACK_CANCEL;
2458 }
2459
2460 /**
2461  * @brief Delete longpress timer.
2462  *
2463  * @return void
2464  */
2465 static void ui_candidate_delete_longpress_timer (void)
2466 {
2467     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2468
2469     if (_longpress_timer != NULL) {
2470         ecore_timer_del (_longpress_timer);
2471         _longpress_timer = NULL;
2472     }
2473 }
2474
2475 /**
2476  * @brief Callback function for candidate longpress timer.
2477  *
2478  * @param data Data to pass when it is called.
2479  *
2480  * @return ECORE_CALLBACK_CANCEL
2481  */
2482 static Eina_Bool ui_candidate_longpress_timeout (void *data)
2483 {
2484     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2485
2486     int index = (int)GPOINTER_TO_INT (data);
2487     ui_candidate_delete_longpress_timer ();
2488     _is_click = false;
2489     _info_manager->send_longpress_event (_click_object, index);
2490     return ECORE_CALLBACK_CANCEL;
2491 }
2492
2493 /**
2494  * @brief Delete destroy timer.
2495  *
2496  * @return void
2497  */
2498 static void ui_candidate_delete_destroy_timer (void)
2499 {
2500     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2501
2502     if (_destroy_timer != NULL) {
2503         ecore_timer_del (_destroy_timer);
2504         _destroy_timer = NULL;
2505     }
2506 }
2507
2508 /**
2509  * @brief Callback function for destroy timer.
2510  *
2511  * @param data Data to pass when it is called.
2512  *
2513  * @return ECORE_CALLBACK_CANCEL
2514  */
2515 static Eina_Bool ui_candidate_destroy_timeout (void *data)
2516 {
2517     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2518
2519     ui_candidate_delete_destroy_timer ();
2520     ui_destroy_candidate_window ();
2521     return ECORE_CALLBACK_CANCEL;
2522 }
2523 #endif /* CANDIDATE */
2524
2525 #ifdef HAVE_ECOREX
2526 /**
2527  * @brief Callback function for off_prepare_done.
2528  *
2529  * @param data Data to pass when it is called.
2530  *
2531  * @return ECORE_CALLBACK_CANCEL
2532  */
2533 static Eina_Bool off_prepare_done_timeout (void *data)
2534 {
2535     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2536
2537     /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
2538     // WILL_HIDE_REQUEST_DONE Ack to WM
2539     Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
2540     //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
2541     LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
2542             root_window, _control_window);
2543     _off_prepare_done_timer = NULL;
2544
2545     return ECORE_CALLBACK_CANCEL;
2546 }
2547 #endif /* HAVE_ECOREX */
2548
2549 #if ISF_BUILD_CANDIDATE_UI
2550 /**
2551  * @brief Delete candidate hide timer.
2552  *
2553  * @return void
2554  */
2555 static void delete_candidate_hide_timer (void)
2556 {
2557     LOGD ("deleting candidate_hide_timer");
2558     if (_candidate_hide_timer) {
2559         ecore_timer_del (_candidate_hide_timer);
2560         _candidate_hide_timer = NULL;
2561     }
2562 }
2563
2564 static void candidate_window_hide (void)
2565 {
2566     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2567
2568     delete_candidate_hide_timer ();
2569     _candidate_state = WINDOW_STATE_HIDE;
2570
2571     LOGD ("evas_object_hide (_candidate_window, %p)", elm_win_xwindow_get (_candidate_window));
2572
2573     if (_candidate_window) {
2574         /* There are cases that when there are rapid ISE_HIDE and ISE_SHOW requests,
2575            candidate window should be displayed but STATE_OFF for the first ISE_HIDE
2576            calls this function, so when the candidate window is shown by the following
2577            STATE_ON message, a blank area is displayed in candidate window -
2578            so we let the _candidate_area_1 as the default area that would be displayed */
2579         //evas_object_hide (_candidate_area_1);
2580         //evas_object_hide (_more_btn);
2581         _candidate_area_1_visible = false;
2582
2583         evas_object_hide (_candidate_window);
2584         SCIM_DEBUG_MAIN (3) << "    Hide candidate window\n";
2585     }
2586 }
2587
2588 /**
2589  * @brief Callback function for candidate hide timer
2590  *
2591  * @param data Data to pass when it is called.
2592  *
2593  * @return ECORE_CALLBACK_CANCEL
2594  */
2595 static Eina_Bool candidate_hide_timer (void *data)
2596 {
2597     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2598
2599     LOGD ("calling candidate_window_hide ()");
2600     candidate_window_hide ();
2601
2602     return ECORE_CALLBACK_CANCEL;
2603 }
2604
2605 #ifdef HAVE_ECOREX
2606 /**
2607  * @brief Delete candidate show handler.
2608  *
2609  * @return void
2610  */
2611 static void delete_candidate_show_handler (void)
2612 {
2613     if (_candidate_show_handler) {
2614         ecore_event_handler_del (_candidate_show_handler);
2615         _candidate_show_handler = NULL;
2616     }
2617 }
2618
2619 /**
2620  * @brief Callback function for window show completion event
2621  *
2622  * @param data Data to pass when it is called.
2623  *
2624  * @return ECORE_CALLBACK_CANCEL
2625  */
2626
2627 static Eina_Bool x_event_window_show_cb (void *data, int ev_type, void *event)
2628 {
2629     delete_candidate_show_handler ();
2630
2631     Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
2632     if (_candidate_state == WINDOW_STATE_WILL_SHOW) {
2633         if (e->win == elm_win_xwindow_get (_candidate_window)) {
2634             LOGD ("Candidate window show callback");
2635
2636             /* If our candidate window is in WILL_SHOW state and this show callback was called,
2637                now we are finally displayed on to the screen */
2638             _candidate_state = WINDOW_STATE_SHOW;
2639
2640             /* Update the geometry information for auto scrolling */
2641             set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2642             _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2643             _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2644
2645             /* And the state event */
2646             _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2647
2648             /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2649             if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2650                 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2651                     _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2652                 }
2653             }
2654         }
2655     } else {
2656         if (e->win == elm_win_xwindow_get (_candidate_window)) {
2657             LOGD ("Candidate window show callback, but _candidate_state is %d", _candidate_state);
2658         }
2659     }
2660
2661     return ECORE_CALLBACK_CANCEL;
2662 }
2663 #endif /* HAVE_ECOREX */
2664
2665 /**
2666  * @brief Show candidate window.
2667  *
2668  * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2669  */
2670 static void ui_candidate_show (bool bSetVirtualKbd)
2671 {
2672     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2673
2674     delete_candidate_hide_timer ();
2675
2676     if (!_candidate_window) return;
2677     if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
2678         return;
2679
2680     /* FIXME : SHOULD UNIFY THE METHOD FOR CHECKING THE HW KEYBOARD EXISTENCE */
2681     /* If the ISE is not visible currently, wait for the ISE to be opened and then show our candidate window */
2682     _candidate_show_requested = true;
2683     if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) && (_ise_state != WINDOW_STATE_SHOW)) {
2684         LOGD ("setting _show_candidate_requested to TRUE");
2685         return;
2686     }
2687
2688     /* If the ISE angle is valid, respect the value to make sure
2689        the candidate window always have the same angle with ISE */
2690     if (_ise_angle != -1) {
2691         _candidate_angle = _ise_angle;
2692     }
2693     ui_candidate_window_rotate (_candidate_angle);
2694
2695     /* If the candidate window was about to hide, turn it back to SHOW state now */
2696     if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
2697         _candidate_state = WINDOW_STATE_SHOW;
2698     }
2699
2700     /* Change to WILL_SHOW state only when we are not currently in SHOW state */
2701     if (_candidate_state != WINDOW_STATE_SHOW) {
2702         _candidate_state = WINDOW_STATE_WILL_SHOW;
2703     }
2704
2705 #ifdef HAVE_ECOREX
2706     if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2707         /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
2708         // Unset conformant area
2709         Ecore_X_Window current_app_window = efl_get_app_window ();
2710         if (_app_window != current_app_window) {
2711             struct rectinfo info = {0, 0, 0, 0};
2712             info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
2713             set_keyboard_geometry_atom_info (_app_window, info);
2714             LOGD ("Conformant reset for window %x", _app_window);
2715             _app_window = current_app_window;
2716         }
2717     }
2718
2719     if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2720         if (bSetVirtualKbd) {
2721             set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2722         }
2723     }
2724     efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
2725 #endif
2726
2727     ui_candidate_delete_check_size_timer ();
2728     _check_size_timer = ecore_timer_add (0.02, ui_candidate_check_size_timeout, NULL);
2729
2730     SCIM_DEBUG_MAIN (3) << "    Show candidate window\n";
2731
2732     if (_ise_state == WINDOW_STATE_SHOW) {
2733         edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
2734         edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
2735     } else {
2736         edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
2737         edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
2738     }
2739
2740     /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2741     if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2742         if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2743             LOGD ("sending ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW");
2744             _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
2745         }
2746     }
2747
2748     if (_candidate_state != WINDOW_STATE_SHOW) {
2749 #ifdef HAVE_ECOREX
2750         if (_candidate_show_handler) {
2751             LOGD ("Was still waiting for CANDIDATE_WINDOW_SHOW....");
2752         } else {
2753             delete_candidate_show_handler ();
2754             LOGD ("Registering ECORE_X_EVENT_WINDOW_SHOW event, %d", _candidate_state);
2755             _candidate_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_window_show_cb, NULL);
2756         }
2757 #endif
2758     } else {
2759         LOGD ("The candidate window was already in SHOW state, update geometry information");
2760         _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2761         _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2762
2763         /* And the state event */
2764         _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2765
2766         /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2767         if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2768             if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2769                 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2770             }
2771         }
2772     }
2773
2774     evas_object_show (_candidate_window);
2775 }
2776
2777 /**
2778  * @brief Hide candidate window.
2779  *
2780  * @param bForce The flag to hide candidate window by force.
2781  * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2782  */
2783 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd, bool will_hide)
2784 {
2785     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " bForce:" << bForce << " bSetVirtualKbd:" << bSetVirtualKbd << " will_hide:" << will_hide << "...\n";
2786
2787     if (!_candidate_window)
2788         return;
2789
2790     if (bForce) {
2791         if (_candidate_area_2 && _candidate_area_2_visible) {
2792             evas_object_hide (_candidate_area_2);
2793             _candidate_area_2_visible = false;
2794             evas_object_hide (_scroller_bg);
2795             evas_object_hide (_close_btn);
2796             _info_manager->candidate_more_window_hide ();
2797             ui_candidate_window_adjust ();
2798         }
2799     }
2800
2801     if (bForce || ui_candidate_can_be_hide ()) {
2802         if (will_hide) {
2803             LOGD ("candidate_state = WILL_HIDE");
2804             _candidate_state = WINDOW_STATE_WILL_HIDE;
2805
2806             delete_candidate_hide_timer ();
2807             _candidate_hide_timer = ecore_timer_add (2.0, candidate_hide_timer, NULL);
2808         }
2809
2810         if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2811             _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2812             /* FIXME : should check if bSetVirtualKbd flag is really needed in this case */
2813 #ifdef HAVE_ECOREX
2814             if (_ise_state == WINDOW_STATE_SHOW) {
2815                 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2816             } else {
2817                 if (bSetVirtualKbd) {
2818                     set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2819                 }
2820             }
2821 #endif
2822             if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2823                 _info_manager->update_input_panel_event
2824                     ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_HIDE);
2825             }
2826         }
2827
2828         /* Update the new keyboard geometry first, and then send the candidate hide event */
2829         _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_HIDE);
2830
2831         if (!will_hide) {
2832             /* If we are not in will_hide state, hide the candidate window immediately */
2833             candidate_window_hide ();
2834
2835             if (_preedit_window)
2836                 evas_object_hide (_preedit_window);
2837         }
2838     }
2839 }
2840
2841 /**
2842  * @brief Callback function for more button.
2843  *
2844  * @param data Data to pass when it is called.
2845  * @param e The evas for current event.
2846  * @param button The evas object for current event.
2847  * @param event_info The information for current event.
2848  */
2849 static void ui_candidate_window_more_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2850 {
2851     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2852
2853     _info_manager->candidate_more_window_show ();
2854
2855     if (candidate_expanded == false) {
2856         candidate_expanded = true;
2857         int number = SCIM_LOOKUP_TABLE_MAX_PAGESIZE;
2858         for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
2859             if (_candidate_0 [i] == NULL) {
2860                 number = i;
2861                 break;
2862             }
2863         }
2864         if (g_isf_candidate_table.get_current_page_size () != number)
2865             update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2866     }
2867
2868     if (_candidate_angle == 180) {
2869         Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2870         ecore_evas_move_resize (ee, 0, 0, 0, 0);
2871         LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2872     } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2873         /*
2874          * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2875          * candidates, but it will flash or locate in a wrong position, this code just a workaround
2876          * for avoiding this situation.
2877          */
2878         Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2879         ecore_evas_move_resize (ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2880         LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2881             ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2882     }
2883
2884     evas_object_show (_candidate_area_2);
2885     _candidate_area_2_visible = true;
2886     evas_object_show (_scroller_bg);
2887     evas_object_hide (_more_btn);
2888     evas_object_show (_close_btn);
2889
2890     ui_candidate_window_adjust ();
2891     ui_settle_candidate_window ();
2892     flush_memory ();
2893 }
2894
2895 /**
2896  * @brief Callback function for close button.
2897  *
2898  * @param data Data to pass when it is called.
2899  * @param e The evas for current event.
2900  * @param button The evas object for current event.
2901  * @param event_info The information for current event.
2902  */
2903 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2904 {
2905     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2906
2907     if (_candidate_area_2 == NULL || !_candidate_area_2_visible)
2908         return;
2909
2910     _info_manager->candidate_more_window_hide ();
2911
2912     evas_object_hide (_candidate_area_2);
2913     _candidate_area_2_visible = false;
2914     evas_object_hide (_scroller_bg);
2915     evas_object_hide (_close_btn);
2916
2917     candidate_expanded = false;
2918     evas_object_show (_candidate_area_1);
2919     _candidate_area_1_visible = true;
2920     evas_object_show (_more_btn);
2921
2922     elm_scroller_region_show (_candidate_area_2, 0, 0, _candidate_scroll_width, 100);
2923     if (_candidate_angle == 180) {
2924         Ecore_Evas *ee= ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2925         ecore_evas_move_resize (ee, 0, 0, 0, 0);
2926         LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2927     } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2928         /*
2929          * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2930          * candidates, but it will flash or locate in a wrong position, this code just a workaround
2931          * for avoiding this situation.
2932          */
2933         Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2934         ecore_evas_move_resize (ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2935         LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2936             ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2937     }
2938
2939     ui_candidate_window_adjust ();
2940     ui_settle_candidate_window ();
2941     flush_memory ();
2942 }
2943
2944 /**
2945  * @brief Callback function for mouse button press.
2946  *
2947  * @param data Data to pass when it is called.
2948  * @param e The evas for current event.
2949  * @param button The evas object for current event.
2950  * @param event_info The information for current event.
2951  */
2952 static void ui_mouse_button_pressed_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2953 {
2954     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2955
2956     _click_object = GPOINTER_TO_INT (data) & 0xFF;
2957     _is_click     = true;
2958
2959     Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
2960     if (!ev) return;
2961
2962     _click_down_pos [0] = ev->canvas.x;
2963     _click_down_pos [1] = ev->canvas.y;
2964
2965     if (_click_object == ISF_EFL_CANDIDATE_0 || _click_object == ISF_EFL_CANDIDATE_ITEMS) {
2966         int index = (int)GPOINTER_TO_INT (data) >> 8;
2967
2968 #ifdef HAVE_FEEDBACK
2969         if (feedback_initialized) {
2970             int feedback_result = 0;
2971             bool sound_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_SOUND_FEEDBACK, false);
2972
2973             if (sound_feedback) {
2974                 feedback_result = feedback_play_type (FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_SIP);
2975
2976                 if (FEEDBACK_ERROR_NONE == feedback_result)
2977                     LOGD ("Sound play successful");
2978                 else
2979                     LOGW ("Cannot play feedback sound : %d", feedback_result);
2980             }
2981
2982             bool vibrate_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_VIBRATION_FEEDBACK, false);
2983
2984             if (vibrate_feedback) {
2985                 feedback_result = feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
2986
2987                 if (FEEDBACK_ERROR_NONE == feedback_result)
2988                     LOGD ("Vibration play successful");
2989                 else
2990                     LOGW ("Cannot play feedback vibration : %d", feedback_result);
2991             }
2992         }
2993 #endif
2994
2995         ui_candidate_delete_longpress_timer ();
2996         _longpress_timer = ecore_timer_add (1.0, ui_candidate_longpress_timeout, (void *)index);
2997     }
2998 }
2999
3000 /**
3001  * @brief Callback function for mouse button release.
3002  *
3003  * @param data Data to pass when it is called.
3004  * @param e The evas for current event.
3005  * @param button The evas object for current event.
3006  * @param event_info The information for current event.
3007  */
3008 static void ui_mouse_button_released_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3009 {
3010     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " index:" << GPOINTER_TO_INT (data) << "...\n";
3011
3012     ui_candidate_delete_longpress_timer ();
3013
3014     int index = GPOINTER_TO_INT (data);
3015     if (_click_object == ISF_EFL_AUX && _is_click) {
3016 /*      double ret = 0;
3017         const char *buf = edje_object_part_state_get (button, "aux", &ret);
3018         if (strcmp ("selected", buf)) {
3019             for (unsigned int i = 0; i < _aux_items.size (); i++) {
3020                 buf = edje_object_part_state_get (_aux_items [i], "aux", &ret);
3021                 if (!strcmp ("selected", buf))
3022                     edje_object_signal_emit (_aux_items [i], "aux,state,unselected", "aux");
3023             }
3024             edje_object_signal_emit (button, "aux,state,selected", "aux");
3025             _info_manager->select_aux (index);
3026         }*/
3027         int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
3028         edje_object_color_class_get (_aux_items [index], "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
3029         // Normal item is clicked
3030         if (!(r == 62 && g == 207 && b == 255)) {
3031             for (unsigned int i = 0; i < _aux_items.size (); i++) {
3032                 edje_object_color_class_set (_aux_items [i], "text_color", 249, 249, 249, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3033             }
3034             edje_object_color_class_set (_aux_items [index], "text_color", 62, 207, 255, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3035             _info_manager->select_aux (index);
3036         }
3037     } else if (_click_object == ISF_EFL_CANDIDATE_0 && _is_click) {
3038         ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3039         _info_manager->select_candidate (index);
3040     } else if (_click_object == ISF_EFL_CANDIDATE_ITEMS && _is_click) {
3041         ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3042         _info_manager->select_candidate (index);
3043     }
3044 }
3045
3046 /**
3047  * @brief Callback function for mouse move.
3048  *
3049  * @param data Data to pass when it is called.
3050  * @param e The evas for current event.
3051  * @param button The evas object for current event.
3052  * @param event_info The information for current event.
3053  */
3054 static void ui_mouse_moved_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3055 {
3056     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3057
3058     Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
3059     if (!ev) return;
3060
3061     _click_up_pos [0] = ev->canvas.x;
3062     _click_up_pos [1] = ev->canvas.y;
3063
3064     if (abs (_click_up_pos [0] - _click_down_pos [0]) >= (int)(15 * _height_rate) ||
3065         abs (_click_up_pos [1] - _click_down_pos [1]) >= (int)(15 * _height_rate)) {
3066         _is_click = false;
3067         ui_candidate_delete_longpress_timer ();
3068     }
3069 }
3070
3071 /**
3072  * @brief Show rect for candidate focus object when screen reader is enabled.
3073  *
3074  * @param x Rect X position.
3075  * @param y Rect Y position.
3076  * @param w Rect width.
3077  * @param h Rect height.
3078  */
3079 static void ui_tts_focus_rect_show (int x, int y, int w, int h)
3080 {
3081     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3082     if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
3083         return;
3084
3085     if (_tts_focus_rect == NULL) {
3086         _tts_focus_rect = evas_object_rectangle_add (evas_object_evas_get ((Evas_Object*)_candidate_window));
3087         evas_object_color_set (_tts_focus_rect, 0, 0, 0, 0);
3088         elm_access_highlight_set (elm_access_object_register (_tts_focus_rect, (Evas_Object*)_candidate_window));
3089     }
3090     evas_object_move (_tts_focus_rect, x, y);
3091     evas_object_resize (_tts_focus_rect, w, h);
3092     evas_object_raise (_tts_focus_rect);
3093     evas_object_show (_tts_focus_rect);
3094 }
3095
3096 /**
3097  * @brief Hide rect for candidate focus object when screen reader is enabled.
3098  */
3099 static void ui_tts_focus_rect_hide (void)
3100 {
3101     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3102
3103     if (_tts_focus_rect) {
3104         //evas_object_hide (_tts_focus_rect);
3105         evas_object_move (_tts_focus_rect, -1000, -1000);
3106     }
3107 }
3108
3109 /**
3110  * @brief Callback function for candidate scroller stop event.
3111  *
3112  * @param data Data to pass when it is called.
3113  * @param obj The evas object for current event.
3114  * @param event_info The information for current event.
3115  */
3116 static void ui_candidate_scroller_stop_cb (void *data, Evas_Object *obj, void *event_info)
3117 {
3118     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3119     if (!_wait_stop_event)
3120         return;
3121
3122     if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
3123         if (_candidate_0 [_candidate_tts_focus_index]) {
3124             int x, y, w, h;
3125             evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
3126             ui_tts_focus_rect_show (x, y, w, h);
3127         }
3128     }
3129     _wait_stop_event = false;
3130 }
3131
3132 /**
3133  * @brief Create preedit window.
3134  */
3135 static void ui_create_preedit_window (void)
3136 {
3137     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3138
3139     if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3140         return;
3141
3142     _preedit_width  = 100;
3143     _preedit_height = _preedit_height * _height_rate;
3144     if (_preedit_window == NULL) {
3145         _preedit_window = efl_create_window ("ISF Popup", "Preedit Window");
3146         evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
3147         int rots [4] = {0, 90, 180, 270};
3148         elm_win_wm_rotation_available_rotations_set (_preedit_window, rots, 4);
3149         int preedit_font_size = (int)(32 * _width_rate);
3150
3151         _preedit_text = edje_object_add (evas_object_evas_get (_preedit_window));
3152         edje_object_file_set (_preedit_text, _candidate_edje_file.c_str (), "preedit_text");
3153         evas_object_size_hint_fill_set (_preedit_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
3154         evas_object_size_hint_weight_set (_preedit_text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3155         elm_win_resize_object_add (_preedit_window, _preedit_text);
3156         evas_object_show (_preedit_text);
3157
3158         _tmp_preedit_text = evas_object_text_add (evas_object_evas_get (_preedit_window));
3159         evas_object_text_font_set (_tmp_preedit_text, _candidate_font_name.c_str (), preedit_font_size);
3160     }
3161 }
3162
3163 /**
3164  * @brief Create native style candidate window.
3165  */
3166 static void ui_create_native_candidate_window (void)
3167 {
3168     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3169     _more_btn_width = 80 * (_width_rate > 1 ? 1 : _width_rate);
3170     _more_btn_height = 64 * _height_rate;
3171
3172     _candidate_port_width        = _screen_width;
3173     _candidate_port_height_min   = 84 * _height_rate * _candidate_port_line;
3174     _candidate_port_height_min_2 = 84 * _height_rate + _candidate_port_height_min;
3175     _candidate_port_height_max   = 426 * _height_rate + _candidate_port_height_min;
3176     _candidate_port_height_max_2 = 84 * _height_rate + _candidate_port_height_max;
3177     _candidate_land_width        = _screen_height;
3178     _candidate_land_height_min   = 84 * _width_rate;
3179     _candidate_land_height_min_2 = 168 * _width_rate;
3180     _candidate_land_height_max   = 342 * _width_rate;
3181     _candidate_land_height_max_2 = 426 * _width_rate;
3182
3183     _candidate_scroll_0_width_min= _screen_width;
3184     _candidate_scroll_0_width_max= _screen_height;
3185     _candidate_scroll_width_min  = _screen_width;
3186     _candidate_scroll_width_max  = _screen_height;
3187     _candidate_scroll_height_min = 252 * _width_rate;
3188     _candidate_scroll_height_max = 420 * _height_rate;
3189
3190     _candidate_area_1_pos [0]    = 0 * _width_rate;
3191     _candidate_area_1_pos [1]    = 2 * _height_rate;
3192     _more_btn_pos [0]            = _candidate_port_width - _more_btn_width - _h_padding;
3193     _more_btn_pos [1]            = 12 * _height_rate;
3194     _more_btn_pos [2]            = _candidate_land_width - _more_btn_width - _h_padding;
3195     _more_btn_pos [3]            = 12 * _width_rate;
3196     _close_btn_pos [0]           = _candidate_port_width - _more_btn_width - _h_padding;
3197     _close_btn_pos [1]           = 12 * _height_rate;
3198     _close_btn_pos [2]           = _candidate_land_width - _more_btn_width - _h_padding;
3199     _close_btn_pos [3]           = 12 * _width_rate;
3200
3201     _aux_height                  = 84 * _height_rate - 2;
3202     _aux_port_width              = _screen_width;
3203     _aux_land_width              = _screen_height;
3204
3205     _item_min_height             = 84 * _height_rate - 2;
3206
3207     /* Create candidate window */
3208     if (_candidate_window == NULL) {
3209         _candidate_window = efl_create_window ("ISF Popup", "Prediction Window");
3210         int rots [4] = {0, 90, 180, 270};
3211         elm_win_wm_rotation_available_rotations_set (_candidate_window, rots, 4);
3212         if (_candidate_angle == 90 || _candidate_angle == 270) {
3213             _candidate_width  = _candidate_land_width;
3214             _candidate_height = _candidate_land_height_min;
3215         } else {
3216             _candidate_width  = _candidate_port_width;
3217             _candidate_height = _candidate_port_height_min;
3218         }
3219 #ifdef HAVE_ECOREX
3220         /*
3221         ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3222                 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3223         ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3224                 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3225         ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3226                 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3227         ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3228                 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3229         */
3230 #else
3231         ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3232                 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3233         ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3234                 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3235         ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3236                 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3237         ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3238                 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3239 #endif
3240         /* Add dim background */
3241         Evas_Object *dim_bg = elm_bg_add (_candidate_window);
3242         evas_object_color_set (dim_bg, 0, 0, 0, 153);
3243         elm_win_resize_object_add (_candidate_window, dim_bg);
3244         evas_object_show (dim_bg);
3245
3246         /* Add candidate background */
3247         _candidate_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3248         edje_object_file_set (_candidate_bg, _candidate_edje_file.c_str (), "candidate_bg");
3249         evas_object_size_hint_weight_set (_candidate_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3250         evas_object_resize (_candidate_bg, _candidate_port_width, _candidate_port_height_min);
3251         evas_object_move (_candidate_bg, 0, 0);
3252         evas_object_show (_candidate_bg);
3253
3254         /* Create _candidate_0 scroller */
3255         _candidate_0_scroll = elm_scroller_add (_candidate_window);
3256         elm_scroller_bounce_set (_candidate_0_scroll, EINA_TRUE, EINA_FALSE);
3257         elm_scroller_policy_set (_candidate_0_scroll, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3258         evas_object_resize (_candidate_0_scroll, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
3259         evas_object_move (_candidate_0_scroll, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3260
3261         /* Create candidate table */
3262         _candidate_0_table = elm_table_add (_candidate_window);
3263         evas_object_size_hint_weight_set (_candidate_0_table, 0.0, 0.0);
3264         evas_object_size_hint_align_set (_candidate_0_table, 0.0, 0.0);
3265         elm_table_padding_set (_candidate_0_table, 0, 0);
3266         elm_object_content_set (_candidate_0_scroll, _candidate_0_table);
3267         evas_object_show (_candidate_0_table);
3268         _candidate_area_1 = _candidate_0_scroll;
3269
3270         /* Create more button */
3271         _more_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3272         if (_ise_width == 0 && _ise_height == 0)
3273             edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
3274         else
3275             edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
3276         evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
3277         evas_object_resize (_more_btn, _more_btn_width, _more_btn_height);
3278         evas_object_event_callback_add (_more_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_more_button_cb, NULL);
3279
3280         /* Add scroller background */
3281         _candidate_scroll_width = _candidate_scroll_width_min;
3282         _scroller_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3283         edje_object_file_set (_scroller_bg, _candidate_edje_file.c_str (), "scroller_bg");
3284         evas_object_size_hint_weight_set (_scroller_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3285         evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3286         evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
3287
3288         /* Create vertical scroller */
3289         _candidate_scroll = elm_scroller_add (_candidate_window);
3290         elm_scroller_bounce_set (_candidate_scroll, 0, 1);
3291         elm_scroller_policy_set (_candidate_scroll, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
3292         evas_object_resize (_candidate_scroll, _candidate_scroll_width, _candidate_scroll_height_max);
3293         evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3294         elm_scroller_page_size_set (_candidate_scroll, 0, _item_min_height+_v_padding);
3295         evas_object_move (_candidate_scroll, 0, _candidate_port_height_min);
3296
3297         /* Create candidate table */
3298         _candidate_table = elm_table_add (_candidate_window);
3299         evas_object_size_hint_weight_set (_candidate_table, 0.0, 0.0);
3300         evas_object_size_hint_align_set (_candidate_table, 0.0, 0.0);
3301         elm_table_padding_set (_candidate_table, 0, 0);
3302         elm_object_content_set (_candidate_scroll, _candidate_table);
3303         evas_object_show (_candidate_table);
3304         _candidate_area_2 = _candidate_scroll;
3305         evas_object_smart_callback_add (_candidate_scroll, "scroll,anim,stop", ui_candidate_scroller_stop_cb, NULL);
3306
3307         /* Create close button */
3308         _close_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3309         if (_ise_width == 0 && _ise_height == 0)
3310             edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
3311         else
3312             edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
3313         evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
3314         evas_object_resize (_close_btn, _more_btn_width, _more_btn_height);
3315         evas_object_event_callback_add (_close_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_close_button_cb, NULL);
3316
3317         _tmp_candidate_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3318         evas_object_text_font_set (_tmp_candidate_text, _candidate_font_name.c_str (), _candidate_font_size);
3319
3320         /* Create aux */
3321         _aux_area = elm_scroller_add (_candidate_window);
3322         elm_scroller_bounce_set (_aux_area, 1, 0);
3323         elm_scroller_policy_set (_aux_area, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3324         evas_object_resize (_aux_area, _aux_port_width, _aux_height);
3325         evas_object_move (_aux_area, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3326
3327         _aux_table = elm_table_add (_candidate_window);
3328         elm_object_content_set (_aux_area, _aux_table);
3329         elm_table_padding_set (_aux_table, 0, 0);
3330         evas_object_size_hint_weight_set (_aux_table, 0.0, 0.0);
3331         evas_object_size_hint_align_set (_aux_table, 0.0, 0.0);
3332         evas_object_show (_aux_table);
3333
3334         _aux_line = edje_object_add (evas_object_evas_get (_candidate_window));
3335         edje_object_file_set (_aux_line, _candidate_edje_file.c_str (), "popup_line");
3336         evas_object_resize (_aux_line, _candidate_port_width, 2);
3337         evas_object_move (_aux_line, 0, _aux_height + 2);
3338
3339         _tmp_aux_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3340         evas_object_text_font_set (_tmp_aux_text, _candidate_font_name.c_str (), _aux_font_size);
3341     } else {
3342         evas_object_hide (_candidate_window);
3343     }
3344
3345     flush_memory ();
3346 }
3347
3348 /**
3349  * @brief Create candidate window.
3350  *
3351  * @return void
3352  */
3353 static void ui_create_candidate_window (void)
3354 {
3355     check_time ("\nEnter ui_create_candidate_window");
3356     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3357     if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3358         return;
3359
3360     _candidate_x     = 0;
3361     _candidate_y     = 0;
3362     _candidate_angle = 0;
3363
3364     ui_create_native_candidate_window ();
3365
3366 #ifdef HAVE_ECOREX
3367     unsigned int set = 1;
3368
3369     ecore_x_window_prop_card32_set (elm_win_xwindow_get (_candidate_window),
3370             ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
3371             &set, 1);
3372 #endif
3373     int angle = efl_get_app_window_angle ();
3374     if (_candidate_angle != angle) {
3375         _candidate_angle = angle;
3376         ui_candidate_window_rotate (angle);
3377     } else {
3378         ui_settle_candidate_window ();
3379     }
3380
3381     candidate_expanded = false;
3382
3383     check_time ("Exit ui_create_candidate_window");
3384 }
3385
3386 /**
3387  * @brief Destroy candidate window.
3388  *
3389  * @return void
3390  */
3391 static void ui_destroy_candidate_window (void)
3392 {
3393     check_time ("Enter ui_destroy_candidate_window");
3394     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3395
3396     /* Delete candidate items, popup lines and seperator items */
3397     for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3398         if (_candidate_0 [i]) {
3399             evas_object_del (_candidate_0 [i]);
3400             _candidate_0 [i] = NULL;
3401         }
3402         if (_seperate_0 [i]) {
3403             evas_object_del (_seperate_0 [i]);
3404             _seperate_0 [i] = NULL;
3405         }
3406         if (_seperate_items [i]) {
3407             evas_object_del (_seperate_items [i]);
3408             _seperate_items [i] = NULL;
3409         }
3410         if (_line_0 [i]) {
3411             evas_object_del (_line_0 [i]);
3412             _line_0 [i] = NULL;
3413         }
3414         if (_line_items [i]) {
3415             evas_object_del (_line_items [i]);
3416             _line_items [i] = NULL;
3417         }
3418     }
3419
3420     _aux_items.clear ();
3421     _aux_seperates.clear ();
3422     /* Delete candidate window */
3423     if (_candidate_window) {
3424         LOGD ("calling ui_candidate_hide (true)");
3425         ui_candidate_hide (true);
3426
3427         evas_object_del (_candidate_window);
3428         _candidate_window = NULL;
3429         _aux_area         = NULL;
3430         _candidate_area_1 = NULL;
3431         _candidate_area_2 = NULL;
3432     }
3433
3434     if (_tts_focus_rect) {
3435         evas_object_del (_tts_focus_rect);
3436         _tts_focus_rect = NULL;
3437     }
3438
3439     if (_candidate_bg) {
3440         evas_object_del (_candidate_bg);
3441         _candidate_bg = NULL;
3442     }
3443
3444     if (_more_btn) {
3445         evas_object_del (_more_btn);
3446         _more_btn = NULL;
3447     }
3448
3449     if (_scroller_bg) {
3450         evas_object_del (_scroller_bg);
3451         _scroller_bg = NULL;
3452     }
3453
3454     if (_close_btn) {
3455         evas_object_del (_close_btn);
3456         _close_btn = NULL;
3457     }
3458
3459     if (_aux_line) {
3460         evas_object_del (_aux_line);
3461         _aux_line = NULL;
3462     }
3463
3464     if (_tmp_candidate_text) {
3465         evas_object_del (_tmp_candidate_text);
3466         _tmp_candidate_text = NULL;
3467     }
3468
3469     if (_tmp_preedit_text) {
3470         evas_object_del (_tmp_preedit_text);
3471         _tmp_preedit_text = NULL;
3472     }
3473
3474     if (_tmp_aux_text) {
3475         evas_object_del (_tmp_aux_text);
3476         _tmp_aux_text = NULL;
3477     }
3478
3479     if (_preedit_text) {
3480         evas_object_del (_preedit_text);
3481         _preedit_text = NULL;
3482     }
3483
3484     if (_preedit_window) {
3485         evas_object_hide (_preedit_window);
3486         evas_object_del (_preedit_window);
3487         _preedit_window = NULL;
3488     }
3489
3490     flush_memory ();
3491     check_time ("Exit ui_destroy_candidate_window");
3492 }
3493
3494 /**
3495  * @brief Settle candidate window position.
3496  */
3497 static void ui_settle_candidate_window (void)
3498 {
3499     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3500
3501     if (!_candidate_window)
3502         return;
3503
3504     /* If both ISE and candidate window are going to be hidden,
3505        let's just not move our candidate window */
3506     if (_ise_state == WINDOW_STATE_WILL_HIDE && _candidate_state == WINDOW_STATE_WILL_HIDE)
3507         return;
3508
3509     int spot_x, spot_y;
3510     int x, y, width, height;
3511     int ise_width = 0, ise_height = 0;
3512     bool get_geometry_result = false;
3513
3514     /* Get candidate window position */
3515     ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
3516
3517 #ifdef HAVE_ECOREX
3518     /*
3519     int pos_x = 0, pos_y = 0;
3520     if (_candidate_angle == 90 || _candidate_angle == 270)
3521         get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_height, &ise_width);
3522     else
3523         get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_width, &ise_height);
3524     */
3525 #else
3526     spot_x = _ise_x;
3527     spot_y = _ise_y;
3528     ise_width = _ise_width;
3529     ise_height = _ise_height;
3530     get_geometry_result = true;
3531 #endif
3532     if ((_ise_state != WINDOW_STATE_SHOW && _ise_state != WINDOW_STATE_WILL_HIDE) ||
3533             (get_geometry_result == false) || (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
3534         ise_height = 0;
3535         ise_width = 0;
3536     }
3537
3538     int height2 = ui_candidate_get_valid_height ();
3539
3540     if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
3541         if (_candidate_angle == 90) {
3542             spot_x = _screen_width - ise_height - height2;
3543             spot_y = 0;
3544         } else if (_candidate_angle == 270) {
3545             spot_x = ise_height - (_candidate_height - height2);
3546             spot_y = 0;
3547         } else if (_candidate_angle == 180) {
3548             spot_x = 0;
3549             spot_y = ise_height - (_candidate_height - height2);
3550         } else {
3551             spot_x = 0;
3552             spot_y = _screen_height - ise_height - height2;
3553         }
3554     } else {
3555         spot_x = _spot_location_x;
3556         spot_y = _spot_location_y;
3557
3558         rectinfo ise_rect = {0, 0, (uint32)ise_width, (uint32)ise_height};
3559         if (_candidate_angle == 90 || _candidate_angle == 270) {
3560             if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32)_screen_width)
3561                 ise_rect.height = ISE_DEFAULT_HEIGHT_LANDSCAPE * _width_rate;
3562         } else {
3563             if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32) _screen_height)
3564                 ise_rect.height = ISE_DEFAULT_HEIGHT_PORTRAIT * _height_rate;
3565         }
3566
3567         int nOffset = _candidate_port_height_min / 3;
3568         if (_candidate_angle == 270) {
3569             if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3570                 spot_x = _screen_width - _spot_location_top_y - (_candidate_height - height2);
3571             } else {
3572                 spot_x = _screen_width - _spot_location_y - _candidate_height;
3573             }
3574         } else if (_candidate_angle == 90) {
3575             if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3576                 spot_x = _spot_location_top_y - height2;
3577             } else {
3578                 spot_x = spot_y;
3579             }
3580         } else if (_candidate_angle == 180) {
3581             if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3582                 spot_y = _screen_height - _spot_location_top_y - (_candidate_height - height2);
3583             } else {
3584                 spot_y = _screen_height - _spot_location_y - _candidate_height;
3585             }
3586         } else {
3587             if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3588                 spot_y = _spot_location_top_y - height2;
3589             }
3590         }
3591     }
3592
3593     if (_candidate_angle == 90) {
3594         spot_y = (_screen_height - _candidate_width) / 2;
3595         spot_x = spot_x < _indicator_height ? _indicator_height : spot_x;
3596         if (spot_x > _screen_width - _candidate_height)
3597             spot_x = _screen_width - _candidate_height;
3598     } else if (_candidate_angle == 270) {
3599         spot_y = (_screen_height - _candidate_width) / 2;
3600         spot_x = spot_x < 0 ? 0 : spot_x;
3601         if (spot_x > _screen_width - (_indicator_height+_candidate_height))
3602             spot_x = _screen_width - (_indicator_height+_candidate_height);
3603     } else if (_candidate_angle == 180) {
3604         spot_x = (_screen_width - _candidate_width) / 2;
3605         spot_y = spot_y < 0 ? 0 : spot_y;
3606         if (spot_y > _screen_height - (_indicator_height+_candidate_height))
3607             spot_y = _screen_height - (_indicator_height+_candidate_height);
3608     } else {
3609         spot_x = (_screen_width - _candidate_width) / 2;
3610         spot_y = spot_y < _indicator_height ? _indicator_height : spot_y;
3611         if (spot_y > _screen_height - _candidate_height)
3612             spot_y = _screen_height - _candidate_height;
3613     }
3614
3615     if (spot_x != x || spot_y != y) {
3616         _candidate_x = spot_x;
3617         _candidate_y = spot_y;
3618         evas_object_move (_candidate_window, spot_x, spot_y);
3619         LOGD ("Moving candidate window to : %d %d", spot_x, spot_y);
3620         if (_preedit_window) {
3621             if (_candidate_angle == 90) {
3622                 spot_x -= _preedit_height;
3623                 spot_y = _screen_height - _preedit_width;
3624             } else if (_candidate_angle == 270) {
3625                 spot_x += height2;
3626             } else if (_candidate_angle == 180) {
3627                 spot_x = _screen_width - _preedit_width;
3628                 spot_y += height2;
3629             } else {
3630                 spot_y -= _preedit_height;
3631             }
3632             evas_object_move (_preedit_window, spot_x, spot_y);
3633         }
3634         if (_candidate_state == WINDOW_STATE_SHOW) {
3635             _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
3636         }
3637     }
3638 }
3639 #endif /* CANDIDATE */
3640
3641 /**
3642  * @brief Set soft candidate geometry.
3643  *
3644  * @param x      The x position in screen.
3645  * @param y      The y position in screen.
3646  * @param width  The candidate window width.
3647  * @param height The candidate window height.
3648  */
3649 static void set_soft_candidate_geometry (int x, int y, int width, int height)
3650 {
3651     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
3652
3653     LOGD ("candidate geometry x: %d , y: %d , width: %d , height: %d, _ise_state: %d, candidate_mode: %d", x, y, width, height, _ise_state, _candidate_mode);
3654
3655     if ((_candidate_mode != SOFT_CANDIDATE_WINDOW) || (_info_manager->get_current_toolbar_mode () != TOOLBAR_KEYBOARD_MODE))
3656         return;
3657
3658 #ifdef HAVE_ECOREX
3659     _soft_candidate_width = width;
3660     _soft_candidate_height = height;
3661      set_keyboard_geometry_atom_info (_app_window, get_ise_geometry());
3662 #endif
3663     _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
3664 }
3665
3666 #if ISF_BUILD_CANDIDATE_UI
3667 //////////////////////////////////////////////////////////////////////
3668 // End of Candidate Functions
3669 //////////////////////////////////////////////////////////////////////
3670 #ifdef HAVE_ECOREX
3671 /**
3672  * @brief Set transient for app window.
3673  *
3674  * @param window The Ecore_X_Window handler of app window.
3675  */
3676 static void efl_set_transient_for_app_window (Ecore_X_Window window)
3677 {
3678     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3679
3680     /* Set a transient window for window stack */
3681     Ecore_X_Window   xAppWindow = efl_get_app_window ();
3682     ecore_x_icccm_transient_for_set (window, xAppWindow);
3683
3684     LOGD ("win : %x, forwin : %x", window, xAppWindow);
3685 }
3686
3687 static int efl_get_window_rotate_angle (Ecore_X_Window win)
3688 {
3689     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3690
3691     int ret;
3692     int count;
3693     int angle = 0;
3694     unsigned char *prop_data = NULL;
3695
3696     ret = ecore_x_window_prop_property_get (win,
3697             ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
3698     if (ret && prop_data) {
3699         memcpy (&angle, prop_data, sizeof (int));
3700         LOGD ("WINDOW angle of %p is %d", win, angle);
3701     } else {
3702         std::cerr << "ecore_x_window_prop_property_get () is failed!!!\n";
3703         LOGW ("WINDOW angle of %p FAILED!", win);
3704     }
3705     if (prop_data)
3706         XFree (prop_data);
3707
3708     return angle;
3709 }
3710 #endif /* HAVE_ECOREX */
3711
3712 /**
3713  * @brief Get angle for app window.
3714  *
3715  * @param win_obj The Evas_Object handler of application window.
3716  *
3717  * @return The angle of app window.
3718  */
3719 static int efl_get_app_window_angle ()
3720 {
3721     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3722 #ifdef HAVE_ECOREX
3723     return efl_get_window_rotate_angle (efl_get_app_window ());
3724 #else
3725     //FIXME:
3726     return 0;
3727 #endif
3728 }
3729 #endif /* CANDIDATE */
3730
3731 /**
3732  * @brief Get angle for ise window.
3733  *
3734  * @param win_obj The Evas_Object handler of ise window.
3735  *
3736  * @return The angle of ise window.
3737  */
3738 static int efl_get_ise_window_angle ()
3739 {
3740     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3741 #ifdef HAVE_ECOREX
3742     return efl_get_window_rotate_angle (_ise_window);
3743 #else
3744     //FIXME:
3745     return 0;
3746 #endif
3747 }
3748
3749 #if ISF_BUILD_CANDIDATE_UI
3750 #ifdef HAVE_ECOREX
3751 /**
3752  * @brief Get angle of quickpanel window.
3753  *
3754  * @return The angle of quickpanel window.
3755  */
3756 static int efl_get_quickpanel_window_angle ()
3757 {
3758     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3759     return efl_get_window_rotate_angle (efl_get_quickpanel_window ());
3760 }
3761 #endif
3762
3763 /**
3764  * @brief Set showing effect for application window.
3765  *
3766  * @param win The Evas_Object handler of application window.
3767  * @param strEffect The pointer of effect string.
3768  */
3769 static void efl_set_showing_effect_for_app_window (Evas_Object *win, const char* strEffect)
3770 {
3771     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3772 #ifdef HAVE_ECOREX
3773     ecore_x_icccm_name_class_set (elm_win_xwindow_get (static_cast<Evas_Object*>(win)), strEffect, "ISF");
3774 #endif
3775 }
3776
3777 /**
3778  * @brief Create elementary window.
3779  *
3780  * @param strWinName The window name.
3781  * @param strEffect The window effect string.
3782  *
3783  * @return The window pointer
3784  */
3785 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect)
3786 {
3787     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3788
3789     Evas_Object *win = elm_win_add (NULL, strWinName, ELM_WIN_UTILITY);
3790     elm_win_title_set (win, strWinName);
3791
3792     /* set window properties */
3793     elm_win_autodel_set (win, EINA_TRUE);
3794     elm_object_focus_allow_set (win, EINA_FALSE);
3795     elm_win_borderless_set (win, EINA_TRUE);
3796     elm_win_alpha_set (win, EINA_TRUE);
3797     elm_win_prop_focus_skip_set (win, EINA_TRUE);
3798     efl_set_showing_effect_for_app_window (win, strEffect);
3799
3800     return win;
3801 }
3802 #endif /* CANDIDATE */
3803
3804 #ifdef HAVE_ECOREX
3805 /**
3806  * @brief Create elementary control window.
3807  *
3808  * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3809  */
3810 static Eina_Bool efl_create_control_window (void)
3811 {
3812     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3813
3814     /* WMSYNC, #1 Creating and registering control window */
3815     if (ecore_x_display_get () == NULL)
3816         return EINA_FALSE;
3817
3818     Ecore_X_Window root = ecore_x_window_root_first_get ();
3819     _control_window = ecore_x_window_input_new (root, -100, -100, 1, 1);
3820     //ecore_x_e_virtual_keyboard_control_window_set (root, _control_window, 0, EINA_TRUE);
3821
3822     Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_CONTROL_WINDOW");
3823     ecore_x_window_prop_xid_set (root, atom, ECORE_X_ATOM_WINDOW, &_control_window, 1);
3824
3825     return EINA_TRUE;
3826 }
3827
3828 /**
3829  * @brief Get an window's x window id.
3830  *
3831  * @param name the property name.
3832  * @return X window id.
3833  */
3834 static Ecore_X_Window efl_get_window (const char *name)
3835 {
3836     /* Gets the XID of the window from the root window property */
3837     int  ret = 0;
3838     Atom type_return;
3839     int  format_return;
3840     unsigned long    nitems_return;
3841     unsigned long    bytes_after_return;
3842     unsigned char   *data = NULL;
3843     Ecore_X_Window   window = 0;
3844
3845     ret = XGetWindowProperty ((Display *)ecore_x_display_get (),
3846                               ecore_x_window_root_get (_control_window),
3847                               ecore_x_atom_get (name),
3848                               0, G_MAXLONG, False, XA_WINDOW, &type_return,
3849                               &format_return, &nitems_return, &bytes_after_return,
3850                               &data);
3851
3852     if (ret == Success) {
3853         if ((type_return == XA_WINDOW) && (format_return == 32) && (data)) {
3854             window = *(Window *)data;
3855         }
3856     } else {
3857         std::cerr << "XGetWindowProperty () is failed!!!\n";
3858     }
3859
3860     if (data)
3861         XFree (data);
3862
3863     return window;
3864 }
3865
3866 /**
3867  * @brief Get app window's x window id.
3868  *
3869  * @return the X window id of application to have focus or to request to show IME.
3870  */
3871 static Ecore_X_Window efl_get_app_window (void)
3872 {
3873     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3874
3875     return efl_get_window ("_ISF_ACTIVE_WINDOW");
3876 }
3877
3878 /**
3879  * @brief Get clipboard window's x window id.
3880  *
3881  * @return the X window id of clipboard.
3882  */
3883 static Ecore_X_Window efl_get_clipboard_window (void)
3884 {
3885     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3886
3887     return efl_get_window ("CBHM_ELM_WIN");
3888 }
3889
3890 /**
3891  * @brief Get global navigation window's x window id.
3892  *
3893  * @return the X window id of global navigation.
3894  */
3895 static Ecore_X_Window efl_get_global_navigation_window (void)
3896 {
3897     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3898
3899     return efl_get_window ("GNB_WIN");
3900 }
3901
3902 /**
3903  * @brief Get app window's x window id.
3904  *
3905  * @return the X window id of quick panel.
3906  */
3907 static Ecore_X_Window efl_get_quickpanel_window (void)
3908 {
3909     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3910
3911     Ecore_X_Window rootWin = ecore_x_window_root_first_get ();
3912     Ecore_X_Window qpwin;
3913     ecore_x_window_prop_xid_get (rootWin, ecore_x_atom_get ("_E_ILLUME_QUICKPANEL_WINDOW_LIST"), ECORE_X_ATOM_WINDOW, &qpwin, 1);
3914
3915     return qpwin;
3916 }
3917
3918 /**
3919  * @brief Get default zone geometry.
3920  *
3921  * @param x The zone x position.
3922  * @param y The zone y position.
3923  * @param w The zone width.
3924  * @param h The zone height.
3925  *
3926  * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3927  */
3928 static Eina_Bool efl_get_default_zone_geometry_info (Ecore_X_Window root, uint *x, uint *y, uint *w, uint *h)
3929 {
3930     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3931
3932     Ecore_X_Atom    zone_geometry_atom;
3933     Ecore_X_Window *zone_lists;
3934     int             num_zone_lists;
3935     int             num_ret;
3936     Eina_Bool       ret;
3937
3938     zone_geometry_atom = ecore_x_atom_get ("_E_ILLUME_ZONE_GEOMETRY");
3939     if (!zone_geometry_atom) {
3940         /* Error... */
3941         return EINA_FALSE;
3942     }
3943
3944     uint geom[4];
3945     num_zone_lists = ecore_x_window_prop_window_list_get (root, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, &zone_lists);
3946     if (num_zone_lists > 0) {
3947         num_ret = ecore_x_window_prop_card32_get (zone_lists[0], zone_geometry_atom, geom, 4);
3948         if (num_ret == 4) {
3949             if (x) *x = geom[0];
3950             if (y) *y = geom[1];
3951             if (w) *w = geom[2];
3952             if (h) *h = geom[3];
3953             ret = EINA_TRUE;
3954         } else {
3955             ret = EINA_FALSE;
3956         }
3957     } else {
3958         /* if there is no zone available */
3959         ret = EINA_FALSE;
3960     }
3961
3962     if (zone_lists) {
3963         /* We must free zone_lists */
3964         free (zone_lists);
3965     }
3966
3967     return ret;
3968 }
3969 #endif /* HAVE_ECOREX */
3970
3971 #if ISF_BUILD_CANDIDATE_UI
3972 /**
3973  * @brief Get screen resolution.
3974  *
3975  * @param width The screen width.
3976  * @param height The screen height.
3977  */
3978 static void efl_get_screen_resolution (int &width, int &height)
3979 {
3980     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3981
3982     static Evas_Coord scr_w = 0, scr_h = 0;
3983     if (scr_w == 0 || scr_h == 0) {
3984 #ifdef HAVE_ECOREX
3985         uint w = 0, h = 0;
3986         if (efl_get_default_zone_geometry_info (ecore_x_window_root_first_get (), NULL, NULL, &w, &h)) {
3987             scr_w = w;
3988             scr_h = h;
3989         } else {
3990             ecore_x_window_size_get (ecore_x_window_root_first_get (), &scr_w, &scr_h);
3991         }
3992 #else
3993         Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3994         if (wl2_display)
3995             ecore_wl2_display_screen_size_get(wl2_display, &scr_w, &scr_h);
3996 #endif
3997     }
3998
3999     width  = scr_w;
4000     height = scr_h;
4001 }
4002 #endif /* CANDIDATE */
4003
4004 //////////////////////////////////////////////////////////////////////
4005 // Start of PanelAgent Functions
4006 //////////////////////////////////////////////////////////////////////
4007
4008 /**
4009  * @brief Initialize panel agent.
4010  *
4011  * @param config The config string for PanelAgent.
4012  * @param display The current display.
4013  * @param resident The variable indicates whether panel will be resident.
4014  *
4015  * @return true if initialize is successful, otherwise return false.
4016  */
4017 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident)
4018 {
4019     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4020
4021     LOGD ("initializing panel agent");
4022
4023     _info_manager = new InfoManager ();
4024
4025     if (!_info_manager || !_info_manager->initialize (_info_manager, config, display, resident)) {
4026         ISF_SAVE_LOG ("panel_agent initialize fail!");
4027         return false;
4028     }
4029
4030     _info_manager->signal_connect_focus_in                   (slot (slot_focus_in));
4031     _info_manager->signal_connect_focus_out                  (slot (slot_focus_out));
4032     _info_manager->signal_connect_expand_candidate           (slot (slot_expand_candidate));
4033     _info_manager->signal_connect_contract_candidate         (slot (slot_contract_candidate));
4034     _info_manager->signal_connect_set_candidate_ui           (slot (slot_set_candidate_style));
4035     _info_manager->signal_connect_update_factory_info        (slot (slot_update_factory_info));
4036     _info_manager->signal_connect_update_spot_location       (slot (slot_update_spot_location));
4037     _info_manager->signal_connect_update_input_context       (slot (slot_update_input_context));
4038     _info_manager->signal_connect_update_ise_geometry        (slot (slot_update_ise_geometry));
4039 #if ISF_BUILD_CANDIDATE_UI
4040     _info_manager->signal_connect_show_preedit_string        (slot (slot_show_preedit_string));
4041     _info_manager->signal_connect_show_aux_string            (slot (slot_show_aux_string));
4042 #endif
4043     _info_manager->signal_connect_show_lookup_table          (slot (slot_show_candidate_table));
4044     _info_manager->signal_connect_hide_preedit_string        (slot (slot_hide_preedit_string));
4045     _info_manager->signal_connect_hide_aux_string            (slot (slot_hide_aux_string));
4046     _info_manager->signal_connect_hide_lookup_table          (slot (slot_hide_candidate_table));
4047     _info_manager->signal_connect_update_preedit_string      (slot (slot_update_preedit_string));
4048     _info_manager->signal_connect_update_preedit_caret       (slot (slot_update_preedit_caret));
4049     _info_manager->signal_connect_update_aux_string          (slot (slot_update_aux_string));
4050     _info_manager->signal_connect_update_lookup_table        (slot (slot_update_candidate_table));
4051     _info_manager->signal_connect_select_candidate           (slot (slot_select_candidate));
4052     _info_manager->signal_connect_get_candidate_geometry     (slot (slot_get_candidate_geometry));
4053     _info_manager->signal_connect_get_input_panel_geometry   (slot (slot_get_input_panel_geometry));
4054     _info_manager->signal_connect_set_active_ise_by_uuid     (slot (slot_set_active_ise));
4055     _info_manager->signal_connect_get_ise_list               (slot (slot_get_ise_list));
4056     _info_manager->signal_connect_get_all_helper_ise_info    (slot (slot_get_all_helper_ise_info));
4057     _info_manager->signal_connect_set_has_option_helper_ise_info(slot (slot_set_has_option_helper_ise_info));
4058     _info_manager->signal_connect_set_enable_helper_ise_info (slot (slot_set_enable_helper_ise_info));
4059     _info_manager->signal_connect_show_helper_ise_list       (slot (slot_show_helper_ise_list));
4060     _info_manager->signal_connect_show_helper_ise_selector   (slot (slot_show_helper_ise_selector));
4061     _info_manager->signal_connect_is_helper_ise_enabled      (slot (slot_is_helper_ise_enabled));
4062     _info_manager->signal_connect_get_ise_information        (slot (slot_get_ise_information));
4063     _info_manager->signal_connect_get_keyboard_ise_list      (slot (slot_get_keyboard_ise_list));
4064     _info_manager->signal_connect_get_language_list          (slot (slot_get_language_list));
4065     _info_manager->signal_connect_get_all_language           (slot (slot_get_all_language));
4066     _info_manager->signal_connect_get_ise_language           (slot (slot_get_ise_language));
4067     _info_manager->signal_connect_get_ise_info_by_uuid       (slot (slot_get_ise_info));
4068     _info_manager->signal_connect_set_keyboard_ise           (slot (slot_set_keyboard_ise));
4069     _info_manager->signal_connect_get_keyboard_ise           (slot (slot_get_keyboard_ise));
4070     _info_manager->signal_connect_accept_connection          (slot (slot_accept_connection));
4071     _info_manager->signal_connect_close_connection           (slot (slot_close_connection));
4072     _info_manager->signal_connect_exit                       (slot (slot_exit));
4073
4074     _info_manager->signal_connect_register_helper            (slot(slot_register_helper));
4075     _info_manager->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
4076     _info_manager->signal_connect_show_ise                   (slot (slot_show_ise));
4077     _info_manager->signal_connect_hide_ise                   (slot (slot_hide_ise));
4078
4079     _info_manager->signal_connect_will_hide_ack              (slot (slot_will_hide_ack));
4080
4081     _info_manager->signal_connect_set_keyboard_mode          (slot (slot_set_keyboard_mode));
4082
4083     _info_manager->signal_connect_candidate_will_hide_ack    (slot (slot_candidate_will_hide_ack));
4084     _info_manager->signal_connect_get_ise_state              (slot (slot_get_ise_state));
4085     _info_manager->signal_connect_start_default_ise          (slot (slot_start_default_ise));
4086     _info_manager->signal_connect_stop_default_ise           (slot (slot_stop_default_ise));
4087     _info_manager->signal_connect_show_panel                 (slot (slot_show_helper_ise_selector));
4088 #if ENABLE_REMOTE_INPUT
4089     _info_manager->signal_connect_remoteinput_send_input_message(slot (slot_send_remote_input_message));
4090     _info_manager->signal_connect_remoteinput_send_surrounding_text(slot (slot_recv_remote_surrounding_text));
4091 #endif
4092     _info_manager->signal_connect_get_recent_ise_geometry    (slot (slot_get_recent_ise_geometry));
4093     _info_manager->signal_connect_check_privilege_by_sockfd  (slot (slot_check_privilege_by_sockfd));
4094
4095     _info_manager->signal_connect_run_helper                 (slot (slot_run_helper));
4096     _info_manager->signal_connect_launch_option_application  (slot (slot_launch_option_application));
4097     _info_manager->signal_connect_get_ise_setting_appid      (slot (slot_get_ise_setting_appid));
4098     _info_manager->signal_connect_set_preloading_ise         (slot (slot_set_preloading_ise));
4099
4100     LOGD ("initializing panel agent succeeded");
4101
4102     return true;
4103 }
4104
4105 static void delete_ise_hide_timer (void)
4106 {
4107     LOGD ("deleting ise_hide_timer");
4108     if (_ise_hide_timer) {
4109         ecore_timer_del (_ise_hide_timer);
4110         _ise_hide_timer = NULL;
4111     }
4112 }
4113
4114 static void hide_ise ()
4115 {
4116     LOGD ("send request to hide helper");
4117     String uuid = _info_manager->get_current_helper_uuid ();
4118     _info_manager->hide_helper (uuid);
4119
4120     /* Only if we are not already in HIDE state */
4121     if (_ise_state != WINDOW_STATE_HIDE) {
4122         /* From this point, slot_get_input_panel_geometry should return hidden state geometry */
4123         _ise_state = WINDOW_STATE_WILL_HIDE;
4124
4125         _updated_hide_state_geometry = false;
4126     }
4127     _ise_angle = -1;
4128 #ifdef HAVE_ECOREX
4129     ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
4130 #endif
4131 #if ISF_BUILD_CANDIDATE_UI
4132     if (_candidate_window) {
4133         if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)
4134             ui_candidate_hide (true, true, true);
4135         else
4136             ui_candidate_hide (true, false, true);
4137     }
4138 #endif /* CANDIDATE */
4139
4140 #ifdef HAVE_ECOREWL
4141 #ifdef HAVE_NOTIFICATION
4142     delete_notification (&ise_selector_module_noti);
4143 #endif
4144 #endif
4145 }
4146
4147 #if ENABLE_MULTIWINDOW_SUPPORT
4148 static Eina_Bool ise_hide_timeout (void *data)
4149 {
4150     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4151
4152     delete_ise_hide_timer ();
4153     hide_ise ();
4154
4155     return ECORE_CALLBACK_CANCEL;
4156 }
4157 #endif
4158
4159 /**
4160  * @brief Insert data to ime_info table.
4161  *
4162  * @param list The list to store uuid
4163  *
4164  * @return true if it is successful, otherwise return false.
4165  */
4166 static bool update_ise_list (std::vector<String> &list)
4167 {
4168     std::vector<String> uuids;
4169     std::vector<TOOLBAR_MODE_T>  modes;
4170     std::vector<ImeInfoDB>::iterator iter;
4171     bool result = true;
4172
4173     if (_ime_info.size() == 0) {
4174         if (isf_pkg_select_all_ime_info_db(_ime_info) == 0)
4175             result = false;
4176     }
4177
4178     /* Update _groups */
4179     _groups.clear();
4180     std::vector<String> ise_langs;
4181     for (size_t i = 0; i < _ime_info.size (); ++i) {
4182         scim_split_string_list(ise_langs, _ime_info[i].languages);
4183         for (size_t j = 0; j < ise_langs.size (); j++) {
4184             if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
4185             _groups[ise_langs[j]].push_back (i);
4186         }
4187         ise_langs.clear ();
4188     }
4189
4190     for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
4191         uuids.push_back(iter->appid);
4192         modes.push_back(iter->mode);
4193     }
4194
4195     if (uuids.size() > 0) {
4196         list.clear ();
4197         list = uuids;
4198
4199         _info_manager->update_ise_list (list);
4200
4201         if (_initial_ise_uuid.length () > 0) {
4202             String active_uuid   = _initial_ise_uuid;
4203             String default_uuid  = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
4204             if (std::find (uuids.begin (), uuids.end (), default_uuid) == uuids.end ()) {
4205                 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (modes[get_ise_index (_initial_ise_uuid)] != TOOLBAR_KEYBOARD_MODE)) {
4206                     active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4207                 }
4208
4209                 if (set_active_ise (active_uuid, _soft_keyboard_launched) == false) {
4210                     if (_initial_ise_uuid.compare (active_uuid)) {
4211                         LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
4212                         set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
4213                     }
4214                 }
4215             } else if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {    // Check whether keyboard engine is installed
4216                 String IMENGINE_KEY  = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
4217                 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
4218                 if (std::find (uuids.begin (), uuids.end (), keyboard_uuid) == uuids.end ()) {
4219                     active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4220                     _info_manager->change_factory (active_uuid);
4221                     _config->write (IMENGINE_KEY, active_uuid);
4222                     _config->flush ();
4223                 }
4224             }
4225         }
4226
4227 #ifdef HAVE_VCONF
4228         char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
4229         if (lang_str) {
4230             if (_ime_info.size () > 0 && _ime_info[0].display_lang.compare(lang_str) == 0)
4231                 _locale_string = String (lang_str);
4232             free (lang_str);
4233         }
4234 #endif
4235     }
4236     else
4237         LOGW ("No IME list");
4238
4239 #ifdef HAVE_PKGMGR_INFO
4240     if (!pkgmgr) {
4241         int ret = package_manager_create (&pkgmgr);
4242         if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4243             ret = package_manager_set_event_cb (pkgmgr, _package_manager_event_cb, NULL);
4244             if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4245                 LOGD ("package_manager_set_event_cb succeeded.");
4246             }
4247             else {
4248                 LOGE ("package_manager_set_event_cb failed(%d)", ret);
4249             }
4250         }
4251         else {
4252             LOGE ("package_manager_create failed(%d)", ret);
4253         }
4254     }
4255 #endif
4256
4257     return result;
4258 }
4259
4260 /**
4261  * @brief Focus in slot function for PanelAgent.
4262  */
4263 static void slot_focus_in (void)
4264 {
4265     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4266
4267     _focus_in = true;
4268     if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
4269         if (_launch_ise_on_request && !_soft_keyboard_launched) {
4270             String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
4271             if (uuid.length () > 0 && (_ime_info[get_ise_index(uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
4272                 LOGD ("Start helper (%s)", uuid.c_str ());
4273
4274                 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
4275                 if (_info_manager->start_helper (uuid))
4276                     _soft_keyboard_launched = true;
4277             }
4278         }
4279     }
4280
4281 #if ISF_BUILD_CANDIDATE_UI
4282     ui_candidate_delete_destroy_timer ();
4283 #endif /* CANDIDATE */
4284 }
4285
4286 /**
4287  * @brief Focus out slot function for PanelAgent.
4288  */
4289 static void slot_focus_out (void)
4290 {
4291     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4292
4293     _focus_in = false;
4294
4295 #if ISF_BUILD_CANDIDATE_UI
4296     ui_candidate_delete_destroy_timer ();
4297     _destroy_timer = ecore_timer_add (ISF_CANDIDATE_DESTROY_DELAY, ui_candidate_destroy_timeout, NULL);
4298 #endif /* CANDIDATE */
4299 }
4300
4301 /**
4302  * @brief Expand candidate slot function for PanelAgent.
4303  */
4304 static void slot_expand_candidate (void)
4305 {
4306     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4307     if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4308         return;
4309
4310 #if ISF_BUILD_CANDIDATE_UI
4311     if (_candidate_area_2 && !_candidate_area_2_visible)
4312         ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
4313 #endif /* CANDIDATE */
4314 }
4315
4316 /**
4317  * @brief Contract candidate slot function for PanelAgent.
4318  */
4319 static void slot_contract_candidate (void)
4320 {
4321     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4322
4323     if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4324         return;
4325
4326 #if ISF_BUILD_CANDIDATE_UI
4327     ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
4328 #endif /* CANDIDATE */
4329 }
4330
4331 /**
4332  * @brief Set candidate style slot function for PanelAgent.
4333  *
4334  * @param portrait_line The displayed line number for portrait.
4335  * @param mode The candidate mode.
4336  */
4337 static void slot_set_candidate_style (int portrait_line, int mode)
4338 {
4339     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " display_line:" << portrait_line << " mode:" << mode << "\n";
4340 #if ISF_BUILD_CANDIDATE_UI
4341     if ((portrait_line != _candidate_port_line) || (mode != _candidate_mode)) {
4342         _candidate_mode      = (ISF_CANDIDATE_MODE_T)mode;
4343         _candidate_port_line = (ISF_CANDIDATE_PORTRAIT_LINE_T)portrait_line;
4344         _soft_candidate_width = 0;
4345         _soft_candidate_height = 0;
4346
4347         if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4348             if (_candidate_window)
4349                 ui_destroy_candidate_window ();
4350
4351             return;
4352         }
4353
4354         if (_candidate_window)
4355             ui_create_candidate_window ();
4356     }
4357 #endif /* CANDIDATE */
4358 }
4359
4360 #if defined(HAVE_NOTIFICATION) || defined(HAVE_ECOREX)
4361 static unsigned int get_ise_count (TOOLBAR_MODE_T mode, bool valid_helper)
4362 {
4363     unsigned int ise_count = 0;
4364     for (unsigned int i = 0; i < _ime_info.size (); i++) {
4365         if (mode == _ime_info[i].mode) {
4366             if (mode == TOOLBAR_KEYBOARD_MODE || !valid_helper)
4367                 ise_count++;
4368             else if (_ime_info[i].is_enabled)
4369                 ise_count++;
4370         }
4371     }
4372
4373     return ise_count;
4374 }
4375 #endif
4376
4377 /**
4378  * @brief Update keyboard ISE information slot function for PanelAgent.
4379  *
4380  * @param info The information of current Keyboard ISE.
4381  */
4382 static void slot_update_factory_info (const PanelFactoryInfo &info)
4383 {
4384     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4385
4386     String ise_name = info.name;
4387
4388     String old_ise = _info_manager->get_current_ise_name ();
4389 #if ISF_BUILD_CANDIDATE_UI
4390     if (old_ise != ise_name) {
4391         if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && _candidate_window) {
4392             ui_destroy_candidate_window ();
4393         }
4394     }
4395 #endif /* CANDIDATE */
4396
4397     TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
4398
4399     if (TOOLBAR_HELPER_MODE == mode)
4400         ise_name = _ime_info[get_ise_index (_info_manager->get_current_helper_uuid())].label;
4401
4402     if (ise_name.length () > 0)
4403         _info_manager->set_current_ise_name (ise_name);
4404
4405 #ifdef HAVE_NOTIFICATION
4406     if (_MOBILE || _COMMON) {
4407         if (old_ise != ise_name) {
4408             if (TOOLBAR_KEYBOARD_MODE == mode) {
4409                 char noti_msg[256] = {0};
4410                 unsigned int keyboard_ise_count = get_ise_count (TOOLBAR_KEYBOARD_MODE, false);
4411                 if (keyboard_ise_count == 0) {
4412                     LOGD ("the number of keyboard ise is %d", keyboard_ise_count);
4413                     return;
4414                 }
4415                 else if (keyboard_ise_count >= 2) {
4416                     snprintf (noti_msg, sizeof (noti_msg), _("%s selected"), ise_name.c_str ());
4417                 }
4418                 else if (keyboard_ise_count == 1) {
4419                     snprintf (noti_msg, sizeof (noti_msg), _("Only %s available"), ise_name.c_str ());
4420                 }
4421
4422                 notification_status_message_post (noti_msg);
4423                 LOGD ("%s", noti_msg);
4424             }
4425         }
4426     }
4427 #endif
4428 }
4429
4430 /**
4431  * @brief Update cursor position slot function for PanelAgent.
4432  *
4433  * @param x The x position of current cursor.
4434  * @param y The bottom y position of current cursor.
4435  * @param top_y The top y position of current cursor.
4436  */
4437 static void slot_update_spot_location (int x, int y, int top_y)
4438 {
4439     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4440
4441 #if ISF_BUILD_CANDIDATE_UI
4442     if (x >= 0 && x < _screen_height && y >= 0 && y < _screen_height) {
4443         _spot_location_x = x;
4444         _spot_location_y = y;
4445         _spot_location_top_y = top_y;
4446
4447         ui_settle_candidate_window ();
4448     }
4449 #endif /* CANDIDATE */
4450 }
4451
4452 /**
4453  * @brief The input context of ISE is changed.
4454  *
4455  * @param type  The event type.
4456  * @param value The event value.
4457  */
4458 static void slot_update_input_context (int type, int value)
4459 {
4460 }
4461
4462 /**
4463  * @brief Update ise geometry.
4464  *
4465  * @param x      The x position in screen.
4466  * @param y      The y position in screen.
4467  * @param width  The ISE window width.
4468  * @param height The ISE window height.
4469  */
4470 static void slot_update_ise_geometry (int x, int y, int width, int height)
4471 {
4472     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
4473
4474     LOGD ("x : %d , y : %d , width : %d , height : %d, _ise_state : %d", x, y, width, height, _ise_state);
4475
4476     if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
4477         if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4478             /*IF ISE sent the ise_geometry information when the current_keyboard_mode is H/W mode and candidate_mode is SOFT_CANDIDATE,
4479              It means that given geometry information is for the candidate window */
4480             set_soft_candidate_geometry (x, y, width, height);
4481         }
4482         return;
4483     }
4484
4485     _ise_x = x;
4486     _ise_y = y;
4487
4488 #if ISF_BUILD_CANDIDATE_UI
4489     _ise_width = width;
4490     _ise_height = height;
4491
4492     if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
4493         ui_settle_candidate_window ();
4494     }
4495 #endif /* CANDIDATE */
4496
4497     if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
4498         _ise_reported_geometry.valid = true;
4499         _ise_reported_geometry.angle = efl_get_ise_window_angle ();
4500         _ise_reported_geometry.geometry.pos_x = x;
4501         _ise_reported_geometry.geometry.pos_y = y;
4502         _ise_reported_geometry.geometry.width = width;
4503         _ise_reported_geometry.geometry.height = height;
4504         if (_ise_state == WINDOW_STATE_SHOW) {
4505 #ifdef HAVE_ECOREX
4506             set_keyboard_geometry_atom_info (_app_window, _ise_reported_geometry.geometry);
4507 #endif
4508             _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
4509         }
4510     }
4511 }
4512
4513 #if ISF_BUILD_CANDIDATE_UI
4514 /**
4515  * @brief Show preedit slot function for PanelAgent.
4516  */
4517 static void slot_show_preedit_string (void)
4518 {
4519     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4520
4521     if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4522         return;
4523
4524     if (_preedit_window == NULL) {
4525         ui_create_preedit_window ();
4526
4527         /* Move preedit window according to candidate window position */
4528         if (_candidate_window) {
4529             /* Get candidate window position */
4530             int x, y, width, height;
4531             ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
4532
4533             int height2 = ui_candidate_get_valid_height ();
4534             int angle = efl_get_app_window_angle ();
4535
4536             if (angle == 90) {
4537                 x -= _preedit_height;
4538                 y = _screen_height - _preedit_width;
4539             } else if (_candidate_angle == 270) {
4540                 x += height2;
4541             } else if (_candidate_angle == 180) {
4542                 x = _screen_width - _preedit_width;
4543                 y += height2;
4544             } else {
4545                 y -= _preedit_height;
4546             }
4547
4548             if (_preedit_window)
4549                 evas_object_move (_preedit_window, x, y);
4550         }
4551     }
4552
4553     if (_preedit_window && evas_object_visible_get (_preedit_window))
4554         return;
4555
4556     slot_show_candidate_table ();
4557
4558     if (_preedit_window)
4559         evas_object_show (_preedit_window);
4560 }
4561
4562 /**
4563  * @brief Show aux slot function for PanelAgent.
4564  */
4565 static void slot_show_aux_string (void)
4566 {
4567     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4568
4569     if (_candidate_window == NULL)
4570         ui_create_candidate_window ();
4571
4572     if (_aux_area == NULL || _aux_area_visible)
4573         return;
4574
4575     evas_object_show (_aux_area);
4576     _aux_area_visible = true;
4577     ui_candidate_window_adjust ();
4578
4579     LOGD ("calling ui_candidate_show ()");
4580     ui_candidate_show ();
4581     ui_settle_candidate_window ();
4582     ui_candidate_delete_destroy_timer ();
4583
4584 }
4585 #endif /* CANDIDATE */
4586
4587 /**
4588  * @brief Show candidate table slot function for PanelAgent.
4589  */
4590 static void slot_show_candidate_table (void)
4591 {
4592     if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4593         _info_manager->helper_candidate_show ();
4594         return;
4595     }
4596
4597 #if ISF_BUILD_CANDIDATE_UI
4598     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4599     if (_candidate_window == NULL)
4600         ui_create_candidate_window ();
4601
4602 #ifdef HAVE_ECOREX
4603     if (_candidate_state == WINDOW_STATE_SHOW &&
4604         (_candidate_area_1_visible || _candidate_area_2_visible)) {
4605         efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
4606         return;
4607     }
4608 #endif
4609
4610     evas_object_show (_candidate_area_1);
4611     _candidate_area_1_visible = true;
4612     ui_candidate_window_adjust ();
4613
4614     LOGD ("calling ui_candidate_show ()");
4615     ui_candidate_show ();
4616     ui_settle_candidate_window ();
4617     ui_candidate_delete_destroy_timer ();
4618
4619 #ifdef HAVE_FEEDBACK
4620     int feedback_result = feedback_initialize ();
4621
4622     if (FEEDBACK_ERROR_NONE == feedback_result) {
4623         LOGD ("Feedback initialize successful");
4624         feedback_initialized = true;
4625     } else {
4626         LOGW ("Feedback initialize fail : %d", feedback_result);
4627         feedback_initialized = false;
4628     }
4629 #endif /* HAVE_FEEDBACK */
4630 #endif /* CANDIDATE */
4631 }
4632
4633 /**
4634  * @brief Hide preedit slot function for PanelAgent.
4635  */
4636 static void slot_hide_preedit_string (void)
4637 {
4638     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4639
4640 #if ISF_BUILD_CANDIDATE_UI
4641     if (!_preedit_window || !evas_object_visible_get (_preedit_window))
4642         return;
4643
4644     evas_object_hide (_preedit_window);
4645 #endif /* CANDIDATE */
4646 }
4647
4648 /**
4649  * @brief Hide aux slot function for PanelAgent.
4650  */
4651 static void slot_hide_aux_string (void)
4652 {
4653     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4654
4655 #if ISF_BUILD_CANDIDATE_UI
4656     if (!_aux_area || !_aux_area_visible)
4657         return;
4658
4659     evas_object_hide (_aux_area);
4660     _aux_area_visible = false;
4661     elm_scroller_region_show (_aux_area, 0, 0, 10, 10);
4662     ui_candidate_window_adjust ();
4663
4664     LOGD ("calling ui_candidate_hide (false, true, true)");
4665     ui_candidate_hide (false, true, true);
4666     ui_settle_candidate_window ();
4667
4668     if (ui_candidate_can_be_hide ()) {
4669         _candidate_show_requested = false;
4670         LOGD ("setting _show_candidate_requested to FALSE");
4671     }
4672 #endif /* CANDIDATE */
4673 }
4674
4675 /**
4676  * @brief Hide candidate table slot function for PanelAgent.
4677  */
4678 static void slot_hide_candidate_table (void)
4679 {
4680     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4681
4682     if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4683         _info_manager->helper_candidate_hide ();
4684         return;
4685     }
4686
4687 #if ISF_BUILD_CANDIDATE_UI
4688     if (!_candidate_area_1 || _candidate_state == WINDOW_STATE_WILL_HIDE)
4689         return;
4690
4691     if (_candidate_area_1_visible || _candidate_area_2_visible) {
4692         bool bForce = false;
4693         if (_candidate_area_1_visible) {
4694             if (_aux_area_visible) {
4695                 evas_object_hide (_candidate_area_1);
4696                 _candidate_area_1_visible = false;
4697                 evas_object_hide (_more_btn);
4698             } else {
4699                 /* Let's not actually hide the _candidate_area_1 object, for the case that
4700                    even if the application replies CANDIDATE_WILL_HIDE_ACK a little late,
4701                    it is better to display the previous candidates instead of blank screen */
4702                 _candidate_area_1_visible = false;
4703                 bForce = true;
4704             }
4705         }
4706         if (_candidate_area_2_visible) {
4707             evas_object_hide (_candidate_area_2);
4708             _candidate_area_2_visible = false;
4709             evas_object_hide (_scroller_bg);
4710             evas_object_hide (_close_btn);
4711             _info_manager->candidate_more_window_hide ();
4712         }
4713         ui_candidate_window_adjust ();
4714
4715         LOGD ("calling ui_candidate_hide (%d, true, true)", bForce);
4716         ui_candidate_hide (bForce, true, true);
4717         ui_settle_candidate_window ();
4718     }
4719
4720 #ifdef HAVE_FEEDBACK
4721     int feedback_result = feedback_deinitialize ();
4722
4723     if (FEEDBACK_ERROR_NONE == feedback_result)
4724         LOGD ("Feedback deinitialize successful");
4725     else
4726         LOGW ("Feedback deinitialize fail : %d", feedback_result);
4727
4728     feedback_initialized = false;
4729 #endif
4730
4731     if (ui_candidate_can_be_hide ()) {
4732         _candidate_show_requested = false;
4733         LOGD ("setting _show_candidate_requested to FALSE");
4734     }
4735 #endif /* CANDIDATE */
4736 }
4737
4738 /**
4739  * @brief Update preedit slot function for PanelAgent.
4740  *
4741  * @param str The new preedit string.
4742  * @param attrs The attribute list of new preedit string.
4743  */
4744 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret)
4745 {
4746     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " string=" << str << "\n";
4747
4748 #if ISF_BUILD_CANDIDATE_UI
4749     if (str.length () <= 0)
4750         return;
4751
4752     if (_preedit_window == NULL || !evas_object_visible_get (_preedit_window)) {
4753         slot_show_preedit_string ();
4754     }
4755
4756     int x, y, width, height, candidate_width;
4757     evas_object_text_text_set (_tmp_preedit_text, str.c_str ());
4758     evas_object_geometry_get (_tmp_preedit_text, &x, &y, &width, &height);
4759     ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &candidate_width, &height);
4760     _preedit_width = (width + ISF_PREEDIT_BORDER * 2) < candidate_width ? (width + ISF_PREEDIT_BORDER * 2) : candidate_width;
4761
4762     /* Resize preedit window and avoid text blink */
4763     int old_width, old_height;
4764     evas_object_geometry_get (_preedit_window, &x, &y, &old_width, &old_height);
4765     if (old_width < _preedit_width) {
4766         evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4767         edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4768     } else {
4769         edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4770         evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4771     }
4772
4773     /* Move preedit window */
4774     if (_candidate_angle == 90 || _candidate_angle == 180) {
4775         ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_preedit_window)), &x, &y, &width, &height);
4776         if (_candidate_angle == 90) {
4777             y = _screen_height - _preedit_width;
4778         } else if (_candidate_angle == 180) {
4779             x = _screen_width - _preedit_width;
4780         }
4781         evas_object_move (_preedit_window, x, y);
4782     }
4783 #endif /* CANDIDATE */
4784 }
4785
4786 /**
4787  * @brief Update caret slot function for PanelAgent.
4788  *
4789  * @param caret The caret position.
4790  */
4791 static void slot_update_preedit_caret (int caret)
4792 {
4793     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " caret=" << caret << "\n";
4794 }
4795
4796 #if ISF_BUILD_CANDIDATE_UI
4797 /**
4798  * @brief Set highlight text color and background color for edje object.
4799  *
4800  * @param item The edje object pointer.
4801  * @param nForeGround The text color.
4802  * @param nBackGround The background color.
4803  * @param bSetBack The flag for background color.
4804  */
4805 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack)
4806 {
4807     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4808
4809     int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
4810     if (edje_object_color_class_get (item, "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4811         r = SCIM_RGB_COLOR_RED (nForeGround);
4812         g = SCIM_RGB_COLOR_GREEN (nForeGround);
4813         b = SCIM_RGB_COLOR_BLUE (nForeGround);
4814         edje_object_color_class_set (item, "text_color", r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
4815     }
4816     if (bSetBack && edje_object_color_class_get (item, "rect_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4817         r = SCIM_RGB_COLOR_RED (nBackGround);
4818         g = SCIM_RGB_COLOR_GREEN (nBackGround);
4819         b = SCIM_RGB_COLOR_BLUE (nBackGround);
4820         edje_object_color_class_set (item, "rect_color", r, g, b, 255, r2, g2, b2, a2, r3, g3, b3, a3);
4821     }
4822 }
4823 #endif /* CANDIDATE */
4824
4825 /**
4826  * @brief Update aux slot function for PanelAgent.
4827  *
4828  * @param str The new aux string.
4829  * @param attrs The attribute list of new aux string.
4830  */
4831 static void slot_update_aux_string (const String &str, const AttributeList &attrs)
4832 {
4833     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4834 #if ISF_BUILD_CANDIDATE_UI
4835     if (_candidate_window == NULL)
4836         ui_create_candidate_window ();
4837
4838     if (!_aux_area || (str.length () <= 0))
4839         return;
4840
4841     if (!_aux_area_visible) {
4842         LOGD ("calling ui_candidate_show ()");
4843         ui_candidate_show ();
4844         slot_show_aux_string ();
4845     }
4846
4847     int x, y, width, height, item_width = 0;
4848     unsigned int window_width = 0, count = 0, i;
4849
4850     Evas_Object *aux_edje = NULL;
4851
4852     /* Get highlight item index */
4853     int    aux_index = -1, aux_start = 0, aux_end = 0;
4854     String strAux      = str;
4855     bool   bSetBack    = false;
4856     uint32 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
4857     uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
4858     for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4859         if (aux_index == -1 && ait->get_type () == SCIM_ATTR_DECORATE) {
4860             aux_index = ait->get_value ();
4861         } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
4862             nForeGround = ait->get_value ();
4863         } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
4864             nBackGround = ait->get_value ();
4865             bSetBack = true;
4866         }
4867     }
4868
4869     std::vector<String> aux_list;
4870     scim_split_string_list (aux_list, strAux, '|');
4871
4872     if (_aux_items.size () > 0) {
4873         for (i = 0; i < _aux_items.size (); i++)
4874             evas_object_del (_aux_items [i]);
4875         _aux_items.clear ();
4876     }
4877     if (_aux_seperates.size () > 0) {
4878         for (i = 0; i < _aux_seperates.size (); i++)
4879             evas_object_del (_aux_seperates [i]);
4880         _aux_seperates.clear ();
4881     }
4882
4883     int   seperate_width  = 4;
4884     int   seperate_height = 52 * _height_rate;
4885     Evas *evas = evas_object_evas_get (_candidate_window);
4886     for (i = 0; i < aux_list.size (); i++) {
4887         if (i > 0) {
4888             Evas_Object *seperate_item = edje_object_add (evas);
4889             edje_object_file_set (seperate_item, _candidate_edje_file.c_str (), "seperate_line");
4890             evas_object_size_hint_min_set (seperate_item, seperate_width, seperate_height);
4891             elm_table_pack (_aux_table, seperate_item, 2 * i - 1, 0, 1, 1);
4892             evas_object_show (seperate_item);
4893             _aux_seperates.push_back (seperate_item);
4894         }
4895
4896         count++;
4897         aux_edje = edje_object_add (evas);
4898         edje_object_file_set (aux_edje, _candidate_edje_file.c_str (), "aux");
4899         edje_object_part_text_set (aux_edje, "aux", aux_list [i].c_str ());
4900         edje_object_text_class_set (aux_edje, "tizen", _candidate_font_name.c_str (), _aux_font_size);
4901         elm_table_pack (_aux_table, aux_edje, 2 * i, 0, 1, 1);
4902         evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_AUX));
4903         evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
4904         evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_AUX));
4905         evas_object_show (aux_edje);
4906         _aux_items.push_back (aux_edje);
4907 /*      if (i == (unsigned int)aux_index)
4908             edje_object_signal_emit (aux_edje, "aux,state,selected", "aux");
4909         else
4910             edje_object_signal_emit (aux_edje, "aux,state,unselected", "aux");
4911 */
4912         evas_object_text_text_set (_tmp_aux_text, aux_list [i].c_str ());
4913         evas_object_geometry_get (_tmp_aux_text, &x, &y, &width, &height);
4914         item_width = width + 2*_blank_width;
4915         item_width = item_width > _item_min_width ? item_width : _item_min_width;
4916         evas_object_size_hint_min_set (aux_edje, item_width, _aux_height);
4917         if (aux_index == (int)i || (aux_index == -1 && i == 0)) {
4918             aux_start = window_width;
4919             aux_end   = window_width + item_width;
4920         }
4921         window_width = window_width + item_width + 4;
4922     }
4923
4924     // Set highlight item
4925     for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4926         if (ait->get_type () == SCIM_ATTR_DECORATE) {
4927             unsigned int index = ait->get_value ();
4928             if (index < _aux_items.size ())
4929                 set_highlight_color (_aux_items [index], nForeGround, nBackGround, bSetBack);
4930         }
4931     }
4932
4933     int w, h;
4934     elm_scroller_region_get (_aux_area, &x, &y, &w, &h);
4935     item_width = aux_end - aux_start;
4936     if (item_width > 0) {
4937         if (item_width >= w)
4938             elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4939         else if (aux_end > x + w)
4940             elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4941         else if (aux_start < x)
4942             elm_scroller_region_show (_aux_area, aux_start, y, w, h);
4943     }
4944     flush_memory ();
4945 #endif /* CANDIDATE */
4946 }
4947
4948 #if ISF_BUILD_CANDIDATE_UI
4949 /**
4950  * @brief Update candidate/associate table.
4951  *
4952  * @param table_type The table type.
4953  * @param table The lookup table for candidate or associate.
4954  */
4955 static void update_table (int table_type, const LookupTable &table)
4956 {
4957     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << table.get_current_page_size () << ")\n";
4958
4959     int item_num = table.get_current_page_size ();
4960     if (item_num < 0)
4961         return;
4962
4963     String     mbs;
4964     WideString wcs;
4965
4966     AttributeList attrs;
4967     int i, x, y, item_0_width = 0;
4968
4969     int nLast = 0;
4970
4971     int seperate_width  = 2;
4972     int seperate_height = 52 * _height_rate;
4973     int line_width      = _candidate_scroll_width;
4974     int line_height     = _v_padding;
4975     int total_width     = 0;
4976     int current_width   = 0;
4977     int line_0          = 0;
4978     int line_count      = 0;
4979     int more_item_count = 0;
4980     int scroll_0_width  = _candidate_scroll_0_width_min;
4981     int cursor_pos      = table.get_cursor_pos ();
4982     int cursor_line     = 0;
4983
4984     if (_candidate_angle == 90 || _candidate_angle == 270)
4985         scroll_0_width = _screen_height - _more_btn_width - _h_padding;
4986     else
4987         scroll_0_width = _screen_width - _more_btn_width - _h_padding;
4988
4989     _candidate_image_count = 0;
4990     _candidate_text_count = 0;
4991     _candidate_pop_image_count = 0;
4992     _candidate_display_number = 0;
4993     _candidate_row_items.clear ();
4994
4995     Evas *evas = evas_object_evas_get (_candidate_window);
4996     for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
4997         if (_candidate_0 [i]) {
4998             evas_object_del (_candidate_0 [i]);
4999             _candidate_0 [i] = NULL;
5000         }
5001         if (_seperate_0 [i]) {
5002             evas_object_del (_seperate_0 [i]);
5003             _seperate_0 [i] = NULL;
5004         }
5005         if (_seperate_items [i]) {
5006             evas_object_del (_seperate_items [i]);
5007             _seperate_items [i] = NULL;
5008         }
5009         if (_line_0 [i]) {
5010             evas_object_del (_line_0 [i]);
5011             _line_0 [i] = NULL;
5012         }
5013         if (_line_items [i]) {
5014             evas_object_del (_line_items [i]);
5015             _line_items [i] = NULL;
5016         }
5017     }
5018
5019     for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
5020         if (i < item_num) {
5021             bool   bHighLight  = false;
5022             bool   bSetBack    = false;
5023             uint32 nForeGround = SCIM_RGB_COLOR (249, 249, 249);
5024             uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
5025             attrs = table.get_attributes_in_current_page (i);
5026             for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5027                 if (ait->get_type () == SCIM_ATTR_DECORATE && ait->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
5028                     bHighLight  = true;
5029                     nForeGround = SCIM_RGB_COLOR (62, 207, 255);
5030                 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
5031                     bHighLight  = true;
5032                     nForeGround = ait->get_value ();
5033                 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
5034                     bSetBack    = true;
5035                     nBackGround = ait->get_value ();
5036                 }
5037             }
5038
5039             wcs = table.get_candidate_in_current_page (i);
5040             mbs = utf8_wcstombs (wcs);
5041
5042             if (!_candidate_0 [i] && total_width <= scroll_0_width) {
5043                 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5044                 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_CANDIDATE_0));
5045                 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5046                 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_0));
5047
5048                 /* Check whether this item is the last one */
5049                 if (i == item_num - 1) {
5050                     if (_candidate_angle == 90 || _candidate_angle == 270)
5051                         scroll_0_width = _candidate_land_width;
5052                     else
5053                         scroll_0_width = _candidate_port_width;
5054                 }
5055
5056                 /* Add first item */
5057                 if (i == 0) {
5058                     item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5059                     evas_object_show (_candidate_0 [i]);
5060                     evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5061                     elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, 0, item_0_width, _item_min_height);
5062                     total_width += item_0_width;
5063                     _candidate_display_number++;
5064                     continue;
5065                 } else {
5066                     total_width += (item_0_width + seperate_width);
5067                     if (total_width <= scroll_0_width) {
5068                         _seperate_0 [i] = edje_object_add (evas);
5069                         edje_object_file_set (_seperate_0 [i], _candidate_edje_file.c_str (), "seperate_line");
5070                         evas_object_size_hint_min_set (_seperate_0 [i], seperate_width, seperate_height);
5071                         elm_table_pack (_candidate_0_table, _seperate_0 [i],
5072                                 total_width - item_0_width - seperate_width,
5073                                 line_0*(_item_min_height+line_height) + (_item_min_height - seperate_height)/2,
5074                                 seperate_width, seperate_height);
5075                         evas_object_show (_seperate_0 [i]);
5076                         evas_object_show (_candidate_0 [i]);
5077                         evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5078                         elm_table_pack (_candidate_0_table, _candidate_0 [i], total_width - item_0_width, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
5079                         _candidate_display_number++;
5080                         continue;
5081                     } else if ((_candidate_angle == 0 || _candidate_angle == 180) &&
5082                             (_candidate_port_line > 1 && (line_0 + 1) < _candidate_port_line)) {
5083                         line_0++;
5084                         scroll_0_width = _candidate_scroll_0_width_min;
5085                         item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5086                         evas_object_show (_candidate_0 [i]);
5087                         evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5088                         elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
5089                         total_width = item_0_width;
5090                         _candidate_display_number++;
5091
5092                         _candidate_row_items.push_back (i - nLast);
5093                         nLast = i;
5094                         continue;
5095                     } else {
5096                         _candidate_row_items.push_back (i - nLast);
5097                         nLast = i;
5098                     }
5099                 }
5100             }
5101
5102             if (!_candidate_0 [i]) {
5103                 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5104                 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_CANDIDATE_ITEMS));
5105                 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5106                 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_ITEMS));
5107             }
5108             if (current_width > 0 && current_width + item_0_width > _candidate_scroll_width) {
5109                 current_width = 0;
5110                 line_count++;
5111
5112                 _candidate_row_items.push_back (i - nLast);
5113                 nLast = i;
5114                 if (cursor_pos >= i)
5115                     cursor_line++;
5116             }
5117             if (current_width == 0 && !_line_items [i]) {
5118                 _line_items [i] = edje_object_add (evas);
5119                 edje_object_file_set (_line_items [i], _candidate_edje_file.c_str (), "popup_line");
5120                 evas_object_size_hint_min_set (_line_items [i], line_width, line_height);
5121                 x = 0;
5122                 y = line_count*(_item_min_height+line_height);
5123                 elm_table_pack (_candidate_table, _line_items [i], x, y, line_width, line_height);
5124                 evas_object_show (_line_items [i]);
5125             }
5126             if (current_width != 0 && !_seperate_items [i]) {
5127                 _seperate_items [i] = edje_object_add (evas);
5128                 edje_object_file_set (_seperate_items [i], _candidate_edje_file.c_str (), "seperate_line");
5129                 evas_object_size_hint_min_set (_seperate_items [i], seperate_width, seperate_height);
5130                 x = current_width;
5131                 y = line_count*(_item_min_height+line_height) + line_height + (_item_min_height - seperate_height)/2;
5132                 elm_table_pack (_candidate_table, _seperate_items [i], x, y, seperate_width, seperate_height);
5133                 evas_object_show (_seperate_items [i]);
5134                 current_width += seperate_width;
5135             }
5136             x = current_width;
5137             y = line_count*(_item_min_height+line_height) + line_height;
5138             evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5139             evas_object_show (_candidate_0 [i]);
5140             elm_table_pack (_candidate_table, _candidate_0 [i], x, y, item_0_width, _item_min_height);
5141             current_width += item_0_width;
5142             more_item_count++;
5143             if (candidate_expanded == false && !bHighLight)
5144                 break;
5145             else
5146                 candidate_expanded = true;
5147         }
5148     }
5149
5150     for (i = 1; i < _candidate_port_line; i++) {
5151         if ((_candidate_angle == 0 || _candidate_angle == 180)) {
5152             if (_line_0 [i] == NULL) {
5153                 _line_0 [i] = edje_object_add (evas);
5154                 edje_object_file_set (_line_0 [i], _candidate_edje_file.c_str (), "popup_line");
5155                 evas_object_size_hint_min_set (_line_0 [i], line_width, line_height);
5156                 x = 0;
5157                 y = i * (_item_min_height + line_height) - line_height;
5158                 elm_table_pack (_candidate_0_table, _line_0 [i], x, y, line_width, line_height);
5159                 evas_object_show (_line_0 [i]);
5160             }
5161
5162             // Create blank line
5163             if (line_0 + 1 < _candidate_port_line && i > line_0) {
5164                 int nIndex = item_num + i;
5165                 nIndex = nIndex < SCIM_LOOKUP_TABLE_MAX_PAGESIZE ? nIndex : SCIM_LOOKUP_TABLE_MAX_PAGESIZE - 1;
5166                 _seperate_0 [nIndex] = edje_object_add (evas);
5167                 edje_object_file_set (_seperate_0 [nIndex], _candidate_edje_file.c_str (), "seperate_line");
5168                 evas_object_size_hint_min_set (_seperate_0 [nIndex], seperate_width, _item_min_height);
5169                 elm_table_pack (_candidate_0_table, _seperate_0 [nIndex],
5170                         0, i*(_item_min_height+line_height), seperate_width, _item_min_height);
5171             }
5172         } else if (_line_0 [i]) {
5173             evas_object_del (_line_0 [i]);
5174             _line_0 [i] = NULL;
5175         }
5176     }
5177
5178     _candidate_row_items.push_back (item_num - nLast);     /* Add the number of last row */
5179     _info_manager->update_displayed_candidate_number (_candidate_display_number);
5180     _info_manager->update_candidate_item_layout (_candidate_row_items);
5181     if (more_item_count == 0) {
5182         ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
5183         evas_object_hide (_more_btn);
5184         evas_object_hide (_close_btn);
5185     } else if (!_candidate_area_2_visible) {
5186         evas_object_show (_more_btn);
5187         evas_object_hide (_close_btn);
5188     } else {
5189         evas_object_hide (_more_btn);
5190         evas_object_show (_close_btn);
5191     }
5192
5193     int w, h;
5194     elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
5195
5196     int line_h   = _item_min_height + _v_padding;
5197     int cursor_y = cursor_line * line_h;
5198     if (cursor_y < y) {
5199         elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
5200     } else if (cursor_y >= y + h) {
5201         elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
5202     }
5203
5204     flush_memory ();
5205 }
5206 #endif /* CANDIDATE */
5207
5208 /**
5209  * @brief Update candidate table slot function for PanelAgent.
5210  *
5211  * @param table The lookup table for candidate.
5212  */
5213 static void slot_update_candidate_table (const LookupTable &table)
5214 {
5215     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5216
5217     if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5218         _info_manager->update_helper_lookup_table (table);
5219         return ;
5220     }
5221
5222 #if ISF_BUILD_CANDIDATE_UI
5223     if (_candidate_window == NULL)
5224         ui_create_candidate_window ();
5225
5226     if (!_candidate_window || table.get_current_page_size () < 0)
5227         return;
5228
5229     if (evas_object_visible_get (_candidate_area_2)) {
5230         candidate_expanded = true;
5231     } else {
5232         candidate_expanded = false;
5233     }
5234
5235     update_table (ISF_CANDIDATE_TABLE, table);
5236     ui_tts_focus_rect_hide ();
5237 #endif /* CANDIDATE */
5238 }
5239
5240 /**
5241  * @brief Send selected candidate index.
5242  *
5243  * @param selected candidate string index number.
5244  */
5245 static void slot_select_candidate (int index)
5246 {
5247     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5248     _info_manager->select_candidate (index);
5249 }
5250
5251 /**
5252  * @brief Get candidate geometry slot function for PanelAgent.
5253  *
5254  * @param info The data is used to store candidate position and size.
5255  */
5256 static void slot_get_candidate_geometry (struct rectinfo &info)
5257 {
5258     int x      = 0;
5259     int y      = 0;
5260     int width  = 0;
5261     int height = 0;
5262
5263     if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5264         info.pos_x  = x;
5265         info.pos_y  = y;
5266         info.width  = width;
5267         info.height = height;
5268         return;
5269     }
5270
5271 #if ISF_BUILD_CANDIDATE_UI
5272     if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5273         /* Get candidate window position */
5274         /*ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);*/
5275         /* Get exact candidate window size */
5276         /*int x2, y2;
5277           evas_object_geometry_get (_candidate_window, &x2, &y2, &width, &height);*/
5278
5279         x      = _candidate_x;
5280         y      = _candidate_y;
5281         width  = _candidate_width;
5282         height = _candidate_height;
5283     }
5284 #endif /* CANDIDATE */
5285
5286     info.pos_x  = x;
5287     info.pos_y  = y;
5288     info.width  = width;
5289     info.height = height;
5290
5291     LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5292     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5293                         << " width:" << info.width << " height:" << info.height << "\n";
5294 }
5295
5296 /**
5297  * @brief Get input panel geometry slot function for PanelAgent.
5298  *
5299  * @param info The data is used to store input panel position and size.
5300  */
5301 static void slot_get_input_panel_geometry (struct rectinfo &info)
5302 {
5303     if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
5304         info.pos_x = 0;
5305         info.width = 0;
5306         info.height = 0;
5307
5308 #if ISF_BUILD_CANDIDATE_UI
5309         if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5310             if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5311                 info.width  = _candidate_width;
5312                 info.height = _candidate_height;
5313             }
5314         } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5315             info.width  = _soft_candidate_width;
5316             info.height = _soft_candidate_height;
5317         }
5318         int angle = efl_get_app_window_angle ();
5319         if (angle == 90 || angle == 270)
5320             info.pos_y = _screen_width - info.height;
5321         else
5322             info.pos_y = _screen_height - info.height;
5323     } else {
5324         info = get_ise_geometry ();
5325         if (_ise_state != WINDOW_STATE_SHOW) {
5326             info.width = 0;
5327             info.height = 0;
5328         } else {
5329             if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5330                 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5331                     int height = ui_candidate_get_valid_height ();
5332
5333                     if ((_candidate_height - height) > _ise_height) {
5334                         info.pos_y  = info.pos_y + info.height - _candidate_height;
5335                         info.height = _candidate_height;
5336                     } else {
5337                         info.pos_y  -= height;
5338                         info.height += height;
5339                     }
5340                 }
5341             }
5342         }
5343 #endif /* CANDIDATE */
5344     }
5345
5346     LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5347     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5348                         << " width:" << info.width << " height:" << info.height << "\n";
5349 }
5350
5351 /**
5352  * @brief Get the recent input panel geometry slot function for PanelAgent.
5353  *
5354  * @param angle the rotation angle of application window.
5355  * @param info The data is used to store input panel position and size.
5356  */
5357 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info)
5358 {
5359     LOGD ("slot_get_recent_ise_geometry");
5360
5361     /* If we have geometry reported by ISE, use the geometry information */
5362     if (angle < 0) {
5363         angle = _ise_angle;
5364     }
5365
5366     if (angle == 0 || angle == 180) {
5367         if (_portrait_recent_ise_geometry.valid) {
5368             info = _portrait_recent_ise_geometry.geometry;
5369             return;
5370         }
5371     }
5372     else {
5373         if (_landscape_recent_ise_geometry.valid) {
5374             info = _landscape_recent_ise_geometry.geometry;
5375             return;
5376         }
5377     }
5378
5379     info.pos_x = -1;
5380     info.pos_y = -1;
5381     info.width = -1;
5382     info.height = -1;
5383 }
5384
5385 static bool slot_check_privilege_by_sockfd (int client_id, String privilege)
5386 {
5387     PrivilegeChecker privilegeChecker (client_id);
5388
5389     bool priv_ret = privilegeChecker.checkPrivilege (privilege.c_str ());
5390
5391     if (priv_ret == false)
5392         LOGW ("Failed to check privilege (%s)", privilege.c_str ());
5393     else
5394         LOGD ("Succeeded to check privilege (%s)", privilege.c_str ());
5395
5396     return priv_ret;
5397 }
5398
5399 /**
5400  * @brief Set active ISE slot function for PanelAgent.
5401  *
5402  * @param uuid The active ISE's uuid.
5403  * @param changeDefault The flag for changing default ISE.
5404  */
5405 static void slot_set_active_ise (const String &uuid, bool changeDefault)
5406 {
5407     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << uuid << ")\n";
5408
5409     bool invalid = false;
5410
5411 #ifdef HAVE_PKGMGR_INFO
5412     /* When changing the active (default) keyboard, initialize ime_info DB if appid is invalid.
5413        This may be necessary if IME packages are changed while panel process is terminated. */
5414     pkgmgrinfo_appinfo_h handle = NULL;
5415     /* Try to get in global packages */
5416     int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
5417     if (ret != PMINFO_R_OK) {
5418         LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
5419         /* This might happen if IME is uninstalled while the panel process is inactive.
5420            The variable uuid would be invalid, so set_active_ise() would return false. */
5421         invalid = true;
5422     }
5423
5424     if (handle)
5425         pkgmgrinfo_appinfo_destroy_appinfo (handle);
5426 #endif
5427
5428     if (invalid) {
5429         _initialize_ime_info ();
5430         set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5431     }
5432     else if (set_active_ise (uuid, _soft_keyboard_launched) == false) {
5433         if (_initial_ise_uuid.compare (uuid))
5434             set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5435     }
5436 }
5437
5438 /**
5439  * @brief Get all ISEs list slot function for PanelAgent.
5440  *
5441  * @param list The list is used to store all ISEs.
5442  *
5443  * @return true if this operation is successful, otherwise return false.
5444  */
5445 static bool slot_get_ise_list (std::vector<String> &list)
5446 {
5447     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5448
5449     bool result = false;
5450
5451     std::vector<String> uuids;
5452     for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5453         uuids.push_back(iter->appid);
5454     }
5455     if (_ime_info.size () > 0) {
5456         list =  uuids;
5457         result = true;
5458     }
5459     else {
5460         result = update_ise_list (list);
5461     }
5462
5463     return result;
5464 }
5465
5466 /**
5467  * @brief Get all Helper ISE information from ime_info DB.
5468  *
5469  * @param info This is used to store all Helper ISE information.
5470  *
5471  * @return true if this operation is successful, otherwise return false.
5472  */
5473 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info)
5474 {
5475     bool result = false;
5476     String active_ime_appid;
5477
5478     info.appid.clear ();
5479     info.label.clear ();
5480     info.is_enabled.clear ();
5481     info.is_preinstalled.clear ();
5482     info.has_option.clear ();
5483
5484     if (_ime_info.size() == 0)
5485         isf_pkg_select_all_ime_info_db (_ime_info);
5486
5487     //active_ime_appid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5488     if (_info_manager) {
5489         active_ime_appid = _info_manager->get_current_helper_uuid ();
5490     }
5491
5492     if (_ime_info.size () > 0) {
5493         for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
5494             if (iter->mode == TOOLBAR_HELPER_MODE) {
5495                 info.appid.push_back (iter->appid);
5496                 info.label.push_back (iter->label);
5497                 info.is_enabled.push_back (iter->is_enabled);
5498                 info.is_preinstalled.push_back (iter->is_preinstalled);
5499                 info.has_option.push_back (static_cast<uint32>(iter->has_option));
5500                 result = true;
5501             }
5502         }
5503     }
5504
5505     return result;
5506 }
5507
5508 /**
5509  * @brief Update "has_option" column of ime_info DB by Application ID
5510  *
5511  * @param[in] appid Application ID of IME to enable or disable
5512  * @param[in] has_option @c true to have IME option(setting), otherwise @c false
5513  */
5514 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option)
5515 {
5516     if (appid.length() == 0) {
5517         LOGW ("Invalid appid");
5518         return;
5519     }
5520
5521     if (_ime_info.size() == 0)
5522         isf_pkg_select_all_ime_info_db(_ime_info);
5523
5524     if (isf_db_update_has_option_by_appid(appid.c_str(), has_option)) {    // Update ime_info DB
5525         for (unsigned int i = 0; i < _ime_info.size (); i++) {
5526             if (appid == _ime_info[i].appid) {
5527                 _ime_info[i].has_option = static_cast<uint32>(has_option);  // Update global variable
5528             }
5529         }
5530     }
5531 }
5532
5533 /**
5534  * @brief Update "is_enable" column of ime_info DB by Application ID
5535  *
5536  * @param[in] appid Application ID of IME to enable or disable
5537  * @param[in] is_enabled @c true to enable the IME, otherwise @c false
5538  */
5539 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled)
5540 {
5541     if (appid.length() == 0) {
5542         LOGW ("Invalid appid");
5543         return;
5544     }
5545
5546     if (_ime_info.size() == 0)
5547         isf_pkg_select_all_ime_info_db(_ime_info);
5548
5549     if (isf_db_update_is_enabled_by_appid(appid.c_str(), is_enabled)) {    // Update ime_info DB
5550         for (unsigned int i = 0; i < _ime_info.size (); i++) {
5551             if (appid == _ime_info[i].appid) {
5552                 _ime_info[i].is_enabled = static_cast<uint32>(is_enabled);  // Update global variable
5553             }
5554         }
5555     }
5556 }
5557
5558 #ifdef HAVE_PKGMGR_INFO
5559 /**
5560  * @brief Finds appid with specific category
5561  *
5562  * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative
5563  */
5564 static int _find_appid_from_category (const pkgmgrinfo_appinfo_h handle, void *user_data)
5565 {
5566     if (user_data) {
5567         char **result = static_cast<char **>(user_data);
5568         char *appid = NULL;
5569         int ret = 0;
5570
5571         /* Get appid */
5572         ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
5573         if (ret == PMINFO_R_OK) {
5574             *result = strdup (appid);
5575         }
5576         else {
5577             LOGW ("pkgmgrinfo_appinfo_get_appid failed!");
5578         }
5579     }
5580     else {
5581         LOGW ("user_data is null!");
5582     }
5583
5584     return -1;  // This callback is no longer called.
5585 }
5586 #endif
5587
5588 /**
5589  * @brief Requests to open the installed IME list application.
5590  */
5591 static void slot_show_helper_ise_list (void)
5592 {
5593     // Launch IME List application; e.g., org.tizen.inputmethod-setting-list
5594     char *app_id = NULL;
5595 #ifdef HAVE_PKGMGR_INFO
5596     pkgmgrinfo_appinfo_filter_h handle;
5597     int ret;
5598
5599     if (ime_list_app.length() < 1) {
5600         ret = pkgmgrinfo_appinfo_filter_create (&handle);
5601         if (ret == PMINFO_R_OK) {
5602             ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-list");
5603             if (ret == PMINFO_R_OK) {
5604                 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
5605             }
5606             pkgmgrinfo_appinfo_filter_destroy (handle);
5607
5608             if (app_id)
5609                 ime_list_app = String (app_id);
5610         }
5611     }
5612     else
5613         app_id = strdup (ime_list_app.c_str());
5614 #endif
5615
5616     if (app_id) {
5617         app_control_launch (app_id);
5618         free(app_id);
5619     }
5620     else {
5621       SECURE_LOGW ("AppID with http://tizen.org/category/ime-list category is not available.");
5622     }
5623 }
5624
5625 /**
5626  * @brief Requests to open the installed IME selector application.
5627  */
5628 static void slot_show_helper_ise_selector (void)
5629 {
5630     // Launch IME Selector application; e.g., org.tizen.inputmethod-setting-selector
5631     char *app_id = NULL;
5632 #ifdef HAVE_PKGMGR_INFO
5633     pkgmgrinfo_appinfo_filter_h handle;
5634     int ret;
5635
5636     if (ime_selector_app.length() < 1) {
5637         ret = pkgmgrinfo_appinfo_filter_create(&handle);
5638         if (ret == PMINFO_R_OK) {
5639             ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
5640             if (ret == PMINFO_R_OK) {
5641                 pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, _find_appid_from_category, &app_id);
5642             }
5643             pkgmgrinfo_appinfo_filter_destroy(handle);
5644
5645             if (app_id)
5646                 ime_selector_app = String(app_id);
5647         }
5648     }
5649     else
5650         app_id = strdup(ime_selector_app.c_str());
5651 #endif
5652
5653     if (app_id) {
5654         app_control_launch (app_id);
5655         free(app_id);
5656     }
5657     else {
5658         SECURE_LOGW ("AppID with http://tizen.org/category/ime-selector category is not available.");
5659     }
5660 }
5661
5662 static bool slot_is_helper_ise_enabled (String appid, int &enabled)
5663 {
5664     bool is_enabled = false;
5665
5666     if (appid.length() == 0) {
5667         LOGW ("Invalid appid.");
5668         return false;
5669     }
5670
5671     if (_ime_info.size() == 0)
5672         isf_pkg_select_all_ime_info_db(_ime_info);
5673
5674     if (isf_db_select_is_enabled_by_appid(appid.c_str(), &is_enabled)) {
5675         enabled = static_cast<int>(is_enabled);
5676     }
5677     else
5678         return false;
5679
5680     return true;
5681 }
5682
5683 /**
5684  * @brief Get the ISE's information.
5685  *
5686  * @param uuid The ISE's uuid.
5687  * @param name The ISE's name.
5688  * @param language The ISE's language.
5689  * @param type The ISE's type.
5690  * @param option The ISE's option.
5691  *
5692  * @return true if this operation is successful, otherwise return false.
5693  */
5694 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name)
5695 {
5696     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5697
5698     if (uuid.length () > 0) {
5699         // update all ISE names according to the display languages
5700         // sometimes get_ise_information is called before vconf display language changed callback is called.
5701         update_ise_locale ();
5702
5703         for (unsigned int i = 0; i < _ime_info.size (); i++) {
5704             if (uuid == _ime_info[i].appid) {
5705                 name = _ime_info[i].label;
5706                 language = _ime_info[i].languages;
5707                 type  = _ime_info[i].mode;
5708                 option = _ime_info[i].options;
5709                 module_name = _ime_info[i].module_name;
5710                 return true;
5711             }
5712         }
5713     }
5714
5715     std::cerr << __func__ << " is failed!!!\n";
5716     return false;
5717 }
5718
5719 /**
5720  * @brief Get keyboard ISEs list slot function for PanelAgent.
5721  *
5722  * @param name_list The list is used to store keyboard ISEs.
5723  *
5724  * @return true if this operation is successful, otherwise return false.
5725  */
5726 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list)
5727 {
5728     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5729
5730     isf_load_ise_information (ALL_ISE, _config);
5731
5732     std::vector<String> lang_list, uuid_list;
5733     isf_get_all_languages (lang_list);
5734     isf_get_keyboard_ises_in_languages (lang_list, uuid_list, name_list, false);
5735
5736     _info_manager->update_ise_list (uuid_list);
5737     return true;
5738 }
5739
5740 /**
5741  * @brief Get enable languages list slot function for PanelAgent.
5742  *
5743  * @param list The list is used to store languages.
5744  */
5745 static void slot_get_language_list (std::vector<String> &list)
5746 {
5747     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5748
5749     String lang_name;
5750     MapStringVectorSizeT::iterator iter = _groups.begin ();
5751
5752     for (; iter != _groups.end (); iter++) {
5753         lang_name = scim_get_language_name (iter->first);
5754         list.push_back (lang_name);
5755     }
5756 }
5757
5758 /**
5759  * @brief Get all languages list slot function for PanelAgent.
5760  *
5761  * @param lang The list is used to store languages.
5762  */
5763 static void slot_get_all_language (std::vector<String> &lang)
5764 {
5765     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5766
5767     isf_get_all_languages (lang);
5768 }
5769
5770 /**
5771  * @brief Get specific ISE language list slot function for PanelAgent.
5772  *
5773  * @param name The ISE name.
5774  * @param list The list is used to store ISE languages.
5775  */
5776 static void slot_get_ise_language (char *name, std::vector<String> &list)
5777 {
5778     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5779
5780     if (name == NULL)
5781         return;
5782
5783     std::vector<String> list_tmp;
5784     list_tmp.clear ();
5785     for (unsigned int i = 0; i < _ime_info.size(); i++) {
5786         if (!strcmp (_ime_info[i].label.c_str (), name)) {
5787             scim_split_string_list (list_tmp, _ime_info[i].languages, ',');
5788             for (i = 0; i < list_tmp.size (); i++)
5789                 list.push_back (scim_get_language_name (list_tmp[i]));
5790             return;
5791         }
5792     }
5793 }
5794
5795 /**
5796  * @brief Get ISE information slot function for PanelAgent.
5797  *
5798  * @param uuid The ISE uuid.
5799  * @param info The variable is used to store ISE information.
5800  *
5801  * @return true if this operation is successful, otherwise return false.
5802  */
5803 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info)
5804 {
5805     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5806
5807     for (unsigned int i = 0; i < _ime_info.size (); i++) {
5808         if (!uuid.compare (_ime_info[i].appid)) {
5809             info.uuid   = _ime_info[i].appid;
5810             info.name   = _ime_info[i].label;
5811             info.icon   = _ime_info[i].iconpath;
5812             info.lang   = _ime_info[i].languages;
5813             info.option = _ime_info[i].options;
5814             info.type   = _ime_info[i].mode;
5815             return true;
5816         }
5817     }
5818
5819     return false;
5820 }
5821
5822 /**
5823  * @brief Set keyboard ISE slot function for PanelAgent.
5824  *
5825  * @param uuid The variable is ISE uuid.
5826  */
5827 static void slot_set_keyboard_ise (const String &uuid)
5828 {
5829     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << uuid << "\n";
5830
5831     std::vector<String> uuids;
5832     std::vector<ImeInfoDB>::iterator iter;
5833     for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5834         uuids.push_back(iter->appid);
5835     }
5836
5837     if (uuid.length () <= 0 || std::find (uuids.begin (), uuids.end (), uuid) == uuids.end ())
5838         return;
5839
5840     String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5841     if (_ime_info[get_ise_index (default_uuid)].mode == TOOLBAR_KEYBOARD_MODE)
5842         return;
5843
5844     uint32 ise_option = 0;
5845     String ise_uuid, ise_name;
5846     isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5847     if (ise_uuid == uuid)
5848         return;
5849
5850     String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
5851     _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
5852     _config->flush ();
5853     _config->reload ();
5854
5855     _info_manager->change_factory (uuid);
5856 }
5857
5858 /**
5859  * @brief Get current keyboard ISE name and uuid slot function for PanelAgent.
5860  *
5861  * @param ise_name The variable is used to store ISE name.
5862  * @param ise_uuid The variable is used to store ISE uuid.
5863  */
5864 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid)
5865 {
5866     uint32 ise_option = 0;
5867     isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5868
5869     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << ise_uuid << "\n";
5870 }
5871
5872 /**
5873  * @brief Accept connection slot function for PanelAgent.
5874  *
5875  * @param fd The file descriptor to connect.
5876  */
5877 static void slot_accept_connection (int fd)
5878 {
5879     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5880
5881 #ifdef HAVE_ECOREX
5882     get_input_window ();
5883 #endif
5884 }
5885
5886 /**
5887  * @brief Close connection slot function for PanelAgent.
5888  *
5889  * @param fd The file descriptor to connect.
5890  */
5891 static void slot_close_connection (int fd)
5892 {
5893     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5894 }
5895
5896 /**
5897  * @brief Exit panel process slot function for PanelAgent.
5898  */
5899 static void slot_exit (void)
5900 {
5901     std::cerr << __FUNCTION__ << "...\n";
5902     ISF_SAVE_LOG ("exit");
5903
5904 #if ISF_BUILD_CANDIDATE_UI
5905     elm_exit ();
5906 #else
5907     ecore_main_loop_quit ();
5908 #endif /* CANDIDATE */
5909 }
5910
5911 static void delete_ise_check_pid_alive_timer(void)
5912 {
5913     LOGD("deleting ise_check_alive_timer");
5914     if (_ise_check_pid_alive_timer) {
5915         ecore_timer_del(_ise_check_pid_alive_timer);
5916         _ise_check_pid_alive_timer = NULL;
5917     }
5918 }
5919
5920 static Eina_Bool ise_check_pid_alive_timer(void *data)
5921 {
5922     Eina_Bool ret = ECORE_CALLBACK_RENEW;
5923     Eina_Bool retry = EINA_FALSE;
5924
5925     int status = aul_app_get_status (_ise_check_pid_alive_uuid.c_str ());
5926     LOGD ("STATUS : %d", status);
5927     if (status >= STATUS_LAUNCHING) {
5928         /* If the status is not one of STATUS_LAUNCHING, STATUS_VISIBLE, STATUS_BG */
5929         if (status >= STATUS_DYING) {
5930             LOGE ("aul_app_get_status reports %d", status);
5931             retry = EINA_TRUE;
5932         }
5933     }
5934     else {
5935         /* Status query not successful, the ISE could have failed launching */
5936         LOGE ("aul_app_get_status failed. %d", status);
5937         retry = EINA_TRUE;
5938     }
5939
5940     if (retry) {
5941         _soft_keyboard_launched = false;
5942         String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
5943         /* The start_helper() function below will going to call slot_run_helper,
5944            which will going to assign a new timer handle to the _ise_check_pid_alive_timer variable.
5945         */
5946         LOGW ("The previous attempt to launch %s seems to be failed, restarting",
5947             _ise_check_pid_alive_uuid.c_str ());
5948         if (_info_manager->start_helper (uuid))
5949             _soft_keyboard_launched = true;
5950         ret = ECORE_CALLBACK_CANCEL;
5951     }
5952
5953     return ret;
5954 }
5955
5956 static void slot_register_helper(int id, const HelperInfo& info)
5957 {
5958     LOGD ("app id : %s", info.uuid.c_str ());
5959     /* Do we need to check whether the pid of this helper is the one we are watching? */
5960     if (info.uuid.compare(_ise_check_pid_alive_uuid) == 0) {
5961         delete_ise_check_pid_alive_timer();
5962     }
5963 }
5964
5965 static void slot_register_helper_properties (int id, const PropertyList &props)
5966 {
5967     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5968 #ifdef HAVE_ECOREX
5969     /* WMSYNC, #2 Receiving X window ID from ISE */
5970     /* FIXME : We should add an API to set window id of ISE */
5971     Property prop = props[0];
5972     if (prop.get_label ().compare ("XID") == 0) {
5973         Ecore_X_Window xwindow = atoi (prop.get_key ().c_str ());
5974         _ise_window = xwindow;
5975         LOGD ("ISE XID : %x", _ise_window);
5976
5977         /* Just in case for the helper sent this message later than show_ise request */
5978         if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
5979             efl_set_transient_for_app_window (_ise_window);
5980         }
5981
5982         Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_ISE_WINDOW");
5983         if (atom && _control_window && _ise_window) {
5984             ecore_x_window_prop_xid_set (_control_window, atom, ECORE_X_ATOM_WINDOW, &_ise_window, 1);
5985         }
5986 #ifdef HAVE_NOTIFICATION
5987         delete_notification (&ise_selector_module_noti);
5988 #endif
5989     }
5990 #endif
5991 }
5992
5993 #if ENABLE_REMOTE_INPUT
5994 static void slot_send_remote_input_message (const String &msg, bool len)
5995 {
5996     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5997
5998     String con = msg.c_str ();
5999     ISE_MESSAGE message = CISEMessageSerializer::deserialize(con);
6000
6001     if (remote_input_impl == NULL) {
6002         remote_input_impl = Remote_Input::get_instance();
6003     }
6004
6005     if (remote_input_impl)
6006         remote_input_impl->handle_websocket_message(message);
6007 }
6008
6009 static void slot_recv_remote_surrounding_text (int cursor, const String &text)
6010 {
6011     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6012
6013     if (remote_input_impl == NULL) {
6014         remote_input_impl = Remote_Input::get_instance();
6015     }
6016
6017     if (remote_input_impl)
6018         remote_input_impl->handle_recv_panel_message(3, text.c_str (), cursor);
6019 }
6020 #endif
6021
6022 static void slot_show_ise (void)
6023 {
6024     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6025
6026     /* If the current toolbar mode is not HELPER_MODE, do not proceed */
6027     if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
6028         LOGD ("Current toolbar mode should be TOOLBAR_HELPER_MODE but is %d, returning",
6029             _info_manager->get_current_toolbar_mode ());
6030         return;
6031     }
6032
6033     LOGD ("slot_show_ise ()");
6034
6035     delete_ise_hide_timer ();
6036 #ifdef HAVE_ECOREX
6037     /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
6038     // Unset conformant area
6039     Ecore_X_Window current_app_window = efl_get_app_window ();
6040     if (_app_window != current_app_window) {
6041         struct rectinfo info = {0, 0, 0, 0};
6042         info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
6043         set_keyboard_geometry_atom_info (_app_window, info);
6044         ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6045         LOGD ("Conformant reset for window %x", _app_window);
6046         _app_window = current_app_window;
6047
6048         /* If the target window has changed but our ISE is still in visible state,
6049            update the keyboard geometry information */
6050         if (_ise_state == WINDOW_STATE_SHOW) {
6051             set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6052         }
6053     }
6054
6055     /* If the candidate was already in SHOW state, respect the current angle */
6056     if (_candidate_state != WINDOW_STATE_SHOW) {
6057         /* FIXME : Need to check if candidate_angle and window_angle should be left as separated */
6058         _candidate_angle = efl_get_app_window_angle ();
6059     }
6060     /* If the ise was already in SHOW state, respect the current angle */
6061     if (_ise_state != WINDOW_STATE_SHOW) {
6062         _ise_angle = efl_get_app_window_angle ();
6063     }
6064
6065     ecore_x_event_mask_set (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6066     efl_set_transient_for_app_window (_ise_window);
6067
6068     /* Make clipboard window to have transient_for information on ISE window,
6069        so that the clipboard window will always be above ISE window */
6070     Ecore_X_Window clipboard_window = efl_get_clipboard_window ();
6071     if (_ise_window && clipboard_window) {
6072         ecore_x_icccm_transient_for_set (clipboard_window, _ise_window);
6073     }
6074
6075     /* If our ISE was already in SHOW state, skip state transition to WILL_SHOW */
6076     if (_ise_state != WINDOW_STATE_SHOW) {
6077         _ise_state = WINDOW_STATE_WILL_SHOW;
6078     }
6079 #else
6080     _ise_angle = 0;
6081 #if ISF_BUILD_CANDIDATE_UI
6082     _candidate_angle = 0;
6083 #endif /* CANDIDATE */
6084     _ise_state = WINDOW_STATE_SHOW;
6085
6086 #ifdef HAVE_NOTIFICATION
6087     if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6088         if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6089             show_ime_selector_notification ();
6090         }
6091     }
6092 #endif
6093 #endif
6094 }
6095
6096 static void slot_hide_ise (void)
6097 {
6098     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6099
6100     LOGD ("slot_hide_ise ()");
6101
6102     if (!_ise_hide_timer)
6103         hide_ise ();
6104 }
6105
6106 static void slot_will_hide_ack (void)
6107 {
6108     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6109 #ifdef HAVE_ECOREX
6110     /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
6111     // WILL_HIDE_REQUEST_DONE Ack to WM
6112     Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6113     //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
6114     LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
6115             root_window, _control_window);
6116     if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6117         LOGD ("calling ui_candidate_hide (true, false)");
6118         ui_candidate_hide (true, false);
6119     }
6120
6121     /* WILL_HIDE_ACK means that the application finished redrawing the autoscroll area,
6122        now hide the candidate window right away if it is also in WILL_HIDE state */
6123     if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6124         candidate_window_hide ();
6125     }
6126
6127     if (_off_prepare_done_timer) {
6128         ecore_timer_del (_off_prepare_done_timer);
6129         _off_prepare_done_timer = NULL;
6130     }
6131 #endif
6132 }
6133
6134 static void slot_candidate_will_hide_ack (void)
6135 {
6136     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6137 #ifdef HAVE_ECOREX
6138     LOGD ("candidate_will_hide_ack");
6139     if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6140         candidate_window_hide ();
6141     }
6142 #endif
6143 }
6144
6145 static void slot_set_keyboard_mode (int mode)
6146 {
6147     LOGD ("slot_set_keyboard_mode called (TOOLBAR_MODE : %d)", mode);
6148
6149     change_keyboard_mode ((TOOLBAR_MODE_T)mode);
6150 }
6151
6152 static void slot_get_ise_state (int &state)
6153 {
6154     if (_ise_state == WINDOW_STATE_SHOW ||
6155         ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (_candidate_state == WINDOW_STATE_SHOW))) {
6156         state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6157     } else {
6158         /* Currently we don't have WILL_HIDE / HIDE state distinction in Ecore_IMF */
6159         switch (_ise_state) {
6160             case WINDOW_STATE_SHOW :
6161                 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6162                 break;
6163             case WINDOW_STATE_WILL_SHOW :
6164                 state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
6165                 break;
6166             case WINDOW_STATE_WILL_HIDE :
6167                 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6168                 break;
6169             case WINDOW_STATE_HIDE :
6170                 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6171                 break;
6172             default :
6173                 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6174         };
6175     }
6176     LOGD ("state = %d", state);
6177     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " state = " << state << "\n";
6178 }
6179
6180 static void slot_start_default_ise (void)
6181 {
6182     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6183
6184     if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE)) {
6185         String uuid  = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6186         int pid = aul_app_get_pid (uuid.c_str ());
6187         if (pid >= 0) {
6188             if (STATUS_DYING == aul_app_get_status (uuid.c_str ()))
6189                 pid = -1;
6190         }
6191         if ((_launch_ise_on_request || !_enable_auto_restart) && !_soft_keyboard_launched && pid < 0) {
6192             LOGD ("Start helper (%s)", uuid.c_str ());
6193             set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
6194
6195             if (_info_manager->start_helper (uuid))
6196                 _soft_keyboard_launched = true;
6197             else
6198                 LOGW ("Failed to start helper (%s)", uuid.c_str ());
6199         }
6200     }
6201 }
6202
6203 static void slot_stop_default_ise (bool is_exist)
6204 {
6205     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6206
6207     if (is_exist) {
6208         if (_launch_ise_on_request && _auto_destroy_ise && _soft_keyboard_launched) {
6209             String uuid = _info_manager->get_current_helper_uuid ();
6210
6211             if (uuid.length () > 0) {
6212                 _info_manager->hide_helper (uuid);
6213                 _info_manager->stop_helper (uuid);
6214                 _soft_keyboard_launched = false;
6215                 LOGD ("stop helper (%s)", uuid.c_str ());
6216             }
6217         }
6218     } else {
6219         if (_soft_keyboard_launched)
6220             _soft_keyboard_launched = false;
6221     }
6222 }
6223
6224 static void launch_helper (const char* exec, const char *name, const char *appid, const char *config, const char *display)
6225 {
6226     int pid;
6227
6228     pid = fork ();
6229
6230     if (pid < 0) return;
6231
6232     if (pid == 0) {
6233         const char *argv [] = { exec,
6234                            "--daemon",
6235                            "--config", config,
6236                            "--display", display,
6237                            const_cast<char*> (name),
6238                            const_cast<char*> (appid),
6239                            0};
6240
6241         SCIM_DEBUG_MAIN (2) << " Call scim-helper-launcher.\n";
6242         ISF_SAVE_LOG ("Exec scim_helper_launcher(%s %s)", name, appid);
6243
6244         unsetenv ("ELM_THEME");
6245         unsetenv ("ELM_SCALE");
6246
6247         setsid ();
6248         LOGD ("launch execpath : %s", exec);
6249         execv (exec, const_cast<char **>(argv));
6250 #if ISF_BUILD_CANDIDATE_UI
6251         elm_exit ();
6252 #else
6253         ecore_main_loop_quit ();
6254 #endif /* CANDIDATE */
6255     }
6256 }
6257
6258 static bool app_control_launch (const char *app_id)
6259 {
6260     app_control_h app_control;
6261     int ret;
6262
6263     ret = app_control_create (&app_control);
6264     if (ret != APP_CONTROL_ERROR_NONE) {
6265         LOGW ("app_control_create returned %08x", ret);
6266         return false;
6267     }
6268
6269     ret = app_control_set_operation (app_control, APP_CONTROL_OPERATION_DEFAULT);
6270     if (ret != APP_CONTROL_ERROR_NONE) {
6271         LOGW ("app_control_set_operation returned %08x", ret);
6272         app_control_destroy (app_control);
6273         return false;
6274     }
6275
6276     ret = app_control_set_app_id (app_control, app_id);
6277     if (ret != APP_CONTROL_ERROR_NONE) {
6278         LOGW ("app_control_set_app_id returned %08x", ret);
6279         app_control_destroy (app_control);
6280         return false;
6281     }
6282
6283     if (_TV && _preloading_ise) {
6284         ret = app_control_add_extra_data(app_control, "Preloading", "true");
6285         if (ret != APP_CONTROL_ERROR_NONE) {
6286             LOGW ("app_control_add_extra_data returned %08x", ret);
6287         }
6288     }
6289
6290     int tries = 0;
6291     do {
6292         if (tries != 0) usleep(1000000); /* If we are retrying to launch, pause for a while */
6293         ret = app_control_send_launch_request(app_control, NULL, NULL);
6294         LOGW ("app_control_send_launch_request returned %08x, app_id=%s", ret, app_id);
6295     } while (ret != APP_CONTROL_ERROR_NONE && (++tries) < 3);
6296
6297     app_control_destroy (app_control);
6298
6299     if (ret != APP_CONTROL_ERROR_NONE) {
6300         LOGW ("Failed to launch IME. appid(%s). reason(%s)", app_id, get_error_message(ret));
6301     } else {
6302         LOGD ("Succeeded to launch IME. appid(%s)", app_id);
6303     }
6304
6305     return (ret == APP_CONTROL_ERROR_NONE);
6306 }
6307
6308 static void add_ise_check_pid_alive_timer(const String &uuid) {
6309     delete_ise_check_pid_alive_timer ();
6310     LOGD ("Register check_alive timer for uuid : %s", uuid.c_str ());
6311     _ise_check_pid_alive_uuid = uuid;
6312     _ise_check_pid_alive_timer = ecore_timer_add (_ise_check_pid_alive_time,
6313         ise_check_pid_alive_timer, NULL);
6314 }
6315
6316 static void terminate_active_ise (const String uuid)
6317 {
6318     /* Check if IME with the same AppID is alive */
6319     int status_ret = aul_app_get_status (uuid.c_str ());
6320     if (status_ret >= STATUS_LAUNCHING) {
6321         /* Request to terminate IME */
6322         int ime_pid = aul_app_get_pid (uuid.c_str ());
6323         status_ret = aul_terminate_pid (ime_pid);
6324         if (status_ret < AUL_R_OK) {
6325             LOGE ("aul_terminate_pid(%d) failed: %d", ime_pid, status_ret);
6326         }
6327         else {
6328             LOGD ("Requested to terminate IME(%s)", uuid.c_str ());
6329             usleep (1000000);
6330         }
6331     }
6332 }
6333
6334 static void set_cpu_boosting ()
6335 {
6336     resource_pid_t resource_st;
6337     resource_st.pid = getpid();
6338     int ret = resource_set_cpu_boosting(resource_st, CPU_BOOSTING_LEVEL_STRONG, CPU_BOOSTING_RESET_ON_FORK, -1);
6339     if (ret != 0)
6340         LOGE("Failed to set cpu boosting");
6341 }
6342
6343 static void clear_cpu_boosting ()
6344 {
6345     resource_pid_t resource_st;
6346     resource_st.pid = getpid();
6347     int ret = resource_clear_cpu_boosting(resource_st);
6348     if (ret != 0)
6349         LOGE("Failed to clear cpu boosting");
6350 }
6351
6352 static void slot_run_helper (const String &uuid, const String &config, const String &display)
6353 {
6354     ISF_SAVE_LOG ("time:%ld  pid:%d  %s  %s  uuid(%s)",
6355         time (0), getpid (), __FILE__, __func__, uuid.c_str ());
6356
6357     String scim_helper_path;
6358
6359     delete_ise_check_pid_alive_timer ();
6360
6361 #ifdef HAVE_PKGMGR_INFO
6362     char *execpath = NULL;
6363     int ret;
6364     pkgmgrinfo_appinfo_h appinfo_handle;
6365
6366     /* get app info handle */
6367     /* Try to get in global packages */
6368     ret = pkgmgr_get_appinfo (uuid.c_str (), &appinfo_handle);
6369     if (ret != PMINFO_R_OK) {
6370         LOGE ("pkgmgr_get_appinfo failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6371         add_ise_check_pid_alive_timer (uuid);
6372         return;
6373     }
6374
6375     /* Get exec path */
6376     ret = pkgmgrinfo_appinfo_get_exec (appinfo_handle, &execpath);
6377     if (ret != PMINFO_R_OK) {
6378         LOGE ("pkgmgrinfo_appinfo_get_exec failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6379         pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6380         add_ise_check_pid_alive_timer (uuid);
6381         return;
6382     }
6383
6384     LOGD ("exec path : %s %zu", execpath, _ime_info.size ());
6385     scim_helper_path = String (execpath);
6386
6387     if (appinfo_handle) {
6388         pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6389         appinfo_handle = NULL;
6390     }
6391 #else
6392     scim_helper_path = String (SCIM_HELPER_LAUNCHER_PROGRAM);
6393 #endif
6394
6395     for (size_t i = 0; i < _ime_info.size (); ++i) {
6396         if (_ime_info[i].appid == uuid && _ime_info[i].module_name.length ()) {
6397             if (scim_helper_path != String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
6398                 terminate_active_ise (uuid);
6399                 /* execute type IME */
6400                 LOGD ("Try to launch IME (%s)", uuid.c_str ());
6401                 app_control_launch (uuid.c_str ());
6402
6403                 /* ISE check alive only works for AUL based IMEs */
6404                 add_ise_check_pid_alive_timer (uuid);
6405             }
6406             else {
6407                 /* shared object (so) type IME */
6408                 launch_helper (scim_helper_path.c_str(), _ime_info[i].module_name.c_str (), uuid.c_str (), config.c_str (), display.c_str ());
6409             }
6410
6411             _soft_keyboard_launched = true;
6412             break;
6413         }
6414     }
6415
6416     SCIM_DEBUG_MAIN (2) << " exit run_helper ().\n";
6417 }
6418
6419 static bool slot_launch_option_application (String ime_appid)
6420 {
6421     String ime_setting_app = isf_pkg_get_setting_app (ime_appid);
6422
6423     LOGD ("IME appid(%s), IME setting app id(%s)", ime_appid.c_str (), ime_setting_app.c_str ());
6424
6425     if (ime_setting_app.length () > 0) {
6426         app_control_launch (ime_setting_app.c_str ());
6427         return true;
6428     }
6429
6430     return false;
6431 }
6432
6433 static bool slot_get_ise_setting_appid (String ime_appid, String &ime_setting_appid)
6434 {
6435     ime_setting_appid = isf_pkg_get_setting_app (ime_appid);
6436
6437     LOGD ("IME appid : %s, IME setting app ID : %s", ime_appid.c_str(), ime_setting_appid.c_str());
6438     return ime_setting_appid.length () > 0 ? true : false;
6439 }
6440
6441 static void slot_set_preloading_ise (bool preloading)
6442 {
6443     _preloading_ise = preloading;
6444 }
6445
6446 //////////////////////////////////////////////////////////////////////
6447 // End of PanelAgent-Functions
6448 //////////////////////////////////////////////////////////////////////
6449
6450
6451 /**
6452  * @brief Callback function for abnormal signal.
6453  *
6454  * @param sig The signal.
6455  */
6456 static void signalhandler (int sig)
6457 {
6458     std::cerr << __FUNCTION__ << " Signal=" << sig << "\n";
6459     ISF_SAVE_LOG ("Signal=%d", sig);
6460
6461 #if ISF_BUILD_CANDIDATE_UI
6462     elm_exit ();
6463 #else
6464     ecore_main_loop_quit ();
6465 #endif /* CANDIDATE */
6466 }
6467
6468 #ifdef HAVE_VCONF
6469 static void update_ise_locale (const char *language)
6470 {
6471     String strLang;
6472
6473     if (language) {
6474         strLang = String (language);
6475     }
6476     else {
6477         char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
6478         if (lang_str) {
6479             if (_locale_string.compare(lang_str) == 0) {
6480                 free (lang_str);
6481                 return;
6482             }
6483
6484             strLang = String (lang_str);
6485
6486             free (lang_str);
6487         }
6488     }
6489
6490     LOGD ("update all ISE names according to display language : %s", strLang.c_str ());
6491     set_language_and_locale (strLang.c_str ());
6492
6493     bool need_to_init_db = false;
6494 #ifdef HAVE_PKGMGR_INFO
6495     int ret = 0;
6496     bool exist = false;
6497     char *label = NULL;
6498     pkgmgrinfo_appinfo_h handle = NULL;
6499
6500     /* Read DB from ime_info table */
6501     isf_load_ise_information(ALL_ISE, _config);
6502
6503     for (unsigned int i = 0; i < _ime_info.size (); i++) {
6504         ret = pkgmgr_get_appinfo (_ime_info[i].appid.c_str(), &handle);
6505
6506         if (ret == PMINFO_R_OK) {
6507             ret = pkgmgrinfo_appinfo_is_category_exist(handle, "http://tizen.org/category/ime", &exist);
6508             if (ret == PMINFO_R_OK && exist) {
6509                 ret = pkgmgrinfo_appinfo_get_label(handle, &label);
6510                 if (ret == PMINFO_R_OK && label) {
6511                     _ime_info[i].label = String(label);
6512                     /* Update label column in ime_info db table */
6513                     if (isf_db_update_label_by_appid(_ime_info[i].appid.c_str(), label)) {
6514                         _ime_info[i].label = label;
6515                     }
6516                 }
6517             }
6518             else {
6519                 // The appid is invalid.. Need to initialize ime_info DB.
6520                 need_to_init_db = true;
6521             }
6522             pkgmgrinfo_appinfo_destroy_appinfo(handle);
6523         }
6524         else {
6525             // The appid is invalid.. Need to initialize ime_info DB.
6526             need_to_init_db = true;
6527         }
6528     }
6529 #endif
6530
6531     if (need_to_init_db) {
6532         _initialize_ime_info ();
6533     }
6534
6535     if (strLang.length () > 0) {
6536         isf_db_update_disp_lang (strLang.c_str ());
6537         _locale_string = strLang;
6538     }
6539 }
6540
6541 /**
6542  * @brief Set language and locale.
6543  *
6544  * @return void
6545  */
6546 static void set_language_and_locale (const char *lang_str)
6547 {
6548     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6549
6550     char language[256];
6551
6552     if (lang_str) {
6553         LOGD ("language : %s", lang_str);
6554 #if ISF_BUILD_CANDIDATE_UI
6555         elm_language_set (lang_str);
6556 #endif /* CANDIDATE */
6557
6558         snprintf (language, sizeof (language), "%s:en_US:en_GB:en", lang_str);
6559         setenv ("LANGUAGE", language, 1);
6560         setenv ("LANG", lang_str, 1);
6561         setlocale (LC_MESSAGES, lang_str);
6562     } else {
6563         setenv ("LANG", "en_US.utf8", 1);
6564         setlocale (LC_MESSAGES, "en_US.utf8");
6565     }
6566 }
6567
6568 /**
6569  * @brief Callback function for display language change.
6570  *
6571  * @param key The key node.
6572  * @param data The data to pass to this callback.
6573  *
6574  * @return void
6575  */
6576 static void display_language_changed_cb (keynode_t *key, void* data)
6577 {
6578     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6579
6580     char *lang_str = vconf_keynode_get_str (key);
6581     LOGD ("lang : %s", lang_str);
6582     set_language_and_locale (lang_str);
6583
6584     /* Update all ISE names according to display language */
6585     update_ise_locale ();
6586
6587     String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
6588     unsigned int ise_idx = get_ise_index (default_uuid);
6589
6590     if (ise_idx < _ime_info.size ()) {
6591         String default_name = _ime_info[ise_idx].label;
6592         _info_manager->set_current_ise_name (default_name);
6593         _config->reload ();
6594     }
6595 }
6596
6597 /**
6598  * @brief Callback function for keyboard mode change.
6599  *
6600  * @param key The key node.
6601  * @param data The data to pass to this callback.
6602  *
6603  * @return void
6604  */
6605 static void keyboard_mode_changed_cb (keynode_t *key, void* data)
6606 {
6607     bool val = vconf_keynode_get_bool (key);
6608
6609     if (val == 0) {
6610         _info_manager->reset_keyboard_ise ();
6611         change_keyboard_mode (TOOLBAR_HELPER_MODE);
6612         _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6613     }
6614 }
6615 #endif
6616
6617 static void set_hw_keyboard_input_detect_flag(bool flag)
6618 {
6619 #ifdef HAVE_VCONF
6620     int input_detect = false;
6621
6622     if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect) == 0) {
6623         if (input_detect != flag) {
6624             if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, flag) != 0)
6625                 LOGW ("Failed to set vconf key");
6626             else
6627                 LOGD ("Succeeded to set vconf key");
6628         }
6629     }
6630 #endif
6631 }
6632
6633 /**
6634  * @brief Change keyboard mode.
6635  *
6636  * @param mode The keyboard mode.
6637  *
6638  * @return void
6639  */
6640 static void change_keyboard_mode (TOOLBAR_MODE_T mode)
6641 {
6642     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6643     uint32 option = 0;
6644     String uuid, name;
6645     bool _support_hw_keyboard_mode = false;
6646 #ifdef HAVE_ECOREX
6647     unsigned int val = 0;
6648 #endif
6649
6650     String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6651     String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6652     _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
6653
6654     if (mode == TOOLBAR_KEYBOARD_MODE && _support_hw_keyboard_mode) {
6655         if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6656             LOGD ("HARDWARE_KEYBOARD_MODE return");
6657             return;
6658         }
6659
6660         LOGD ("HARDWARE KEYBOARD MODE");
6661         _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 1);
6662         _config->flush ();
6663
6664         if (_ime_info[get_ise_index(default_uuid)].mode == TOOLBAR_HELPER_MODE) {
6665             /* Get the keyboard ISE */
6666             isf_get_keyboard_ise (_config, uuid, name, option);
6667             if (option & SCIM_IME_NOT_SUPPORT_HARDWARE_KEYBOARD) {
6668                 uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
6669                 std::cerr << __FUNCTION__ << ": Keyboard ISE (" << name << ") can not support hardware keyboard!!!\n";
6670             }
6671             /* Try to find reasonable keyboard ISE according to helper ISE language */
6672             if (uuid == String (SCIM_COMPOSE_KEY_FACTORY_UUID)) {
6673                 String helper_language = _ime_info[get_ise_index(default_uuid)].languages;
6674                 if (helper_language.length () > 0) {
6675                     std::vector<String> ise_langs;
6676                     scim_split_string_list (ise_langs, helper_language);
6677                     for (size_t i = 0; i < _groups[ise_langs[0]].size (); ++i) {
6678                         int j = _groups[ise_langs[0]][i];
6679                         if (_ime_info[j].appid != uuid && _ime_info[j].mode == TOOLBAR_KEYBOARD_MODE) {
6680                             uuid = _ime_info[j].appid;
6681                             break;
6682                         }
6683                     }
6684                 }
6685             }
6686         }
6687         else {
6688             uuid = default_uuid;
6689         }
6690 #if ISF_BUILD_CANDIDATE_UI
6691         _soft_candidate_width = 0;
6692         _soft_candidate_height = 0;
6693 #endif /* CANDIDATE */
6694         _ise_state = WINDOW_STATE_HIDE;
6695         _info_manager->set_current_toolbar_mode (TOOLBAR_KEYBOARD_MODE);
6696         _info_manager->hide_helper (helper_uuid);
6697
6698         /* Check whether stop soft keyboard */
6699         if (_focus_in && (_ime_info[get_ise_index (helper_uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
6700             /* If focus in and soft keyboard can support hardware key event, then don't stop it */
6701             ;
6702         } else if (_launch_ise_on_request && _soft_keyboard_launched) {
6703             _info_manager->stop_helper (helper_uuid);
6704             _soft_keyboard_launched = false;
6705         }
6706 #ifdef HAVE_ECOREX
6707         ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6708 #endif
6709
6710 #ifdef HAVE_NOTIFICATION
6711         LOGI("Input detected from H/W keyboard");
6712         if (_MOBILE || _COMMON) {
6713             notification_status_message_post (_("Input detected from hardware keyboard"));
6714
6715             /* Read configurations for notification app (isf-kbd-mode-changer) */
6716             String kbd_mode_changer = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_KBD_MODE_CHANGER_PROGRAM), String (""));
6717             hwkbd_module_noti.launch_app = kbd_mode_changer;
6718             LOGD ("Create kbd_mode_changer notification with : %s", kbd_mode_changer.c_str ());
6719             create_notification (&hwkbd_module_noti);
6720         }
6721 #endif
6722
6723         set_hw_keyboard_input_detect_flag(true);
6724     } else if (mode == TOOLBAR_HELPER_MODE) {
6725         LOGD ("SOFTWARE KEYBOARD MODE");
6726         /* When switching back to S/W keyboard mode, let's hide candidate window first */
6727 #if ISF_BUILD_CANDIDATE_UI
6728         LOGD ("calling ui_candidate_hide (true, true, true)");
6729         ui_candidate_hide (true, true, true);
6730 #endif /* CANDIDATE */
6731         _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
6732         _config->flush ();
6733         if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6734             uuid = helper_uuid.length () > 0 ? helper_uuid : _initial_ise_uuid;
6735             if (_launch_ise_on_request) {
6736                 if (set_active_ise (uuid, false) == false) {
6737                     if (_initial_ise_uuid.compare(uuid))
6738                         set_active_ise (_initial_ise_uuid, false);
6739                 }
6740             }
6741             else {
6742                 if (set_active_ise (uuid, true) == false) {
6743                     if (_initial_ise_uuid.compare(uuid)) {
6744                         LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
6745                         set_active_ise (_initial_ise_uuid, true);
6746                     }
6747                 }
6748             }
6749         }
6750
6751 #ifdef HAVE_NOTIFICATION
6752         delete_notification (&hwkbd_module_noti);
6753 #endif
6754
6755         set_hw_keyboard_input_detect_flag(false);
6756     }
6757     _config->reload ();
6758 }
6759
6760 #ifdef HAVE_NOTIFICATION
6761 static void show_ime_selector_notification ()
6762 {
6763     String ise_name;
6764
6765     if (!_MOBILE && !_COMMON) return;
6766
6767     unsigned int idx = get_ise_index (_info_manager->get_current_helper_uuid ());
6768     if (idx < _ime_info.size ())
6769         ise_name = _ime_info[idx].label;
6770
6771     String noti_icon_path = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_QUICK_PANEL_ICON_PATH), String (SCIM_ICONDIR));
6772     noti_icon_path += ISF_ISE_SELECTOR_ICON_FILE;
6773
6774     LOGD("IME selector icon path : %s", noti_icon_path.c_str ());
6775
6776     ise_selector_module_noti.icon = noti_icon_path;
6777     ise_selector_module_noti.content = ise_name;
6778
6779     /* Find IME Selector appid for notification */
6780     if (ime_selector_app.length () < 1) {
6781         char *app_id = NULL;
6782         pkgmgrinfo_appinfo_filter_h handle;
6783         int ret = pkgmgrinfo_appinfo_filter_create (&handle);
6784         if (ret == PMINFO_R_OK) {
6785             ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
6786             if (ret == PMINFO_R_OK) {
6787                 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
6788             }
6789             pkgmgrinfo_appinfo_filter_destroy (handle);
6790
6791             if (app_id) {
6792                 ime_selector_app = String (app_id);
6793                 free (app_id);
6794                 app_id = NULL;
6795             }
6796         }
6797     }
6798
6799     if (ime_selector_app.length () > 0) {
6800         ise_selector_module_noti.launch_app = ime_selector_app;
6801         LOGD ("Create ise_selector notification with : %s", ime_selector_app.c_str ());
6802         create_notification (&ise_selector_module_noti);
6803     }
6804     else
6805         LOGW ("AppID with http://tizen.org/category/ime-selector category is not available");
6806 }
6807 #endif
6808
6809 #ifdef HAVE_ECOREX
6810 /**
6811  * @brief Callback function for ECORE_X_EVENT_WINDOW_PROPERTY.
6812  *
6813  * @param data Data to pass when it is called.
6814  * @param ev_type The event type.
6815  * @param ev The information for current message.
6816  *
6817  * @return ECORE_CALLBACK_PASS_ON
6818  */
6819 static Eina_Bool x_event_window_property_cb (void *data, int ev_type, void *event)
6820 {
6821     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6822
6823     Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property *)event;
6824
6825     if (ev == NULL)
6826         return ECORE_CALLBACK_PASS_ON;
6827
6828     if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
6829         if (ev->win == _control_window) {
6830             /* WMSYNC, #6 The keyboard window is displayed fully so set the conformant geometry */
6831             LOGD ("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE : win : %p, atom : %d", ev->win, ev->atom);
6832             Ecore_X_Virtual_Keyboard_State state;
6833             state = ecore_x_e_virtual_keyboard_state_get (ev->win);
6834             if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON) {
6835                 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_ON");
6836                 _ise_state = WINDOW_STATE_SHOW;
6837
6838                 /* Make sure that we have the same rotation angle with the keyboard window */
6839                 if (_ise_window) {
6840                     _candidate_angle = efl_get_ise_window_angle ();
6841                     _ise_angle = efl_get_ise_window_angle ();
6842                 }
6843
6844                 if (_candidate_show_requested) {
6845                     LOGD ("calling ui_candidate_show (true)");
6846                     ui_candidate_show (true);
6847                 } else {
6848                     if (_candidate_area_1_visible) {
6849                         LOGD ("calling ui_candidate_show (false)");
6850                         ui_candidate_show (false);
6851                     }
6852                 }
6853
6854                 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6855                 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6856                 _info_manager->update_input_panel_event (
6857                         ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_SHOW);
6858
6859 #ifdef HAVE_VCONF
6860                 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW);
6861 #endif
6862
6863                 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6864                     if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6865                         ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6866
6867 #ifdef HAVE_NOTIFICATION
6868                         show_ime_selector_notification ();
6869 #endif
6870                     }
6871                 }
6872
6873                 _updated_hide_state_geometry = false;
6874
6875                 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
6876             } else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) {
6877                 /* WMSYNC, #9 The keyboard window is hidden fully so send HIDE state */
6878                 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF");
6879                 // For now don't send HIDE signal here
6880                 //_info_manager->update_input_panel_event (
6881                 //    ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6882                 _ise_state = WINDOW_STATE_HIDE;
6883                 _ise_angle = -1;
6884                 if (!_updated_hide_state_geometry) {
6885                     /* When the ISE gets hidden by the window manager forcefully without OFF_PREPARE,
6886                        the application might not have updated its autoscroll area */
6887                     set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6888                     _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6889                     _info_manager->update_input_panel_event (
6890                             ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6891
6892                     _updated_hide_state_geometry = true;
6893                 }
6894                 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6895                     LOGD ("calling ui_candidate_hide (true, false)");
6896                     ui_candidate_hide (true, false);
6897                 } else {
6898                     ui_settle_candidate_window ();
6899                 }
6900
6901 #ifdef HAVE_VCONF
6902                 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
6903 #endif
6904
6905 #ifdef HAVE_NOTIFICATION
6906                 delete_notification (&ise_selector_module_noti);
6907 #endif
6908
6909                 _ise_reported_geometry.valid = false;
6910
6911                 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
6912             }
6913             ui_settle_candidate_window ();
6914         }
6915     } else if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
6916         if (ev->win == efl_get_quickpanel_window ()) {
6917             int angle = efl_get_quickpanel_window_angle ();
6918             LOGD ("ev->win : %p, change window angle : %d", ev->win, angle);
6919         }
6920     }
6921
6922     return ECORE_CALLBACK_PASS_ON;
6923 }
6924
6925 /**
6926  * @brief Callback function for X event client message.
6927  *
6928  * @param data Data to pass when it is called.
6929  * @param type The event type.
6930  * @param event The information for current message.
6931  *
6932  * @return ECORE_CALLBACK_RENEW
6933  */
6934 static Eina_Bool x_event_client_message_cb (void *data, int type, void *event)
6935 {
6936     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6937
6938     Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
6939
6940     if (ev == NULL)
6941         return ECORE_CALLBACK_RENEW;
6942
6943 #if 0
6944     if ((ev->win == _control_window)) {
6945         if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST) {
6946             /* WMSYNC, #4 Send WILL_SHOW event when the keyboard window is about to displayed */
6947             LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST");
6948
6949             /* WMSYNC, #5 Let the Window Manager to actually show keyboard window */
6950             // WILL_SHOW_REQUEST_DONE Ack to WM
6951             Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6952             ecore_x_e_virtual_keyboard_on_prepare_done_send (root_window, _control_window);
6953             LOGD ("_ecore_x_e_virtual_keyboard_on_prepare_done_send (%x, %x)",
6954                     root_window, _control_window);
6955
6956             _info_manager->update_input_panel_event (
6957                     ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
6958             ui_create_candidate_window ();
6959
6960             vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_SHOW);
6961         } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST) {
6962             _ise_state = WINDOW_STATE_WILL_HIDE;
6963             /* WMSYNC, #7 Send WILL_HIDE event when the keyboard window is about to hidden */
6964             LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST");
6965             // Clear conformant geometry information first
6966
6967             if (_off_prepare_done_timer) {
6968                 ecore_timer_del (_off_prepare_done_timer);
6969                 _off_prepare_done_timer = NULL;
6970             }
6971             _off_prepare_done_timer = ecore_timer_add (1.0, off_prepare_done_timeout, NULL);
6972
6973             _ise_reported_geometry.valid = false;
6974             set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6975             _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6976             _updated_hide_state_geometry = true;
6977
6978             /* If the input panel is getting hidden because of hw keyboard mode while
6979                the candidate window is still opened, it is considered to be an
6980                "input panel being resized" event instead of "input panel being hidden",
6981                since the candidate window will work as an "input panel" afterwards */
6982             bool send_input_panel_hide_event = true;
6983             if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6984                 LOGD ("_candidate_state : %d", _candidate_state);
6985                 if (_candidate_state == WINDOW_STATE_SHOW) {
6986                     send_input_panel_hide_event = false;
6987                 }
6988             }
6989             if (send_input_panel_hide_event) {
6990                 _info_manager->update_input_panel_event (
6991                         ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6992             }
6993             // For now don't send WILL_HIDE signal here
6994             //_info_manager->update_input_panel_event (
6995             //    ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_HIDE);
6996             // Instead send HIDE signal
6997             vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_HIDE);
6998         } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE) {
6999             /* WMSYNC, #10 Register size hints for candidate window and set conformant geometry */
7000             // PRE_ROTATE_DONE Ack to WM
7001             _candidate_angle = ev->data.l[1];
7002             _ise_angle = ev->data.l[1];
7003             LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE : %d", _candidate_angle);
7004
7005             if (_candidate_angle == 90 || _candidate_angle == 270) {
7006                 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
7007             } else {
7008                 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
7009             }
7010             if (_ise_state == WINDOW_STATE_SHOW) {
7011                 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7012                 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7013             }
7014             ui_settle_candidate_window ();
7015             ui_candidate_window_rotate (_candidate_angle);
7016             Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
7017             LOGD ("ecore_x_e_window_rotation_change_prepare_done_send (%d)", _candidate_angle);
7018             ecore_x_e_window_rotation_change_prepare_done_send (root_window,
7019                     _control_window, _candidate_angle);
7020         } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7021             int ise_angle = (int)ev->data.l[1];
7022             LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST for ISE WINDOW : ISE angle : %d, Candidate angle : %d", ise_angle, _candidate_angle);
7023             _candidate_angle = ise_angle;
7024             _ise_angle = ise_angle;
7025             if (_ise_state == WINDOW_STATE_SHOW) {
7026                 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7027                 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7028                 ui_settle_candidate_window ();
7029             }
7030         }
7031     } else if (ev->win == elm_win_xwindow_get (_candidate_window)) {
7032         if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST || ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE) {
7033             /* WMSYNC, #11 Actual rotate the candidate window */
7034             if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7035                 _candidate_angle = (int)ev->data.l[1];
7036                 ui_candidate_window_rotate (_candidate_angle);
7037                 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST : %d", _candidate_angle);
7038             } else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE &&
7039                 _ise_state != WINDOW_STATE_SHOW) {
7040                 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_TRUE);
7041                 _candidate_angle = (int)ev->data.l[0];
7042                 if (_candidate_angle == 90 || _candidate_angle == 270) {
7043                     evas_object_resize (_candidate_window, _candidate_land_width, _candidate_land_height_min);
7044                 } else {
7045                     evas_object_resize (_candidate_window, _candidate_port_width, _candidate_port_height_min);
7046                 }
7047                 ui_candidate_window_rotate (_candidate_angle);
7048                 ui_settle_candidate_window ();
7049                 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_FALSE);
7050                 LOGD ("ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE : %d", _candidate_angle);
7051             }
7052             SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " : ANGLE (" << _candidate_angle << ")\n";
7053         }
7054     }
7055 #endif
7056
7057     /* Screen reader feature */
7058     if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL) {
7059         static int last_pos_x = -10000;
7060         static int last_pos_y = -10000;
7061
7062         if (_candidate_window) {
7063             if ((unsigned int)ev->data.l[0] == elm_win_xwindow_get (_candidate_window)) {
7064                 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE) {
7065                     // 1 finger double tap
7066                     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "    1 finger double tap focus index = " << _candidate_tts_focus_index << "\n";
7067                     ui_mouse_click (_candidate_tts_focus_index);
7068                 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ) {
7069                     // 1 finger tap
7070                     // 1 finger touch & move
7071                     last_pos_x = ev->data.l[2];
7072                     last_pos_y = ev->data.l[3];
7073                     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "    1 finger touch & move (" << last_pos_x << ", " << last_pos_y << ")\n";
7074                     ui_mouse_over (last_pos_x, last_pos_y);
7075                 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT ||
7076                            (unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV) {
7077                     if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT) {
7078                         // flick right
7079                         SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "    1 finger flick right\n";
7080                         if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_display_number - 1))
7081                             _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : 0;
7082                         else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7083                             _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7084                         else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7085                             _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7086                         else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7087                             _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? 0 : _candidate_row_items[0];
7088                         else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7089                             _candidate_tts_focus_index = _candidate_row_items[0];
7090                         else if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < (g_isf_candidate_table.get_current_page_size () - 1))
7091                             _candidate_tts_focus_index++;
7092                         else if (_candidate_tts_focus_index == (g_isf_candidate_table.get_current_page_size () - 1))
7093                             _candidate_tts_focus_index = 0;
7094                     } else {
7095                         // flick left
7096                         SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "    1 finger flick left\n";
7097                         if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == 0)
7098                             _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : _candidate_display_number - 1;
7099                         else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7100                             _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7101                         else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7102                             _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7103                         else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7104                             _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7105                         else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7106                             _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7107                         else if (_candidate_tts_focus_index > 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ())
7108                             _candidate_tts_focus_index--;
7109                         else if (_candidate_tts_focus_index == 0)
7110                             _candidate_tts_focus_index = g_isf_candidate_table.get_current_page_size () - 1;
7111                     }
7112
7113                     int x = 0, y = 0, w = 0, h = 0;
7114                     _wait_stop_event = false;
7115                     if (candidate_expanded) {
7116                         int total = 0;
7117                         int cursor_line = 0;
7118                         for (unsigned int i = 0; i < _candidate_row_items.size (); i++) {
7119                             total += _candidate_row_items [i];
7120                             if (total > (int)_candidate_display_number && _candidate_tts_focus_index >= total)
7121                                 cursor_line++;
7122                         }
7123
7124                         elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
7125
7126                         int line_h   = _item_min_height + _v_padding;
7127                         int cursor_y = cursor_line * line_h;
7128                         if (cursor_y < y) {
7129                             elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
7130                             _wait_stop_event = true;
7131                         } else if (cursor_y >= y + h) {
7132                             elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
7133                             _wait_stop_event = true;
7134                         }
7135                     }
7136
7137                     x = y = w = h = 0;
7138                     String strTts = String ("");
7139                     if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
7140                         strTts = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (_candidate_tts_focus_index));
7141                         if (_candidate_0 [_candidate_tts_focus_index])
7142                             evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
7143                     } else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX) {
7144                         strTts = String (_("more button"));
7145                         evas_object_geometry_get (_more_btn, &x, &y, &w, &h);
7146                     } else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX) {
7147                         strTts = String (_("close button"));
7148                         evas_object_geometry_get (_close_btn, &x, &y, &w, &h);
7149                     } else {
7150                         ui_tts_focus_rect_hide ();
7151                     }
7152
7153                     if (w > 0 && h > 0) {
7154                         if (!_wait_stop_event)
7155                             ui_tts_focus_rect_show (x, y, w, h);
7156                         else
7157                             ui_tts_focus_rect_hide ();
7158                     }
7159                 }
7160             }
7161         }
7162     }
7163
7164     return ECORE_CALLBACK_RENEW;
7165 }
7166 #endif
7167
7168 Eina_Bool check_focus_out_by_popup_win ()
7169 {
7170     Eina_Bool ret = EINA_FALSE;
7171 #ifdef HAVE_ECOREX
7172     Ecore_X_Window focus_win = ecore_x_window_focus_get ();
7173     Ecore_X_Window_Type win_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
7174
7175     if (!ecore_x_netwm_window_type_get (focus_win, &win_type))
7176         return EINA_FALSE;
7177
7178     LOGD ("win type : %d", win_type);
7179
7180     if (win_type == ECORE_X_WINDOW_TYPE_POPUP_MENU ||
7181         win_type == ECORE_X_WINDOW_TYPE_NOTIFICATION) {
7182         ret = EINA_TRUE;
7183     }
7184 #endif
7185     return ret;
7186 }
7187
7188 #ifdef HAVE_ECOREX
7189 /**
7190  * @brief Callback function for focus out event of application window
7191  *
7192  * @param data Data to pass when it is called.
7193  *
7194  * @return ECORE_CALLBACK_RENEW
7195  */
7196 static Eina_Bool x_event_window_focus_out_cb (void *data, int ev_type, void *event)
7197 {
7198     Ecore_X_Event_Window_Focus_Out *e = (Ecore_X_Event_Window_Focus_Out*)event;
7199
7200     if (e && e->win == _app_window) {
7201         if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7202             if (check_focus_out_by_popup_win ())
7203                 return ECORE_CALLBACK_RENEW;
7204
7205 #if ENABLE_MULTIWINDOW_SUPPORT
7206             unsigned int layout = 0;
7207             LOGD ("Application window focus OUT!");
7208             delete_ise_hide_timer ();
7209
7210             // Check multi window mode
7211             if (ecore_x_window_prop_card32_get (efl_get_app_window (), ECORE_X_ATOM_E_WINDOW_DESKTOP_LAYOUT, &layout, 1) != -1) {
7212                 if (layout == 0 || layout == 1) {
7213                     // Split mode
7214                     LOGD ("Multi window mode. start timer to hide IME");
7215
7216                     // Use timer not to hide and show IME again in focus-out and focus-in event between applications
7217                     _ise_hide_timer = ecore_timer_add (ISF_ISE_HIDE_DELAY, ise_hide_timeout, NULL);
7218                 }
7219             }
7220
7221             if (!_ise_hide_timer) {
7222                 LOGD ("Panel hides ISE");
7223                 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7224                 slot_hide_ise ();
7225                 ui_candidate_hide (true, false, false);
7226             }
7227 #else
7228             LOGD ("Application window focus OUT! Panel hides ISE");
7229             _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7230             slot_hide_ise ();
7231             ui_candidate_hide (true, false, false);
7232 #endif
7233         }
7234     }
7235
7236     return ECORE_CALLBACK_RENEW;
7237 }
7238 #endif
7239
7240 static void restore_config ()
7241 {
7242     if (!_config.null ()) {
7243         String uuid = _initial_ise_uuid;
7244
7245         String global_uuid = scim_global_config_read (String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String(""));
7246         if (global_uuid.length () > 0) uuid = global_uuid;
7247
7248         String default_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
7249         if (default_uuid.length() > 0) uuid = default_uuid;
7250
7251         if (global_uuid.length() == 0) {
7252             scim_global_config_write (String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), uuid);
7253         }
7254         if (default_uuid.length() == 0) {
7255             _config->write (SCIM_CONFIG_DEFAULT_HELPER_ISE, uuid);
7256         }
7257
7258         scim_global_config_flush ();
7259         _config->flush();
7260
7261         scim_global_config_reload ();
7262         _config->reload ();
7263     }
7264 }
7265
7266 /**
7267  * @brief : Launches default soft keyboard for performance enhancement (It's not mandatory)
7268  */
7269 static void launch_default_soft_keyboard (keynode_t *key, void* data)
7270 {
7271     SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7272
7273     String helper_uuid;
7274     if (!_config.null()) {
7275         helper_uuid = _config->read(SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
7276     }
7277     if (helper_uuid.length () > 0) {
7278         /* Start default ISE */
7279         change_keyboard_mode (TOOLBAR_HELPER_MODE);
7280     } else {
7281         if (!_launch_ise_on_request) {
7282             set_temporary_ise (_initial_ise_uuid);
7283             restore_config();
7284         }
7285     }
7286 }
7287
7288 static String sanitize_string (const char *str, int maxlen = 32)
7289 {
7290     String ret;
7291     static char acceptables[] =
7292         "abcdefghijklmnopqrstuvwxyz"
7293         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7294         "1234567890_-.@:";
7295
7296     char *newstr = NULL;
7297     if (maxlen > 0) {
7298         newstr = new char[maxlen + 1];
7299     }
7300     int len = 0;
7301     if (newstr) {
7302         memset (newstr, 0x00, sizeof (char) * (maxlen + 1));
7303
7304         if (str) {
7305             while (len < maxlen && str[len] != '\0' && strchr (acceptables, str[len]) != NULL) {
7306                 newstr[len] = str[len];
7307                 len++;
7308             }
7309             ret = newstr;
7310         }
7311         delete [] newstr;
7312     }
7313     return ret;
7314 }
7315
7316 static Eina_Bool monitor_user_data_path_timer(void *data)
7317 {
7318     const char *path = static_cast<const char*>(data);
7319     bool user_data_path_exists = g_file_test (path, G_FILE_TEST_EXISTS);
7320     bool user_data_path_is_dir = g_file_test (path, G_FILE_TEST_IS_DIR);
7321     if (user_data_path_exists && user_data_path_is_dir) {
7322         LOGW ("'%s' exists : %d, is_dir : %d", path,
7323              (user_data_path_exists ? 1 : 0), (user_data_path_is_dir ? 1 : 0));
7324
7325         scim_global_config_reload (true);
7326
7327         load_config ();
7328
7329         /* Read all ime info from db */
7330         _ime_info.clear ();
7331         isf_pkg_select_all_ime_info_db (_ime_info);
7332
7333         bool launch = true;
7334         if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
7335             launch = false;
7336         }
7337         if (_launch_ise_on_request) {
7338             launch = false;
7339         }
7340         String default_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
7341
7342         set_active_ise (default_ise_uuid, launch);
7343
7344         restore_config ();
7345
7346         g_monitor_user_data_path_timer = NULL;
7347         return ECORE_CALLBACK_CANCEL;
7348     }
7349
7350     return ECORE_CALLBACK_RENEW;
7351 }
7352
7353 int main (int argc, char *argv [])
7354 {
7355     struct tms    tiks_buf;
7356     _clock_start = times (&tiks_buf);
7357
7358     int           i;
7359     int           ret             = 0;
7360
7361     bool          daemon          = false;
7362     bool          should_resident = true;
7363
7364     int           new_argc        = 0;
7365     char        **new_argv        = new char * [40];
7366     int           display_name_c  = 0;
7367     ConfigModule *config_module   = NULL;
7368     String        config_name     = String ("simple");
7369     String        display_name    = String ();
7370     char          buf[256]        = {0};
7371
7372     String        user_data_path  = String ();
7373     bool          user_data_path_exists = false;
7374     bool          user_data_path_is_dir = false;
7375
7376 #ifdef HAVE_ECOREX
7377     Ecore_Event_Handler *xclient_message_handler  = NULL;
7378     Ecore_Event_Handler *xwindow_property_handler = NULL;
7379     Ecore_Event_Handler *xwindow_focus_out_handler = NULL;
7380 #endif
7381
7382     check_time ("\nStarting ISF Panel EFL...... ");
7383     ISF_SAVE_LOG ("Starting ISF Panel EFL......");
7384
7385     DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
7386     DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
7387
7388     /* Parse command options */
7389     i = 0;
7390     while (i < argc) {
7391         if (++i >= argc)
7392             break;
7393
7394         if (String ("-c") == argv [i] || String ("--config") == argv [i]) {
7395             if (++i >= argc) {
7396                 std::cerr << "no argument for option " << argv [i-1] << "\n";
7397                 ret = -1;
7398                 goto cleanup;
7399             }
7400             config_name = argv [i];
7401             continue;
7402         }
7403
7404         if (String ("-h") == argv [i] || String ("--help") == argv [i]) {
7405             std::cout << "Usage: " << argv [0] << " [option]...\n\n"
7406                  << "The options are: \n"
7407                  << "  --display DISPLAY    Run on display DISPLAY.\n"
7408                  << "  -c, --config NAME    Uses specified Config module.\n"
7409                  << "  -d, --daemon         Run " << argv [0] << " as a daemon.\n"
7410                  << "  -ns, --no-stay       Quit if no connected client.\n"
7411 #if ENABLE_DEBUG
7412                  << "  -v, --verbose LEVEL  Enable debug info, to specific LEVEL.\n"
7413                  << "  -o, --output FILE    Output debug information into FILE.\n"
7414 #endif
7415                  << "  -h, --help           Show this help message.\n";
7416             delete []new_argv;
7417             return 0;
7418         }
7419
7420         if (String ("-d") == argv [i] || String ("--daemon") == argv [i]) {
7421             daemon = true;
7422             continue;
7423         }
7424
7425         if (String ("-ns") == argv [i] || String ("--no-stay") == argv [i]) {
7426             should_resident = false;
7427             continue;
7428         }
7429
7430         if (String ("-v") == argv [i] || String ("--verbose") == argv [i]) {
7431             if (++i >= argc) {
7432                 std::cerr << "no argument for option " << argv [i-1] << "\n";
7433                 ret = -1;
7434                 goto cleanup;
7435             }
7436             DebugOutput::set_verbose_level (atoi (argv [i]));
7437             continue;
7438         }
7439
7440         if (String ("-o") == argv [i] || String ("--output") == argv [i]) {
7441             if (++i >= argc) {
7442                 std::cerr << "No argument for option " << argv [i-1] << "\n";
7443                 ret = -1;
7444                 goto cleanup;
7445             }
7446             DebugOutput::set_output (sanitize_string (argv [i]));
7447             continue;
7448         }
7449
7450         if (String ("--display") == argv [i]) {
7451             if (++i >= argc) {
7452                 std::cerr << "No argument for option " << argv [i-1] << "\n";
7453                 ret = -1;
7454                 goto cleanup;
7455             }
7456             display_name = sanitize_string (argv [i]);
7457             continue;
7458         }
7459
7460         if (String ("--") == argv [i])
7461             break;
7462
7463         std::cerr << "Invalid command line option: " << argv [i] << "\n";
7464         delete []new_argv;
7465         return 0;
7466     } /* End of command line parsing. */
7467
7468     if (new_argv) {
7469         new_argv [new_argc ++] = argv [0];
7470
7471         /* Store the rest argvs into new_argv. */
7472         for (++i; i < argc && new_argc < 37; ++i) {
7473             new_argv [new_argc ++] = argv [i];
7474         }
7475
7476         /* Make up DISPLAY env. */
7477         if (display_name.length ()) {
7478             new_argv [new_argc ++] = const_cast <char*> ("--display");
7479             display_name_c = new_argc;
7480             new_argv [new_argc ++] = strdup (display_name.c_str ());
7481
7482             setenv ("DISPLAY", display_name.c_str (), 1);
7483         }
7484
7485         new_argv [new_argc] = 0;
7486     }
7487
7488     if (!config_name.length ()) {
7489         std::cerr << "No Config module is available!\n";
7490         ret = -1;
7491         goto cleanup;
7492     }
7493
7494     /* Get current display. */
7495     {
7496         const char *p = getenv ("DISPLAY");
7497         if (p)
7498             display_name = String (p);
7499     }
7500
7501     snprintf (buf, sizeof (buf), "config_name=%s display_name=%s", config_name.c_str (), display_name.c_str ());
7502     check_time (buf);
7503
7504     if (daemon) {
7505         check_time ("ISF Panel EFL run as daemon");
7506         scim_daemon ();
7507     }
7508
7509     /* No loading default theme to reduce heap memory */
7510     setenv ("ELM_THEME", "", 1);
7511
7512 #if ISF_BUILD_CANDIDATE_UI
7513     elm_init (argc, argv);
7514 #else
7515     ecore_init ();
7516     ecore_app_args_set(argc, (const char **)argv);
7517 #endif /* CANDIDATE */
7518
7519     check_time ("elm_init");
7520
7521     flush_memory ();
7522
7523 #if ISF_BUILD_CANDIDATE_UI
7524     elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
7525 #endif /* CANDIDATE */
7526
7527     if (config_name != "dummy") {
7528         /* Load config module */
7529         config_module = new ConfigModule (config_name);
7530
7531         if (!config_module || !config_module->valid ()) {
7532             std::cerr << "Can not load " << config_name << " Config module.\n";
7533             ret = -1;
7534             goto cleanup;
7535         }
7536     } else {
7537         _config = new DummyConfig ();
7538     }
7539
7540     /* Create config instance */
7541     if (_config.null () && config_module && config_module->valid ())
7542         _config = config_module->create_config ();
7543     if (_config.null ()) {
7544         std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
7545         ret = -1;
7546         goto cleanup;
7547     }
7548     ConfigBase::set (_config);
7549     check_time ("create config instance");
7550
7551     set_cpu_boosting();
7552
7553     try {
7554         if (!initialize_panel_agent (_config, display_name, should_resident)) {
7555             check_time ("Failed to initialize Panel Agent!");
7556             std::cerr << "Failed to initialize Panel Agent!\n";
7557             LOGE ("Failed to initialize Panel Agent!");
7558             ret = -1;
7559             goto cleanup;
7560         }
7561     } catch (scim::Exception & e) {
7562         std::cerr << e.what () << "\n";
7563         LOGD("");
7564         ret = -1;
7565         goto cleanup;
7566     }
7567     check_time ("initialize_panel_agent");
7568
7569 #if ISF_BUILD_CANDIDATE_UI
7570     /* Initialize global variables and pointers for candidate items and etc. */
7571     for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; i++) {
7572         _candidate_0 [i]     = NULL;
7573         _seperate_0 [i]      = NULL;
7574         _seperate_items [i]  = NULL;
7575         _line_0 [i]          = NULL;
7576         _line_items [i]      = NULL;
7577         _candidate_text [i]  = NULL;
7578         _candidate_image [i] = NULL;
7579         _candidate_pop_image [i] = NULL;
7580     }
7581 #endif /* CANDIDATE */
7582
7583     /* Connect the configuration reload signal. */
7584     _config_connection = _config->signal_connect_reload (slot (config_reload_cb));
7585
7586 #ifdef HAVE_ECOREX
7587     if (!efl_create_control_window ()) {
7588         LOGW ("Failed to create control window");
7589         goto cleanup;
7590     }
7591 #endif
7592
7593 #if ISF_BUILD_CANDIDATE_UI
7594     efl_get_screen_resolution (_screen_width, _screen_height);
7595
7596     _width_rate       = (float)(_screen_width / 720.0);
7597     _height_rate      = (float)(_screen_height / 1280.0);
7598     _blank_width      = (int)(_blank_width * _width_rate);
7599     _item_min_width   = (int)(_item_min_width * _width_rate);
7600     _item_min_height  = (int)(_item_min_height * _height_rate);
7601     _candidate_width  = (int)(_candidate_port_width * _width_rate);
7602     _candidate_height = (int)(_candidate_port_height_min * _height_rate);
7603     _indicator_height = (int)(_indicator_height * _height_rate);
7604
7605     _aux_font_size       = (int)(_aux_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7606     _candidate_font_size = (int)(_candidate_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7607 #endif /* CANDIDATE */
7608
7609     /* Load ISF configuration */
7610     user_data_path = scim_get_user_data_dir ();
7611     user_data_path_exists = g_file_test (user_data_path.c_str(), G_FILE_TEST_EXISTS);
7612     user_data_path_is_dir = g_file_test (user_data_path.c_str(), G_FILE_TEST_IS_DIR);
7613     _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
7614     if (vconf_set_bool (VCONFKEY_ISF_IME_LAUNCH_ON_DEMAND, _launch_ise_on_request) != 0)
7615         LOGW ("Failed to set vconf key");
7616
7617     if (user_data_path_exists && user_data_path_is_dir) {
7618         load_config ();
7619     } else {
7620         LOGW ("'%s' exists : %d, is_dir : %d", user_data_path.c_str (),
7621             (user_data_path_exists ? 1 : 0), (user_data_path_is_dir ? 1 : 0));
7622         g_monitor_user_data_path_timer = ecore_timer_add (1.0, monitor_user_data_path_timer, user_data_path.c_str ());
7623     }
7624     check_time("load_config");
7625
7626 #ifdef HAVE_VCONF
7627     char *lang_str;
7628     lang_str = vconf_get_str (VCONFKEY_LANGSET);
7629     set_language_and_locale (lang_str);
7630     if (lang_str)
7631         free (lang_str);
7632
7633     /* Add callback function for input language and display language */
7634     vconf_notify_key_changed (VCONFKEY_LANGSET, display_language_changed_cb, NULL);
7635     vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
7636 #endif
7637
7638     try {
7639         /* Update ISE list */
7640         std::vector<String> list;
7641         update_ise_list (list);
7642
7643         /* Load initial ISE information */
7644         _initial_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_INITIAL_ISE_UUID), String (SCIM_COMPOSE_KEY_FACTORY_UUID));
7645
7646         /* Check if SCIM_CONFIG_DEFAULT_HELPER_ISE is available. If it's not, set it as _initial_ise_uuid.
7647            e.g., This might be necessary when the platform is upgraded from 2.3 to 2.4. */
7648         String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
7649         if (_initial_ise_uuid.length() > 0 && helper_uuid != _initial_ise_uuid) {
7650             bool match = false;
7651             for (unsigned int u = 0; u < _ime_info.size (); u++) {
7652                 if (_ime_info[u].mode == TOOLBAR_HELPER_MODE && helper_uuid == _ime_info[u].appid) {
7653                     match = true;
7654                     break;
7655                 }
7656             }
7657             if (!match) {
7658                 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), _initial_ise_uuid);
7659             }
7660         }
7661
7662         /* Request to terminate active IME */
7663         terminate_active_ise (_initial_ise_uuid);
7664
7665         _preloading_ise = !_launch_ise_on_request;
7666
7667         /* Launches default soft keyboard when all conditions are satisfied */
7668         launch_default_soft_keyboard ();
7669
7670         /* Update the name of each ISE according to display language */
7671         update_ise_locale ();
7672     } catch (scim::Exception & e) {
7673         std::cerr << e.what () << "\n";
7674     } catch (std::logic_error & e) {
7675         std::cerr << e.what () << "\n";
7676     }
7677 #ifdef HAVE_ECOREX
7678     xclient_message_handler  = ecore_event_handler_add (ECORE_X_EVENT_CLIENT_MESSAGE, x_event_client_message_cb, NULL);
7679     xwindow_property_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, x_event_window_property_cb, NULL);
7680     xwindow_focus_out_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_FOCUS_OUT, x_event_window_focus_out_cb, NULL);
7681 #endif
7682
7683 #if ENABLE_REMOTE_INPUT
7684     if (_TV) {
7685         launch_remote_input = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_REMOTE_INPUT), launch_remote_input);
7686
7687          /* Create remote input */
7688         if (launch_remote_input) {
7689              LOGD("remote input start");
7690              remote_input_impl = new Remote_Input();
7691              if (remote_input_impl) {
7692                  remote_input_impl->init(_info_manager);
7693              }
7694         }
7695     }
7696 #endif
7697
7698 #if ISF_BUILD_CANDIDATE_UI
7699     _system_scale = elm_config_scale_get ();
7700
7701     /* Set elementary scale */
7702     if (_screen_width) {
7703         _app_scale = _screen_width / 720.0;
7704         elm_config_scale_set (_app_scale);
7705         char buf[16] = {0};
7706         snprintf (buf, sizeof (buf), "%4.3f", _app_scale);
7707         setenv ("ELM_SCALE", buf, 1);
7708     }
7709 #endif /* CANDIDATE */
7710
7711     signal (SIGQUIT, signalhandler);
7712     signal (SIGTERM, signalhandler);
7713     signal (SIGINT,  signalhandler);
7714     signal (SIGHUP,  signalhandler);
7715
7716     check_time ("EFL Panel launch time");
7717
7718     if (!isf_cynara_initialize())
7719         LOGW ("Failed to initialize cynara");
7720
7721     clear_cpu_boosting();
7722
7723 #if ISF_BUILD_CANDIDATE_UI
7724     elm_run ();
7725 #else
7726     ecore_main_loop_begin ();
7727 #endif /* CANDIDATE */
7728
7729     LOGW("out of loop");
7730
7731     isf_cynara_finish();
7732
7733     _config->flush ();
7734     ret = 0;
7735
7736     if (g_monitor_user_data_path_timer) {
7737         ecore_timer_del (g_monitor_user_data_path_timer);
7738         g_monitor_user_data_path_timer = NULL;
7739     }
7740
7741 #ifdef HAVE_ECOREX
7742     if (xclient_message_handler) {
7743         ecore_event_handler_del (xclient_message_handler);
7744         xclient_message_handler = NULL;
7745     }
7746
7747     if (xwindow_property_handler) {
7748         ecore_event_handler_del (xwindow_property_handler);
7749         xwindow_property_handler = NULL;
7750     }
7751
7752     if (xwindow_focus_out_handler) {
7753         ecore_event_handler_del (xwindow_focus_out_handler);
7754         xwindow_focus_out_handler = NULL;
7755     }
7756 #endif
7757
7758 #ifdef HAVE_VCONF
7759     /* Remove callback function for input language and display language */
7760     vconf_ignore_key_changed (VCONFKEY_LANGSET, display_language_changed_cb);
7761     vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
7762 #endif
7763
7764 cleanup:
7765 #if ISF_BUILD_CANDIDATE_UI
7766     ui_destroy_candidate_window ();
7767     ui_candidate_delete_check_size_timer ();
7768     ui_candidate_delete_longpress_timer ();
7769     ui_candidate_delete_destroy_timer ();
7770 #endif /* CANDIDATE */
7771 #ifdef HAVE_PKGMGR_INFO
7772     if (pkgmgr) {
7773         package_manager_destroy (pkgmgr);
7774         pkgmgr = NULL;
7775     }
7776 #endif
7777     delete_ise_check_pid_alive_timer();
7778
7779     if (_info_manager) {
7780         try {
7781             _info_manager->stop ();
7782         } catch (scim::Exception & e) {
7783             std::cerr << "Exception is thrown from _info_manager->stop (), error is " << e.what () << "\n";
7784         }
7785         delete _info_manager;
7786     }
7787     _config_connection.disconnect ();
7788     if (!_config.null ())
7789         _config.reset ();
7790     ConfigBase::set (0);
7791
7792     if (config_module)
7793         delete config_module;
7794
7795 #if ISF_BUILD_CANDIDATE_UI
7796     elm_shutdown ();
7797 #else
7798     ecore_shutdown ();
7799 #endif /* CANDIDATE */
7800
7801     if (new_argv) {
7802         if ((display_name_c > 0) && new_argv [display_name_c]) {
7803             free (new_argv [display_name_c]);
7804         }
7805         delete []new_argv;
7806     }
7807
7808     ISF_SAVE_LOG ("ret=%d", ret);
7809     if (ret == 0) {
7810         std::cerr << "Successfully exited.\n";
7811         return 0;
7812     } else {
7813         std::cerr << "Abnormally exited.\n";
7814         return -1;
7815     }
7816 }
7817
7818 /*
7819 vi:ts=4:nowrap:expandtab
7820 */