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