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