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