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