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