2 * ISF(Input Service Framework)
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.
7 * Contact: Haifeng Deng <haifeng.deng@samsung.com>, Jihoon Kim <jihoon48.kim@samsung.com>
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)
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.
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
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
33 #include <sys/types.h>
35 #include <sys/times.h>
45 #include <tzplatform_config.h>
46 #include <system_info.h>
47 #include <cpu-boosting.h>
49 #include "scim_private.h"
51 #include "scim_stl_map.h"
52 #if ISF_BUILD_CANDIDATE_UI
53 #include <Elementary.h>
56 #include <Ecore_Wayland.h>
57 #endif /* HAVE_ECOREWL */
60 #endif /* HAVE_FEEDBACK */
61 #endif /* CANDIDATE */
64 #include <vconf-keys.h>
67 #ifdef HAVE_NOTIFICATION
68 #include <notification.h>
69 #include <notification_internal.h>
71 #ifdef HAVE_PKGMGR_INFO
72 #include <package_manager.h>
73 #include <pkgmgr-info.h>
75 #include <app_control.h>
78 #include "isf_panel_efl.h"
79 #include "isf_panel_utility.h"
80 #include "isf_query_utility.h"
82 #include "privilege_checker.h"
83 #include "remote_input.h"
84 #include "tizen_profile.h"
89 /////////////////////////////////////////////////////////////////////////////
90 // Declaration of macro.
91 /////////////////////////////////////////////////////////////////////////////
92 #define EFL_CANDIDATE_THEME1 (SCIM_DATADIR "/isf_candidate_theme1.edj")
94 #define ISF_CANDIDATE_TABLE 0
97 #define ISF_EFL_CANDIDATE_0 2
98 #define ISF_EFL_CANDIDATE_ITEMS 3
100 #define ISE_DEFAULT_HEIGHT_PORTRAIT 444
101 #define ISE_DEFAULT_HEIGHT_LANDSCAPE 316
103 #define ISF_CANDIDATE_DESTROY_DELAY 3
104 #define ISF_ISE_HIDE_DELAY 0.15
106 #define ISF_PREEDIT_BORDER 16
107 #define ISE_LAUNCH_TIMEOUT 2.0
109 #define ISF_POP_PLAY_ICON_FILE (SCIM_ICONDIR "/pop_play.png")
110 #define ISF_KEYBOARD_ICON_FILE (SCIM_ICONDIR "/noti_keyboard_connected.png")
111 #define ISF_ISE_SELECTOR_ICON_FILE "/noti_keyboard.png"
113 #define E_PROP_DEVICEMGR_INPUTWIN "DeviceMgr Input Window"
116 /////////////////////////////////////////////////////////////////////////////
117 // Declaration of external variables.
118 /////////////////////////////////////////////////////////////////////////////
119 extern MapStringVectorSizeT _groups;
120 extern std::vector<ImeInfoDB> _ime_info;
122 #if ISF_BUILD_CANDIDATE_UI
123 CommonLookupTable g_isf_candidate_table;
126 /////////////////////////////////////////////////////////////////////////////
127 // Declaration of internal data types.
128 /////////////////////////////////////////////////////////////////////////////
129 typedef enum _WINDOW_STATE {
130 WINDOW_STATE_HIDE = 0,
131 WINDOW_STATE_WILL_HIDE,
132 WINDOW_STATE_WILL_SHOW,
137 typedef struct NotiData
146 typedef std::vector < std::pair <String, uint32> > VectorPairStringUint32;
148 /////////////////////////////////////////////////////////////////////////////
149 // Declaration of internal functions.
150 /////////////////////////////////////////////////////////////////////////////
153 static void efl_set_transient_for_app_window (Ecore_X_Window window);
156 static int efl_get_ise_window_angle (void);
157 static void set_soft_candidate_geometry(int x, int y, int width, int height);
159 #if ISF_BUILD_CANDIDATE_UI
160 static Evas_Object *efl_create_window(const char *strWinName, const char *strEffect);
161 static int efl_get_app_window_angle(void);
164 static int efl_get_quickpanel_window_angle (void);
165 #endif /* HAVE_ECOREX */
167 static int ui_candidate_get_valid_height (void);
168 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd = true, bool will_hide = false);
169 static void ui_destroy_candidate_window (void);
170 static void ui_settle_candidate_window (void);
171 static void ui_candidate_show (bool bSetVirtualKbd = true);
172 static void ui_create_candidate_window (void);
173 static void update_table (int table_type, const LookupTable &table);
174 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info);
176 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack);
177 static void ui_tts_focus_rect_hide (void);
179 static Evas_Object *get_candidate (const String& str, Evas_Object *parent, int *total_width, uint32 ForeGround, uint32 BackGround, bool HighLight, bool SetBack, int item_num, int item);
180 static bool tokenize_tag (const String& str, struct image *image_data);
181 #endif /* CANDIDATE */
183 static void launch_default_soft_keyboard (keynode_t *key = NULL, void* data = NULL);
185 /* PanelAgent related functions */
186 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident);
188 static void slot_focus_in (void);
189 static void slot_focus_out (void);
190 static void slot_expand_candidate (void);
191 static void slot_contract_candidate (void);
192 static void slot_set_candidate_style (int portrait_line, int mode);
193 static void slot_update_input_context (int type, int value);
194 static void slot_update_ise_geometry (int x, int y, int width, int height);
195 static void slot_update_spot_location (int x, int y, int top_y);
196 static void slot_update_factory_info (const PanelFactoryInfo &info);
197 #if ISF_BUILD_CANDIDATE_UI
198 static void slot_show_preedit_string (void);
199 static void slot_show_aux_string (void);
201 static void slot_show_candidate_table (void);
202 static void slot_hide_preedit_string (void);
203 static void slot_hide_aux_string (void);
204 static void slot_hide_candidate_table (void);
205 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret);
206 static void slot_update_preedit_caret (int caret);
207 static void slot_update_aux_string (const String &str, const AttributeList &attrs);
208 static void slot_update_candidate_table (const LookupTable &table);
209 static void slot_select_candidate (int index);
210 static void slot_set_active_ise (const String &uuid, bool changeDefault);
211 static bool slot_get_ise_list (std::vector<String> &list);
212 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info);
213 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option);
214 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled);
215 static void slot_show_helper_ise_list (void);
216 static void slot_show_helper_ise_selector (void);
217 static bool slot_is_helper_ise_enabled (String appid, int &enabled);
218 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name);
219 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list);
220 static void slot_get_language_list (std::vector<String> &name);
221 static void slot_get_all_language (std::vector<String> &lang);
222 static void slot_get_ise_language (char *name, std::vector<String> &list);
223 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info);
224 static void slot_get_candidate_geometry (struct rectinfo &info);
225 static void slot_get_input_panel_geometry (struct rectinfo &info);
226 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info);
227 static bool slot_check_privilege_by_sockfd (int client_id, String privilege);
228 static void slot_set_keyboard_ise (const String &uuid);
229 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid);
230 static void slot_accept_connection (int fd);
231 static void slot_close_connection (int fd);
232 static void slot_exit (void);
234 static void slot_register_helper (int id, const HelperInfo& info);
235 static void slot_register_helper_properties (int id, const PropertyList &props);
236 static void slot_show_ise (void);
237 static void slot_hide_ise (void);
239 static void slot_will_hide_ack (void);
240 static void slot_candidate_will_hide_ack (void);
242 static void slot_set_keyboard_mode (int mode);
243 static void slot_get_ise_state (int &state);
244 static void slot_start_default_ise (void);
245 static void slot_stop_default_ise (bool is_exist);
246 static void slot_run_helper (const String &uuid, const String &config, const String &display);
247 static bool slot_launch_option_application (String ime_appid);
248 static bool slot_get_ise_setting_appid (String ime_appid, String &ime_setting_appid);
249 static void slot_set_preloading_ise (bool preloading);
251 #if ENABLE_REMOTE_INPUT
252 static void slot_send_remote_input_message (const String &msg, bool len);
253 static void slot_recv_remote_surrounding_text (int cursor, const String &text);
257 static Eina_Bool efl_create_control_window (void);
258 static Ecore_X_Window efl_get_app_window (void);
259 static Ecore_X_Window efl_get_quickpanel_window (void);
260 static Ecore_X_Window efl_get_global_navigation_window (void);
263 static void change_keyboard_mode (TOOLBAR_MODE_T mode);
264 static unsigned int get_ise_index (const String uuid);
265 static bool set_active_ise (const String &uuid, bool launch_ise);
266 static bool update_ise_list (std::vector<String> &list);
267 static void update_ise_locale (const char *lang = NULL);
268 #ifdef HAVE_NOTIFICATION
269 static void delete_notification (NotificationData *noti_data);
270 static void create_notification (NotificationData *noti_data);
271 static void show_ime_selector_notification (void);
273 static void set_language_and_locale (const char *lang_str);
274 static bool app_control_launch (const char *app_id);
275 static void terminate_active_ise (const String uuid);
276 static void set_cpu_boosting (void);
277 static void clear_cpu_boosting (void);
279 /////////////////////////////////////////////////////////////////////////////
280 // Declaration of internal variables.
281 /////////////////////////////////////////////////////////////////////////////
282 #if ISF_BUILD_CANDIDATE_UI
283 static Evas_Object *_candidate_window = 0;
284 static Evas_Object *_candidate_area_1 = 0;
285 static Evas_Object *_candidate_area_2 = 0;
286 static Evas_Object *_candidate_bg = 0;
287 static Evas_Object *_candidate_0_scroll = 0;
288 static Evas_Object *_candidate_scroll = 0;
289 static Evas_Object *_scroller_bg = 0;
290 static Evas_Object *_candidate_0_table = 0;
291 static Evas_Object *_candidate_table = 0;
292 static Evas_Object *_candidate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
293 static Evas_Object *_candidate_text [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
294 static Evas_Object *_candidate_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
295 static Evas_Object *_candidate_pop_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
296 static Evas_Object *_seperate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
297 static Evas_Object *_seperate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
298 static Evas_Object *_line_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
299 static Evas_Object *_line_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
300 static Evas_Object *_more_btn = 0;
301 static Evas_Object *_close_btn = 0;
302 static bool _candidate_show_requested = false;
303 #endif /* CANDIDATE */
304 static bool _updated_hide_state_geometry = false;
305 #if ISF_BUILD_CANDIDATE_UI
306 static int _candidate_x = 0;
307 static int _candidate_y = 0;
308 static int _candidate_width = 0;
309 static int _candidate_height = 0;
310 static int _soft_candidate_width = 0;
311 static int _soft_candidate_height = 0;
312 static int _candidate_valid_height = 0;
314 static bool _candidate_area_1_visible = false;
315 static bool _candidate_area_2_visible = false;
316 static bool _aux_area_visible = false;
317 #endif /* CANDIDATE */
319 static ISF_CANDIDATE_MODE_T _candidate_mode = SOFT_CANDIDATE_WINDOW;
320 static ISF_CANDIDATE_PORTRAIT_LINE_T _candidate_port_line = ONE_LINE_CANDIDATE;
322 #if ISF_BUILD_CANDIDATE_UI
323 static int _candidate_port_width = 480;
324 static int _candidate_port_height_min = 76;
325 static int _candidate_port_height_min_2 = 150;
326 static int _candidate_port_height_max = 286;
327 static int _candidate_port_height_max_2 = 350;
328 static int _candidate_land_width = 784;
329 static int _candidate_land_height_min = 84;
330 static int _candidate_land_height_min_2 = 168;
331 static int _candidate_land_height_max = 150;
332 static int _candidate_land_height_max_2 = 214;
333 static int _candidate_area_1_pos [2] = {0, 2};
334 static int _more_btn_pos [4] = {369, 11, 689, 11};
335 static int _close_btn_pos [4] = {362, 211, 682, 75};
336 static int _more_btn_width = 80;
337 static int _more_btn_height = 64;
339 static int _h_padding = 4;
340 static int _v_padding = 2;
341 static int _item_min_width = 99;
342 static int _item_min_height = 82;
344 static int _candidate_scroll_0_width_min = 350;
345 static int _candidate_scroll_0_width_max = 670;
347 static int _candidate_scroll_width = 453;
348 static int _candidate_scroll_width_min = 453;
349 static int _candidate_scroll_width_max = 663;
350 static int _candidate_scroll_height_min = 124;
351 static int _candidate_scroll_height_max = 190;
353 const int MORE_BUTTON_INDEX = -1;
354 const int CLOSE_BUTTON_INDEX = -2;
355 static uint32 _candidate_display_number = 0;
356 static std::vector<uint32> _candidate_row_items;
357 static Evas_Object *_tts_focus_rect = 0;
358 static bool _wait_stop_event = false;
360 static Evas_Object *_preedit_window = 0;
361 static Evas_Object *_preedit_text = 0;
362 static int _preedit_width = 100;
363 static int _preedit_height = 54;
365 static Evas_Object *_aux_area = 0;
366 static Evas_Object *_aux_line = 0;
367 static Evas_Object *_aux_table = 0;
368 static int _aux_height = 0;
369 static int _aux_port_width = 444;
370 static int _aux_land_width = 764;
371 static std::vector<Evas_Object *> _aux_items;
372 static std::vector<Evas_Object *> _aux_seperates;
374 static Evas_Object *_tmp_preedit_text = 0;
375 static Evas_Object *_tmp_aux_text = 0;
376 static Evas_Object *_tmp_candidate_text = 0;
378 static int _spot_location_x = -1;
379 static int _spot_location_y = -1;
380 static int _spot_location_top_y = -1;
381 static int _candidate_angle = 0;
382 static int _ise_width = 0;
383 static int _ise_height = 0;
384 #endif /* CANDIDATE */
386 static int _ise_angle = -1;
387 static int _ise_x = 0;
388 static int _ise_y = 0;
389 static WINDOW_STATE _ise_state = WINDOW_STATE_HIDE;
390 static WINDOW_STATE _candidate_state = WINDOW_STATE_HIDE;
392 #if ISF_BUILD_CANDIDATE_UI
393 static int _indicator_height = 0;//24;
394 static int _screen_width = 720;
395 static int _screen_height = 1280;
396 static float _width_rate = 1.0;
397 static float _height_rate = 1.0;
398 static int _blank_width = 30;
400 static String _candidate_name = String ("candidate");
401 static String _candidate_edje_file = String (EFL_CANDIDATE_THEME1);
403 static String _candidate_font_name = String ("Tizen");
404 static int _candidate_font_size = 38;
405 static int _aux_font_size = 38;
406 static int _click_object = 0;
407 static int _click_down_pos [2] = {0, 0};
408 static int _click_up_pos [2] = {0, 0};
409 static bool _is_click = true;
410 #endif /* CANDIDATE */
411 static String _initial_ise_uuid = String ("");
412 static String _locale_string = String ("");
413 static ConfigPointer _config;
414 static Connection _config_connection;
416 static InfoManager *_info_manager = 0;
418 static clock_t _clock_start;
420 #if ISF_BUILD_CANDIDATE_UI
421 static Ecore_Timer *_check_size_timer = NULL;
422 static Ecore_Timer *_longpress_timer = NULL;
423 static Ecore_Timer *_destroy_timer = NULL;
424 #endif /* CANDIDATE */
425 #if ISF_BUILD_CANDIDATE_UI
426 static Ecore_Timer *_candidate_hide_timer = NULL;
427 #endif /* CANDIDATE */
428 static Ecore_Timer *_ise_hide_timer = NULL;
431 static Ecore_X_Window _ise_window = 0;
432 static Ecore_X_Window _app_window = 0;
433 static Ecore_X_Window _control_window = 0;
434 static Ecore_X_Window _input_win = 0;
437 #ifdef HAVE_PKGMGR_INFO
438 static package_manager_h pkgmgr = NULL;
439 static VectorPairStringUint32 g_pkgids_to_be_uninstalled;
440 static Ecore_Timer *g_release_uninstalled_ime_info_timer = NULL;
441 static String g_stopped_helper_pkgid = "";
442 static Ecore_Timer *g_start_default_helper_timer = NULL;
443 static VectorPairStringUint32 g_pkgids_to_be_updated_and_installed;
444 static String g_updated_helper_pkgid = "";
447 static bool _launch_ise_on_request = false;
448 static bool _auto_destroy_ise = false;
449 static bool _soft_keyboard_launched = false;
450 static bool _focus_in = false;
451 static bool _enable_auto_restart = true;
452 static bool _preloading_ise = true;
454 #if ISF_BUILD_CANDIDATE_UI
455 static bool candidate_expanded = false;
456 static int _candidate_image_count = 0;
457 static int _candidate_text_count = 0;
458 static int _candidate_pop_image_count = 0;
459 static int candidate_image_height = 38;
460 static int candidate_play_image_width_height = 19;
462 static const int CANDIDATE_TEXT_OFFSET = 2;
464 static double _app_scale = 1.0;
465 static double _system_scale = 1.0;
466 #endif /* CANDIDATE */
468 #ifdef HAVE_NOTIFICATION
469 static NotificationData hwkbd_module_noti = {"Input detected from hardware keyboard", "Tap to use virtual keyboard", ISF_KEYBOARD_ICON_FILE, "", 0};
470 static NotificationData ise_selector_module_noti = {"Select input method", "", "", "", 0};
473 #if ISF_BUILD_CANDIDATE_UI
476 static bool feedback_initialized = false;
478 #endif /* CANDIDATE */
480 #if ENABLE_REMOTE_INPUT
481 static Remote_Input* remote_input_impl = NULL;
482 static bool launch_remote_input = false;
485 #if ISF_BUILD_CANDIDATE_UI
487 static Ecore_Event_Handler *_candidate_show_handler = NULL;
489 #endif /* CANDIDATE */
491 static String ime_selector_app = "";
492 static String ime_list_app = "";
494 static Ecore_Timer *_ise_check_pid_alive_timer = NULL;
495 static const double _ise_check_pid_alive_time = 3.0f;
496 static String _ise_check_pid_alive_uuid;
498 static Ecore_Timer *g_monitor_user_data_path_timer = NULL;
500 #if ISF_BUILD_CANDIDATE_UI
502 EMOJI_IMAGE_WIDTH = 0,
505 EMOJI_IMAGE_TAG_FLAG,
506 EMOJI_IMAGE_POP_FLAG,
513 int emoji_option[EMOJI_IMAGE_END];
517 /* This structure stores the geometry information reported by ISE */
520 bool valid; /* Whether this information is currently valid */
521 int angle; /* For which angle this information is useful */
522 struct rectinfo geometry; /* Geometry information */
525 static struct GeometryCache _ise_reported_geometry = {0, 0, {0, 0, 0, 0}};
526 static struct GeometryCache _portrait_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
527 static struct GeometryCache _landscape_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
530 static void get_input_window (void)
533 Ecore_X_Atom atom = 0;
535 if (_input_win == 0) {
536 atom = ecore_x_atom_get (E_PROP_DEVICEMGR_INPUTWIN);
537 win_ret = ecore_x_window_prop_window_get (ecore_x_window_root_first_get (), atom, &_input_win, 1);
538 if (_input_win == 0 || win_ret < 1) {
539 LOGW ("Input window is NULL!");
541 ecore_x_event_mask_set (_input_win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
547 static int pkgmgr_get_appinfo (const char *appid, pkgmgrinfo_appinfo_h *handle)
550 /* Try to get in global packages */
551 ret = pkgmgrinfo_appinfo_get_appinfo (appid, handle);
552 if (ret != PMINFO_R_OK) {
553 LOGW ("[pkgmgrinfo_appinfo_get_appinfo] appid : '%s', ret : %d, uid : %d", appid, ret, getuid ());
554 /* Try to get in user packages */
555 ret = pkgmgrinfo_appinfo_get_usr_appinfo (appid, getuid (), handle);
556 if (ret != PMINFO_R_OK)
557 LOGW ("[pkgmgrinfo_appinfo_get_usr_appinfo] appid : '%s', ret : %d", appid, ret);
563 #ifdef HAVE_NOTIFICATION
564 static void delete_notification (NotificationData *noti_data)
566 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
568 if (!_MOBILE && !_COMMON) return;
570 if (noti_data->noti_id != 0) {
571 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
572 LOGD ("deleted notification : %s", noti_data->launch_app.c_str ());
573 noti_data->noti_id = 0;
577 static void create_notification (NotificationData *noti_data)
579 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
581 notification_h notification = NULL;
584 if (!_MOBILE && !_COMMON) return;
586 if (noti_data->noti_id != 0) {
587 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
588 noti_data->noti_id = 0;
591 notification = notification_create (NOTIFICATION_TYPE_ONGOING);
592 if (notification != NULL) {
593 notification_set_pkgname (notification, "isf-panel-efl");
594 notification_set_layout (notification, NOTIFICATION_LY_ONGOING_EVENT);
595 notification_set_image (notification, NOTIFICATION_IMAGE_TYPE_ICON, noti_data->icon.c_str());
596 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_TITLE, _(noti_data->title.c_str()), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
597 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_CONTENT, _(noti_data->content.c_str ()), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
598 notification_set_display_applist (notification, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
600 app_control_h service = NULL;
601 if (app_control_create (&service) == APP_CONTROL_ERROR_NONE) {
602 app_control_set_operation (service, APP_CONTROL_OPERATION_DEFAULT);
603 app_control_set_app_id (service, noti_data->launch_app.c_str ());
605 ret = notification_set_launch_option (notification, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)service);
606 if (ret != NOTIFICATION_ERROR_NONE) {
607 LOGW ("Failed to set launch option. error code : %d", ret);
609 ret = notification_insert (notification, ¬i_data->noti_id);
610 if (ret != NOTIFICATION_ERROR_NONE) {
611 LOGW ("Failed to insert notification. error code : %d", ret);
613 app_control_destroy (service);
616 LOGW ("Failed to create appcontrol");
618 notification_free (notification);
621 LOGW ("Failed to create notification");
624 #endif /* HAVE_NOTIFICATION */
626 #if ISF_BUILD_CANDIDATE_UI
627 static bool tokenize_tag (const String& str, struct image *image_token)
629 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
630 if (str.length () <= 0) {
631 LOGW ("str is empty!!!");
635 char **tag_str = NULL;
637 tag_str = eina_str_split (str.c_str (), "\u3013", 0);
642 for (i = 0; tag_str [i]; i++) {
644 if (str.length () == strlen (tag_str[i])) {
654 image_token->path = String (tag_str[i]);
656 if (i - 1 < EMOJI_IMAGE_END)
657 image_token->emoji_option [i - 1] = atoi (tag_str[i]);
659 LOGW ("emoji option is more than EMOJI_IMAGE_END!!!");
671 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)
673 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
675 struct image image_data;
676 int object_width = 0, text_width = 0, image_width = 0, image_height = 0, max_width = 0, button_width = 0;
678 int image_get_width = 0, image_get_height = 0;
679 char image_key [10] = {0, };
680 char **splited_string = NULL;
681 char **sub_splited_string = NULL;
682 double image_rate = 0.0;
683 bool tokenize_result = false;
684 bool candidate_is_long = false;
686 Evas_Object *candidate_object_table = NULL;
687 Evas_Object *candidate_object_table_bg_rect = NULL;
688 Evas_Object *candidate_left_padding = NULL;
690 candidate_object_table = elm_table_add (parent);
692 candidate_left_padding = evas_object_rectangle_add (evas_object_evas_get (parent));
693 evas_object_size_hint_weight_set (candidate_left_padding, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
694 evas_object_size_hint_align_set (candidate_left_padding, EVAS_HINT_FILL, EVAS_HINT_FILL);
695 evas_object_size_hint_min_set (candidate_left_padding, _blank_width, 1);
696 evas_object_color_set (candidate_left_padding, 0, 0, 0, 0);
697 elm_table_pack (candidate_object_table, candidate_left_padding, 0, 0, _blank_width, 1);
698 evas_object_show (candidate_left_padding);
700 object_width += _blank_width;
701 if (item_num > 1 && item_index == 0)
702 button_width = 92 * _width_rate;
706 splited_string = eina_str_split (str.c_str (), "\uE000", 0);
707 if (splited_string) {
708 for (i = 0; splited_string [i]; i++) {
709 if (candidate_is_long)
711 sub_splited_string = eina_str_split (splited_string [i], "\uE001", 0);
712 if (sub_splited_string) {
713 for (j = 0; sub_splited_string [j]; j++) {
714 if (candidate_is_long)
716 tokenize_result = tokenize_tag (sub_splited_string [j], &image_data);
717 if (tokenize_result && _candidate_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
718 _candidate_image [_candidate_image_count] = elm_image_add (parent);
719 snprintf (image_key, sizeof (image_key), "%d", _candidate_image_count);
720 elm_image_file_set (_candidate_image [_candidate_image_count], image_data.path.c_str (), image_key);
721 elm_image_animated_set (_candidate_image [_candidate_image_count], EINA_TRUE);
722 elm_image_animated_play_set (_candidate_image [_candidate_image_count], EINA_TRUE);
723 elm_image_object_size_get (_candidate_image [_candidate_image_count], &image_get_width, &image_get_height);
724 LOGD ("image_path=%s, key=%s", image_data.path.c_str (), image_key);
726 if (image_get_height > image_get_width)
727 image_rate = ((double)candidate_image_height / (double)image_get_width);
729 image_rate = ((double)candidate_image_height / (double)image_get_height);
731 image_width = (int)((double)image_get_width * image_rate);
732 image_height = candidate_image_height;
734 if (_candidate_angle == 90 || _candidate_angle == 270)
735 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
737 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
739 if (image_width > max_width) {
740 Evas_Object *candidate_end = edje_object_add (evas_object_evas_get (parent));
741 edje_object_file_set (candidate_end, _candidate_edje_file.c_str (), _candidate_name.c_str ());
742 evas_object_show (candidate_end);
743 edje_object_part_text_set (candidate_end, "candidate", "...");
744 edje_object_scale_set (_candidate_text [_candidate_text_count], _height_rate);
746 text_width = max_width;
747 evas_object_size_hint_min_set (candidate_end, text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
748 if (HighLight || SetBack) {
749 set_highlight_color (candidate_end, ForeGround, BackGround, SetBack);
751 elm_table_pack (candidate_object_table, candidate_end, object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
752 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
754 if (_candidate_image [_candidate_image_count]) {
755 evas_object_del (_candidate_image [_candidate_image_count]);
756 _candidate_image [_candidate_image_count] = NULL;
758 candidate_is_long = true;
762 evas_object_resize (_candidate_image [_candidate_image_count], image_width, image_height);
763 evas_object_show (_candidate_image [_candidate_image_count]);
764 evas_object_size_hint_min_set (_candidate_image [_candidate_image_count], image_width, image_height);
766 elm_table_pack (candidate_object_table, _candidate_image [_candidate_image_count], object_width, 1, image_width, image_height);
767 object_width += image_width;
768 _candidate_image_count++;
770 if (image_data.emoji_option [EMOJI_IMAGE_POP_FLAG] == 1 && image_width > 0 && _candidate_pop_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
771 _candidate_pop_image [_candidate_pop_image_count] = elm_image_add (parent);
772 elm_image_file_set (_candidate_pop_image [_candidate_pop_image_count], ISF_POP_PLAY_ICON_FILE, image_key);
773 evas_object_resize (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
774 evas_object_show (_candidate_pop_image [_candidate_pop_image_count]);
775 evas_object_size_hint_min_set (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
777 elm_table_pack (candidate_object_table, _candidate_pop_image [_candidate_pop_image_count],
778 object_width - candidate_play_image_width_height, image_height - candidate_play_image_width_height - 2,
779 candidate_play_image_width_height, candidate_play_image_width_height);
781 _candidate_pop_image_count++;
784 } else if (strlen (sub_splited_string [j]) > 0 && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
785 _candidate_text [_candidate_text_count] = edje_object_add (evas_object_evas_get (parent));
786 edje_object_file_set (_candidate_text [_candidate_text_count], _candidate_edje_file.c_str (), _candidate_name.c_str ());
787 evas_object_show (_candidate_text [_candidate_text_count]);
788 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", sub_splited_string [j]);
789 edje_object_text_class_set (_candidate_text [_candidate_text_count], "tizen",
790 _candidate_font_name.c_str (), _candidate_font_size);
791 evas_object_text_text_set (_tmp_candidate_text, sub_splited_string [j]);
792 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &text_width, NULL);
794 if (_candidate_angle == 90 || _candidate_angle == 270)
795 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
797 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
799 if (text_width > max_width) {
800 candidate_is_long = true;
801 /* In order to avoid overlap issue, calculate show_string */
802 String show_string = String (sub_splited_string [j]);
803 int show_length = text_width;
804 while (show_length > max_width && show_string.length () > 1) {
805 show_string = show_string.substr (0, show_string.length () - 1);
806 evas_object_text_text_set (_tmp_candidate_text, (show_string + String ("...")).c_str ());
807 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &show_length, NULL);
809 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", (show_string + String ("...")).c_str ());
810 text_width = max_width;
813 evas_object_size_hint_min_set (_candidate_text [_candidate_text_count], text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
814 if (HighLight || SetBack) {
815 set_highlight_color (_candidate_text [_candidate_text_count], ForeGround, BackGround, SetBack);
817 elm_table_pack (candidate_object_table, _candidate_text [_candidate_text_count], object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
818 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
819 _candidate_text_count++;
825 if (splited_string [0])
826 free (splited_string [0]);
828 free (splited_string);
831 if (sub_splited_string) {
832 if (sub_splited_string [0])
833 free (sub_splited_string [0]);
835 free (sub_splited_string);
838 *total_width = object_width + _blank_width;
840 candidate_object_table_bg_rect = edje_object_add (evas_object_evas_get (parent));
841 edje_object_file_set (candidate_object_table_bg_rect, _candidate_edje_file.c_str (), "candidate_object_table");
842 evas_object_size_hint_weight_set (candidate_object_table_bg_rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
843 evas_object_size_hint_align_set (candidate_object_table_bg_rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
844 evas_object_size_hint_min_set (candidate_object_table_bg_rect, *total_width, _item_min_height);
845 elm_table_pack (candidate_object_table, candidate_object_table_bg_rect, 0, 0, *total_width, _item_min_height);
846 evas_object_show (candidate_object_table_bg_rect);
848 evas_object_size_hint_align_set (candidate_object_table, EVAS_HINT_FILL, EVAS_HINT_FILL);
849 evas_object_size_hint_weight_set (candidate_object_table, EVAS_HINT_EXPAND, 0.0);
851 return candidate_object_table;
853 #endif /* CANDIDATE */
855 /////////////////////////////////////////////////////////////////////////////
856 // Implementation of internal functions.
857 /////////////////////////////////////////////////////////////////////////////
859 * @brief Print system time point for panel performance.
861 * @param strInfo The output information.
863 static void check_time (const char *strInfo)
865 gettime (_clock_start, strInfo);
866 ISF_LOG ("%s ppid=%d pid=%d\n", strInfo, getppid (), getpid ());
870 * @brief Flush memory for elm.
874 static void flush_memory (void)
876 #if ISF_BUILD_CANDIDATE_UI
877 elm_cache_all_flush ();
882 #if ISF_BUILD_CANDIDATE_UI
884 * @brief Get ISE geometry information.
885 * Returns the "expected" ISE geometry when kbd_state is ON, otherwise w/h set to 0
887 * @param info The data is used to store ISE position and size.
888 * @param kbd_state The keyboard state.
890 static struct rectinfo get_ise_geometry ()
892 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
894 struct rectinfo info = {0, 0, 0, 0};
898 Ecore_X_Window gnb_win = efl_get_global_navigation_window ();
900 ecore_x_window_size_get (gnb_win, &w, &h);
903 int win_w = _screen_width, win_h = _screen_height;
904 int angle = (_ise_angle == -1) ? efl_get_app_window_angle () : _ise_angle;
907 /* The height of global navigation bar */
910 if (angle == 90 || angle == 270) {
911 win_w = _screen_height;
912 win_h = _screen_width;
917 /* If we have geometry reported by ISE, use the geometry information */
918 if (_ise_reported_geometry.valid && _ise_reported_geometry.angle == angle) {
919 info = _ise_reported_geometry.geometry;
920 /* But still, if the current ISE is not in SHOW state, set w/h to 0 */
921 if (_ise_state != WINDOW_STATE_SHOW) {
922 info.pos_y = (win_h > win_w) ? win_h : win_w;
927 /* READ ISE's SIZE HINT HERE */
930 int pos_x, pos_y, width, height;
931 if (ecore_x_e_window_rotation_geometry_get (_ise_window, angle,
932 &pos_x, &pos_y, &width, &height)) {
936 if (angle == 90 || angle == 270) {
941 info.height = height;
944 info.pos_x = (int)info.width > win_w ? 0 : (win_w - info.width) / 2;
945 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
947 info.pos_y = (win_h > win_w) ? win_h : win_w;
951 if (_ise_state == WINDOW_STATE_SHOW) {
952 info.pos_y = win_h - info.height - gnb_height;
954 info.pos_y = (win_h > win_w) ? win_h : win_w;
960 LOGD ("angle : %d, w_angle : %d, mode : %d, Geometry : %d %d %d %d",
962 _info_manager->get_current_toolbar_mode (),
963 info.pos_x, info.pos_y, info.width, info.height);
972 // FIXME: Get the ISE's SIZE.
980 _ise_width = info.width;
981 _ise_height = info.height;
985 #endif /* CANDIDATE */
989 * @brief Set keyboard geometry for autoscroll.
990 * This includes the ISE geometry together with candidate window
992 * @param kbd_state The keyboard state.
994 static void set_keyboard_geometry_atom_info (Ecore_X_Window window, struct rectinfo ise_rect)
996 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
998 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
1001 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1002 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1003 ise_rect.width = _candidate_width;
1004 ise_rect.height = _candidate_height;
1006 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
1007 ise_rect.width = _soft_candidate_width;
1008 ise_rect.height = _soft_candidate_height;
1011 int angle = efl_get_app_window_angle ();
1012 if (angle == 90 || angle == 270)
1013 ise_rect.pos_y = _screen_width - ise_rect.height;
1015 ise_rect.pos_y = _screen_height - ise_rect.height;
1017 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1018 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1019 _candidate_valid_height = ui_candidate_get_valid_height ();
1020 if ((_candidate_height - _candidate_valid_height) > _ise_height) {
1021 _candidate_valid_height = _candidate_height;
1022 ise_rect.pos_y = ise_rect.pos_y + ise_rect.height - _candidate_height;
1023 ise_rect.height = _candidate_height;
1025 ise_rect.pos_y -= _candidate_valid_height;
1026 ise_rect.height += _candidate_valid_height;
1032 ecore_x_e_illume_keyboard_geometry_set (window, ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1033 LOGD ("KEYBOARD_GEOMETRY_SET : %d %d %d %d", ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1034 SCIM_DEBUG_MAIN (3) << " KEYBOARD_GEOMETRY x=" << ise_rect.pos_x << " y=" << ise_rect.pos_y
1035 << " width=" << ise_rect.width << " height=" << ise_rect.height << "\n";
1037 /* even the kbd_state is OFF, consider the keyboard is still ON if we have candidate opened */
1038 if (ise_rect.width == 0 && ise_rect.height == 0) {
1039 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1041 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1043 if (_ise_angle == 0 || _ise_angle == 180) {
1044 _portrait_recent_ise_geometry.valid = true;
1045 _portrait_recent_ise_geometry.geometry = ise_rect;
1048 _landscape_recent_ise_geometry.valid = true;
1049 _landscape_recent_ise_geometry.geometry = ise_rect;
1056 * @brief Get ISE index according to uuid.
1058 * @param uuid The ISE uuid.
1060 * @return The ISE index
1062 static unsigned int get_ise_index (const String uuid)
1064 unsigned int index = 0;
1065 if (uuid.length () > 0) {
1066 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1067 if (uuid == _ime_info[i].appid) {
1077 static void set_keyboard_engine (String active_uuid)
1079 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
1080 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
1081 if (active_uuid != keyboard_uuid) {
1082 _info_manager->change_factory (active_uuid);
1083 _config->write (IMENGINE_KEY, active_uuid);
1088 static void _update_ime_info(void)
1090 std::vector<String> ise_langs;
1093 isf_pkg_select_all_ime_info_db(_ime_info);
1095 /* Update _groups */
1097 for (size_t i = 0; i < _ime_info.size (); ++i) {
1098 scim_split_string_list(ise_langs, _ime_info[i].languages);
1099 for (size_t j = 0; j < ise_langs.size (); j++) {
1100 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
1101 _groups[ise_langs[j]].push_back (i);
1107 static void _initialize_ime_info (void)
1109 std::vector<ImeInfoDB>::iterator iter;
1110 VectorPairStringUint32 ime_on_off;
1111 // Store is_enabled values of each keyboard
1112 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1113 if (iter->mode == TOOLBAR_HELPER_MODE) {
1114 ime_on_off.push_back (std::make_pair (iter->appid, iter->is_enabled));
1117 // Delete the whole ime_info DB and reload
1118 isf_db_delete_ime_info ();
1119 _update_ime_info ();
1120 // Restore is_enabled value to valid keyboards
1121 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1122 if (iter->mode == TOOLBAR_HELPER_MODE) {
1123 for (VectorPairStringUint32::iterator it = ime_on_off.begin (); it != ime_on_off.end (); it++) {
1124 if (it->first.compare (iter->appid) == 0) {
1125 if (it->second != iter->is_enabled) {
1126 iter->is_enabled = it->second;
1127 isf_db_update_is_enabled_by_appid (iter->appid.c_str (), static_cast<bool>(iter->is_enabled));
1129 ime_on_off.erase (it);
1137 #ifdef HAVE_PKGMGR_INFO
1139 * @brief Insert or update ime_info data with pkgid.
1141 * @param pkgid pkgid to insert/update ime_info table.
1143 * @return 1 on successful insert, 2 on successful update, -1 if pkgid is not IME package, otherwise return 0.
1145 static int _isf_insert_ime_info_by_pkgid(const char *pkgid)
1148 pkgmgrinfo_pkginfo_h handle = NULL;
1149 int result = 0; // 0: not IME, 1: Inserted, 2: Updated (because of the same appid)
1150 uid_t uid = getuid ();
1154 LOGW ("pkgid is null.");
1158 /* Try to get in global packages */
1159 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &handle);
1160 if (ret != PMINFO_R_OK) {
1161 /* Try to get in user packages */
1162 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, uid, &handle);
1163 if (ret != PMINFO_R_OK) {
1164 LOGW ("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", pkgid, ret, getuid ());
1173 /* Try to get in user packages */
1174 ret = pkgmgrinfo_appinfo_get_usr_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result, uid);
1177 /* Try to get in global packages */
1178 ret = pkgmgrinfo_appinfo_get_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result);
1181 if (ret != PMINFO_R_OK) {
1182 LOGW ("Failed to call %s failed(%d)", user ? "pkgmgrinfo_appinfo_get_usr_list" : "pkgmgrinfo_appinfo_get_list", ret);
1189 pkgmgrinfo_pkginfo_destroy_pkginfo (handle);
1195 * @brief Timer to start initial Helper ISE if the active (selected) 3rd party keyboard is uninstalled.
1197 * @param data User data
1199 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1200 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1202 static Eina_Bool _start_default_helper_timer(void *data)
1204 std::vector<String> total_appids;
1205 std::vector<ImeInfoDB>::iterator it;
1206 VectorPairStringUint32::iterator iter;
1208 /* Let panel know that ISE is deleted... */
1209 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1210 total_appids.push_back(it->appid);
1212 if (total_appids.size() > 0)
1213 _info_manager->update_ise_list (total_appids);
1215 LOGD ("Try to start the initial helper");
1216 set_active_ise(_initial_ise_uuid, true);
1218 for (iter = g_pkgids_to_be_uninstalled.begin (); iter != g_pkgids_to_be_uninstalled.end (); iter++) {
1219 if (iter->first.compare(g_stopped_helper_pkgid) == 0) {
1220 g_pkgids_to_be_uninstalled.erase (iter);
1224 g_stopped_helper_pkgid = "";
1226 g_start_default_helper_timer = NULL;
1227 return ECORE_CALLBACK_CANCEL;
1231 * @brief Timer to release uninstalled IME related info; g_pkgids_to_be_uninstalled has appid and is_enabled.
1233 * @param data User data
1235 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1236 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1238 static Eina_Bool _release_uninstalled_pkginfo_timer(void *data)
1240 g_pkgids_to_be_uninstalled.clear ();
1241 g_release_uninstalled_ime_info_timer = NULL;
1242 return ECORE_CALLBACK_CANCEL;
1246 * @brief Called when the package is installed, uninstalled or updated, and the progress of the request to the package manager changes.
1248 * @param[in] type The type of the package to be installed, uninstalled or updated
1249 * @param[in] package The name of the package to be installed, uninstalled or updated
1250 * @param[in] event_type The type of the request to the package manager
1251 * @param[in] event_state The current state of the request to the package manager
1252 * @param[in] progress The progress for the request that is being processed by the package manager \n
1253 * The range of progress is from 0 to 100
1254 * @param[in] error The error code when the package manager failed to process the request
1255 * @param[in] user_data The user data passed from package_manager_set_event_cb()
1256 * @see package_manager_set_event_cb()
1257 * @see package_manager_unset_event_cb()
1259 INFO: Package install/update/uninstall scenario
1260 Install and Uninstall are obviously simple.
1261 Install: just INSTALL
1262 Uninstall: just UNINSTALL
1263 Update package (change the source codes in IME project and Run As again), there are four scenarios:
1266 2. UNINSTALL -> INSTALL
1267 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1268 and change Application ID in tizen-manifest.xml file and Run As.
1269 3. UPDATE -> INSTALL
1270 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1271 and change Application ID in tizen-manifest.xml file and Run As.
1272 At UPDATE event, pkgid (package parameter) is invalid...
1274 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1275 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1277 If multiple packages (including non-IME pkgs) are uninstalled and installed; Z300H UPS (ultra power saving) mode scenario.
1278 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
1280 Assuming IMEngine won't be changed through this. IMEngine might have multiple appids for one pkgid.
1281 Assuming preinstalled IME won't be changed through this.
1283 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)
1285 String current_ime_appid; // now appid is uuid.
1286 std::vector<String> appids;
1287 std::vector<String> total_appids;
1288 std::vector<ImeInfoDB>::iterator it;
1289 std::vector<String>::iterator it2;
1290 VectorPairStringUint32::iterator it3;
1293 if (!package || !type)
1296 if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
1297 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1298 LOGD ("type=%s package=%s event_type=UPDATE event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1300 ret = _isf_insert_ime_info_by_pkgid (package); // If package is not IME, -1 would be returned.
1301 if (ret == 1) { // In case the package is updated with the changed appid. In this case, there will be two IMEs
1302 ret = isf_db_select_appids_by_pkgid (package, appids);
1304 if (_ime_info.size () > 0 && _ime_info [get_ise_index (appids.front ())].is_enabled)
1305 isf_db_update_is_enabled_by_appid (appids.back ().c_str (), true);
1306 isf_db_delete_ime_info_by_appid (appids.front ().c_str ());
1309 _update_ime_info ();
1311 /* Let panel know that ise list is changed... */
1312 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1313 total_appids.push_back(it->appid);
1315 if (total_appids.size() > 0)
1316 _info_manager->update_ise_list (total_appids);
1318 if (ret > 1 && _soft_keyboard_launched) { // If the previous appid of pkgid is the current IME, restart it with new appid.
1319 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1320 if (current_ime_appid.compare (appids.front ()) == 0) {
1321 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1322 _info_manager->hide_helper (current_ime_appid);
1323 _info_manager->stop_helper (current_ime_appid);
1324 LOGD ("Start IME(%s)", appids.back ().c_str ());
1325 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids.back ());
1326 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1327 _info_manager->start_helper (appids.back ());
1331 else if (ret == 2) { // In case IME package is just updated...
1332 _update_ime_info ();
1334 if (_soft_keyboard_launched) { // If package is the current IME, restart it.
1335 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1336 if (isf_db_select_appids_by_pkgid(package, appids)) {
1337 if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the current ISE package is updated, restart it.
1338 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1339 if (it->mode == TOOLBAR_HELPER_MODE && it->appid.compare(current_ime_appid) == 0) { // Make sure it's Helper ISE...
1340 LOGD ("Restart IME(%s)", current_ime_appid.c_str ());
1341 _info_manager->hide_helper (current_ime_appid);
1342 _info_manager->stop_helper (current_ime_appid);
1343 _info_manager->start_helper (current_ime_appid);
1351 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...
1352 if (isf_db_select_appids_by_pkgid(package, appids) == 1) {
1353 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1354 if (it->pkgid.compare(package) == 0) {
1355 g_pkgids_to_be_updated_and_installed.push_back (std::make_pair (it->pkgid, it->is_enabled));
1359 if (it == _ime_info.end ()) // Probably not going to happen.
1360 g_pkgids_to_be_updated_and_installed.push_back(std::make_pair (String(package), 0));
1362 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1363 if (_soft_keyboard_launched && std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the updated IME is the current ISE...
1364 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1365 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1366 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1367 _info_manager->hide_helper (current_ime_appid);
1368 _info_manager->stop_helper (current_ime_appid);
1369 _soft_keyboard_launched = false;
1370 g_updated_helper_pkgid = package;
1376 if (appids.size () > 0) // Probably appids size is 1.
1377 LOGD ("Delete IME(%s)", appids[0].c_str ());
1378 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1381 /* Let panel know that ise is deleted... */
1382 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1383 total_appids.push_back(it->appid);
1385 if (total_appids.size() > 0)
1386 _info_manager->update_ise_list (total_appids);
1390 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1395 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL) {
1396 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1397 LOGD ("type=%s package=%s event_type=INSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1399 ///////////////// UNINSTALL -> INSTALL and if the uninstalled IME is reinstalled /////////////////
1400 if (g_stopped_helper_pkgid.compare(package) == 0 && g_start_default_helper_timer) {
1401 LOGD ("Cancel timer to start the default IME");
1402 ecore_timer_del(g_start_default_helper_timer);
1403 g_start_default_helper_timer = NULL;
1404 g_stopped_helper_pkgid = "";
1406 ret = _isf_insert_ime_info_by_pkgid(package);
1408 /* Find appid by pkgid. There might be multiple appid, but assume Helper always has one appid.
1409 And appid can be changed, but pkgid won't be changed. */
1410 ret = isf_db_select_appids_by_pkgid(package, appids);
1411 if (ret == 1 && appids.size () == 1) {
1412 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1413 if (it3->first.compare(package) == 0) {
1415 isf_db_update_is_enabled_by_appid(appids[0].c_str (), (bool)it3->second);
1419 /* Let panel know that ise is added... */
1420 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1421 total_appids.push_back(it->appid);
1423 if (total_appids.size() > 0)
1424 _info_manager->update_ise_list (total_appids);
1426 LOGD ("Restart IME(%s)", appids[0].c_str ());
1427 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids[0]);
1428 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1429 _info_manager->start_helper (appids[0]);
1430 _soft_keyboard_launched = true;
1432 g_pkgids_to_be_uninstalled.erase (it3);
1438 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1442 /* Let panel know that ise is added... */
1443 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1444 total_appids.push_back(it->appid);
1446 if (total_appids.size() > 0)
1447 _info_manager->update_ise_list (total_appids);
1451 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1454 else { // If new package is installed...
1455 ret = _isf_insert_ime_info_by_pkgid(package); // If package is not IME, -1 would be returned.
1456 if (ret > 0) { // In case package is IME...
1457 ///////////////// INSTALL /////////////////
1460 /* Let panel know that ise is added... */
1461 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1462 total_appids.push_back(it->appid);
1464 if (total_appids.size() > 0)
1465 _info_manager->update_ise_list (total_appids);
1466 ///////////////// END /////////////////
1468 /* For example, the following happens if appid is changed in IME project and Run As again. The appid would be changed this time.
1469 Assuming only Helper (3rd party) might be installed after update or uninstall and there is one appid per each pkgid...*/
1471 ///////////////// UPDATE -> INSTALL /////////////////
1472 for (it3 = g_pkgids_to_be_updated_and_installed.begin (); it3 != g_pkgids_to_be_updated_and_installed.end (); it3++) {
1473 if (it3->first.compare(package) == 0) {
1475 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1476 if (it->pkgid.compare(package) == 0) {
1477 it->is_enabled = it3->second;
1478 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1483 g_pkgids_to_be_updated_and_installed.erase (it3);
1487 if (g_updated_helper_pkgid.compare(package) == 0) {
1488 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1489 if (it->mode == TOOLBAR_HELPER_MODE && it->pkgid.compare(package) == 0) {
1490 LOGD ("Start IME(%s)", it->appid.c_str ());
1491 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), it->appid);
1492 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1493 _info_manager->start_helper (it->appid);
1494 _soft_keyboard_launched = true;
1498 g_updated_helper_pkgid = "";
1501 ///////////////// END /////////////////
1503 ///////////////// UNINSTALL -> INSTALL /////////////////
1504 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1505 if (it3->first.compare(package) == 0) {
1507 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1508 if (it->pkgid.compare(package) == 0) {
1509 it->is_enabled = it3->second;
1510 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1515 g_pkgids_to_be_uninstalled.erase (it3);
1519 ///////////////// END /////////////////
1521 else if (ret == 0) {
1522 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1527 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL) {
1528 switch (event_state) {
1529 case PACKAGE_MANAGER_EVENT_STATE_STARTED:
1530 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=STARTED progress=%d error=%d", type, package, progress, error);
1532 // Need to check if there is "http://tizen.org/category/ime" category; it can be done by comparing pkgid with ime_info db.
1534 if (_ime_info.size() == 0)
1537 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1538 if (it->pkgid.compare(package) == 0 && it->is_preinstalled == 0) { // Ignore if it's preinstalled IME and IMEngine.
1545 // 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.
1546 LOGD ("%s for pkgid(\"%s\") is about to be deleted", it->appid.c_str (), package);
1547 g_pkgids_to_be_uninstalled.push_back(std::make_pair (String(package), it->is_enabled));
1549 if (_soft_keyboard_launched && isf_db_select_appids_by_pkgid(package, appids)) {
1550 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1551 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.
1552 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1553 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1554 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1555 _info_manager->hide_helper (current_ime_appid);
1556 _info_manager->stop_helper (current_ime_appid);
1557 _soft_keyboard_launched = false;
1558 g_stopped_helper_pkgid = package;
1568 case PACKAGE_MANAGER_EVENT_STATE_COMPLETED:
1569 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1571 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1572 if (it3->first.compare(package) == 0) {
1573 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1577 if (g_stopped_helper_pkgid.compare(package) == 0) { // If the uninstalled ISE is the current ISE, start the initial helper ISE by timer.
1578 if (g_start_default_helper_timer)
1579 ecore_timer_del(g_start_default_helper_timer);
1580 LOGD ("Add timer to start the default IME");
1581 g_start_default_helper_timer = ecore_timer_add(3.0, _start_default_helper_timer, NULL);
1583 else { // Need to clean up g_pkgids_to_be_uninstalled info unless the same package is installed again; e.g., UNINSTALL -> INSTALL case.
1584 if (g_release_uninstalled_ime_info_timer)
1585 ecore_timer_del(g_release_uninstalled_ime_info_timer);
1586 LOGD ("Add timer to release uninstalled IME pkg info");
1587 g_release_uninstalled_ime_info_timer = ecore_timer_add(7.0, _release_uninstalled_pkginfo_timer, NULL);
1590 /* Let panel know that ise is deleted... */
1591 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1592 total_appids.push_back(it->appid);
1594 if (total_appids.size() > 0)
1595 _info_manager->update_ise_list (total_appids);
1602 case PACKAGE_MANAGER_EVENT_STATE_FAILED:
1603 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=FAILED progress=%d error=%d", type, package, progress, error);
1605 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1606 if (it3->first.compare(package) == 0) {
1607 // Update _ime_info for sure...
1610 if (g_stopped_helper_pkgid.compare(package) == 0) {
1611 ret = isf_db_select_appids_by_pkgid(package, appids);
1612 if (ret == 1 && appids.size () == 1) {
1613 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1614 if (it->appid.compare(appids[0]) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1615 LOGD ("Restart IME(%s)", appids[0].c_str ());
1616 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1617 _info_manager->start_helper (appids[0]);
1618 _soft_keyboard_launched = true;
1624 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1626 g_stopped_helper_pkgid = "";
1629 g_pkgids_to_be_uninstalled.erase (it3);
1643 * @brief Set keyboard ISE.
1645 * @param uuid The keyboard ISE's uuid.
1647 * @return false if keyboard ISE change is failed, otherwise return true.
1649 static bool set_keyboard_ise (const String &uuid)
1651 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1653 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1655 if (TOOLBAR_HELPER_MODE == mode) {
1656 String pre_uuid = _info_manager->get_current_helper_uuid ();
1657 _info_manager->hide_helper (pre_uuid);
1658 _info_manager->stop_helper (pre_uuid);
1659 _soft_keyboard_launched = false;
1660 } else if (TOOLBAR_KEYBOARD_MODE == mode) {
1661 uint32 kbd_option = 0;
1662 String kbd_uuid, kbd_name;
1663 isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
1664 if (kbd_uuid == uuid)
1668 _info_manager->change_factory (uuid);
1670 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
1671 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
1677 * @brief Set helper ISE.
1679 * @param uuid The helper ISE's uuid.
1680 * @param launch_ise The flag for launching helper ISE.
1682 * @return false if helper ISE change is failed, otherwise return true.
1684 static bool set_helper_ise (const String &uuid, bool launch_ise)
1686 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1688 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1689 String pre_uuid = _info_manager->get_current_helper_uuid ();
1690 LOGD ("pre_appid=%s, appid=%s, launch_ise=%d, %d", pre_uuid.c_str(), uuid.c_str(), launch_ise, _soft_keyboard_launched);
1691 if (pre_uuid == uuid && _soft_keyboard_launched)
1694 if (TOOLBAR_HELPER_MODE == mode && pre_uuid.length () > 0 && _soft_keyboard_launched) {
1695 _info_manager->hide_helper (pre_uuid);
1696 _info_manager->stop_helper (pre_uuid);
1697 _soft_keyboard_launched = false;
1698 LOGD ("stop helper : %s", pre_uuid.c_str ());
1702 LOGD ("Start helper (%s)", uuid.c_str ());
1704 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1705 if (_info_manager->start_helper (uuid))
1706 _soft_keyboard_launched = true;
1708 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), uuid);
1713 #ifdef HAVE_PKGMGR_INFO
1714 int get_ime_app_list_cb (const pkgmgrinfo_appinfo_h handle, void *user_data)
1717 char *appid = NULL, *pkgid = NULL, *pkgtype = NULL, *exec = NULL, *label = NULL, *path = NULL;
1718 pkgmgrinfo_pkginfo_h pkginfo_handle = NULL;
1720 int *result = static_cast<int*>(user_data);
1722 if (result) /* in this case, need to check category */ {
1724 ret = pkgmgrinfo_appinfo_is_category_exist (handle, "http://tizen.org/category/ime", &exist);
1725 if (ret != PMINFO_R_OK || !exist) {
1731 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
1732 if (ret == PMINFO_R_OK)
1733 ime_db.appid = String (appid ? appid : "");
1735 LOGE ("pkgmgrinfo_appinfo_get_appid failed! error code=%d", ret);
1739 ime_db.iconpath = "";
1742 ret = pkgmgrinfo_appinfo_get_pkgid (handle, &pkgid);
1743 if (ret == PMINFO_R_OK)
1744 ime_db.pkgid = String (pkgid ? pkgid : "");
1746 LOGE ("pkgmgrinfo_appinfo_get_pkgid failed! error code=%d", ret);
1751 ret = pkgmgrinfo_appinfo_get_exec (handle, &exec);
1752 if (ret == PMINFO_R_OK)
1753 ime_db.exec = String (exec ? exec : "");
1755 LOGE ("pkgmgrinfo_appinfo_get_exec failed! error code=%d", ret);
1760 ret = pkgmgrinfo_appinfo_get_label (handle, &label);
1761 if (ret == PMINFO_R_OK)
1762 ime_db.label = String (label ? label : "");
1764 /* get pkgmgrinfo_pkginfo_h */
1765 /* Try to get in global packages */
1766 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &pkginfo_handle);
1767 if (ret != PMINFO_R_OK) {
1768 /* Try to get in user packages */
1769 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, getuid (), &pkginfo_handle);
1772 if (ret == PMINFO_R_OK && pkginfo_handle) {
1774 ret = pkgmgrinfo_pkginfo_get_type (pkginfo_handle, &pkgtype);
1776 if (ret == PMINFO_R_OK)
1777 ime_db.pkgtype = String (pkgtype ? pkgtype : "");
1779 ISF_SAVE_LOG ("pkgtype is not available!");
1780 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1785 pkgmgrinfo_pkginfo_get_root_path (pkginfo_handle, &path);
1788 ime_db.languages = "en";
1789 ime_db.display_lang = "";
1791 if (ime_db.pkgtype.compare ("rpm") == 0 && //1 Inhouse IMEngine ISE(IME)
1792 ime_db.exec.find ("scim-launcher") != String::npos) // Some IMEngine's pkgid doesn't have "ise-engine" prefix.
1794 ime_db.mode = TOOLBAR_KEYBOARD_MODE;
1796 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1797 + String (SCIM_PATH_DELIM_STRING) + String ("IMEngine");
1798 ime_db.module_name = ime_db.pkgid;
1799 ime_db.is_enabled = 1;
1800 ime_db.is_preinstalled = 1;
1801 ime_db.has_option = 0; // It doesn't matter. No option for IMEngine...
1804 ime_db.mode = TOOLBAR_HELPER_MODE;
1805 if (ime_db.pkgtype.compare ("rpm") == 0 && path) //1 Inhouse Helper ISE(IME)
1808 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1810 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART;
1812 ime_db.module_name = ime_db.pkgid;
1814 String module_path = String (path) + String ("/lib");
1815 String fullpath = module_path + String (SCIM_PATH_DELIM_STRING) + ime_db.module_name + String (".so");
1817 if (stat (fullpath.c_str (), &st) < 0) {
1818 /* Not found in lib directory of package's root path */
1819 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1820 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1823 ime_db.module_path = module_path;
1826 ime_db.is_enabled = 1;
1827 ime_db.is_preinstalled = 1;
1828 ime_db.has_option = 1; // Let's assume the inhouse IME always has an option menu.
1830 else if (ime_db.pkgtype.compare ("wgt") == 0) //1 Download Web IME
1832 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1833 | SCIM_HELPER_NEED_SPOT_LOCATION_INFO | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1834 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1835 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1836 ime_db.module_name = String ("ise-web-helper-agent");
1837 if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1838 ime_db.is_enabled = 1;
1839 ime_db.is_preinstalled = 1;
1842 if (_MOBILE || _COMMON)
1843 ime_db.is_enabled = 0;
1845 ime_db.is_enabled = 1;
1847 ime_db.is_preinstalled = 0;
1849 ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1851 else if (ime_db.pkgtype.compare ("tpk") == 0) //1 Download Native IME
1853 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1854 | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1856 ime_db.module_path = String (path) + String ("/lib");
1858 ime_db.module_path = String (tzplatform_getenv(TZ_SYS_RW_APP)) + ime_db.pkgid + String ("/lib");
1859 ime_db.module_name = String ("lib") + ime_db.exec.substr (ime_db.exec.find_last_of (SCIM_PATH_DELIM) + 1);
1860 if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1861 ime_db.is_enabled = 1;
1862 ime_db.is_preinstalled = 1;
1865 if (_MOBILE || _COMMON)
1866 ime_db.is_enabled = 0;
1868 ime_db.is_enabled = 1;
1870 ime_db.is_preinstalled = 0;
1872 ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1875 LOGE ("Unsupported pkgtype(%s)", ime_db.pkgtype.c_str ());
1876 if (pkginfo_handle) {
1877 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1878 pkginfo_handle = NULL;
1884 _ime_info.push_back(ime_db);
1886 if (pkginfo_handle) {
1887 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1888 pkginfo_handle = NULL;
1896 * @brief Set active ISE.
1898 * @param uuid The ISE's uuid.
1899 * @param launch_ise The flag for launching helper ISE.
1901 * @return false if ISE change is failed, otherwise return true.
1903 static bool set_active_ise (const String &uuid, bool launch_ise)
1905 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1906 LOGD ("set ISE (%s) %d", uuid.c_str(), launch_ise);
1908 if (uuid.length () <= 0)
1911 bool ise_changed = false, valid = false;
1913 int ime_num = -1; /* If we failed retrieving the number of IMEs installed, assume we need to clear IME related settings */
1914 pkgmgrinfo_appinfo_filter_h handle;
1915 int ret = pkgmgrinfo_appinfo_filter_create(&handle);
1916 if (ret == PMINFO_R_OK) {
1917 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
1918 if (ret == PMINFO_R_OK) {
1919 ret = pkgmgrinfo_appinfo_filter_count(handle, &ime_num);
1920 if (ret != PMINFO_R_OK) {
1921 LOGW("pkgmgrinfo_appinfo_filter_count failed(%d)", ret);
1924 pkgmgrinfo_appinfo_filter_destroy (handle);
1927 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
1930 /* If the ime_num and _ime_info.size() are different, it is likely that the isf-panel-efl was
1931 terminated abnormally while processing package manager's install / uninstall events */
1932 LOGD("Checking whether db file needs to be re-created : %d %zu", ime_num, _ime_info.size());
1933 if (ime_num != (int)_ime_info.size()) {
1935 isf_db_delete_ime_info();
1936 isf_pkg_reload_ime_info_db();
1937 isf_pkg_select_all_ime_info_db(_ime_info);
1940 if (_ime_info.size () == 0) {
1941 #ifdef HAVE_PKGMGR_INFO
1942 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
1943 if (ret == PMINFO_R_OK) {
1944 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
1945 if (ret == PMINFO_R_OK)
1946 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
1948 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
1950 pkgmgrinfo_appinfo_filter_destroy (handle);
1953 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
1958 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1959 if (!uuid.compare (_ime_info[i].appid)) {
1960 if (TOOLBAR_KEYBOARD_MODE == _ime_info[i].mode)
1961 ise_changed = set_keyboard_ise (_ime_info[i].appid);
1962 else if (TOOLBAR_HELPER_MODE == _ime_info[i].mode) {
1963 if (_ime_info[i].is_enabled) {
1964 if (_ime_info[i].exec == String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
1965 /* If IME so is deleted somehow, main() in scim_helper_launcher.cpp will return -1.
1966 Checking HelperModule validity seems necessary here. */
1967 HelperModule helper_module (_ime_info[i].module_name);
1968 if (helper_module.valid ())
1970 helper_module.unload ();
1973 /* executable type */
1978 ise_changed = set_helper_ise (_ime_info[i].appid, launch_ise);
1980 LOGW ("Helper ISE(appid=\"%s\",module_name=\"%s\") is not valid.", _ime_info[i].appid.c_str (), _ime_info[i].module_name.c_str ());
1983 LOGW ("Helper ISE(appid=\"%s\") is not enabled.", _ime_info[i].appid.c_str ());
1986 _info_manager->set_current_toolbar_mode (_ime_info[i].mode);
1988 /* From Tizen 4.0 all the ISEs need to handle H/W keyboard events */
1989 _ime_info[i].options |= ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1990 _info_manager->set_current_helper_option (_ime_info[i].options);
1991 _info_manager->set_current_ise_name (_ime_info[i].label);
1992 _ise_state = WINDOW_STATE_HIDE;
1993 _candidate_mode = SOFT_CANDIDATE_WINDOW;
1994 _candidate_port_line = ONE_LINE_CANDIDATE;
1995 #if ISF_BUILD_CANDIDATE_UI
1998 _soft_candidate_width = 0;
1999 _soft_candidate_height = 0;
2001 if (_candidate_window)
2002 ui_create_candidate_window ();
2005 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _ime_info[i].appid);
2006 scim_global_config_flush ();
2012 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2016 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2023 LOGW ("Failed to launch IME (%s), %zu", uuid.c_str (), _ime_info.size());
2029 * @brief Set temporary ISE.
2031 * @param uuid The ISE's uuid.
2033 * @return false if ISE change is failed, otherwise return true.
2035 static bool set_temporary_ise (const String &uuid)
2037 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2038 LOGD ("set temporary ISE (%s)", uuid.c_str ());
2040 if (uuid.length () <= 0)
2043 if (_ime_info.size () == 0) {
2044 #ifdef HAVE_PKGMGR_INFO
2045 pkgmgrinfo_appinfo_filter_h handle;
2046 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
2047 if (ret == PMINFO_R_OK) {
2048 /* Add the package info for the IME that matches with our uuid only */
2049 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_ID, uuid.c_str ());
2050 if (ret == PMINFO_R_OK)
2051 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
2053 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
2055 pkgmgrinfo_appinfo_filter_destroy (handle);
2057 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
2062 #ifdef HAVE_PKGMGR_INFO
2063 bool ise_changed = false;
2065 pkgmgrinfo_appinfo_h handle = NULL;
2066 int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
2067 if (ret != PMINFO_R_OK) {
2068 LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
2074 ret = pkgmgrinfo_appinfo_get_label (handle, &label);
2075 if (ret != PMINFO_R_OK) {
2076 LOGW ("Could not get label for appid '%s'", uuid.c_str ());
2077 pkgmgrinfo_appinfo_destroy_appinfo (handle);
2081 ise_changed = set_helper_ise (uuid, true);
2084 _info_manager->set_current_toolbar_mode (TOOLBAR_HELPER_MODE);
2086 _info_manager->set_current_helper_option (SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO |
2087 SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT);
2089 _info_manager->set_current_helper_option (SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO |
2090 SCIM_HELPER_AUTO_RESTART);
2091 String label_string = label;
2092 _info_manager->set_current_ise_name (label_string);
2095 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2098 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2101 pkgmgrinfo_appinfo_destroy_appinfo (handle);
2111 * @brief Load ISF configuration and ISEs information.
2113 static void load_config (void)
2115 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2117 /* Read configurations. */
2118 if (!_config.null ()) {
2119 bool shared_ise = _config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), false);
2120 _info_manager->set_should_shared_ise (shared_ise);
2122 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
2123 _auto_destroy_ise = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_ENABLE_AUTO_DESTROY_ISE), _auto_destroy_ise);
2124 _enable_auto_restart = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_ENABLE_AUTO_RESTART_ISE), _enable_auto_restart);
2126 isf_load_ise_information (ALL_ISE, _config);
2130 * @brief Reload config callback function for ISF panel.
2132 * @param config The config pointer.
2134 static void config_reload_cb (const ConfigPointer &config)
2136 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2137 /* load_config (); */
2138 _info_manager->reload_config ();
2141 #if ISF_BUILD_CANDIDATE_UI
2142 //////////////////////////////////////////////////////////////////////
2143 // Start of Candidate Functions
2144 //////////////////////////////////////////////////////////////////////
2146 * @brief Get candidate window valid height for autoscroll.
2148 * @return The valid height.
2150 static int ui_candidate_get_valid_height (void)
2152 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2157 if (_candidate_window) {
2158 if (_candidate_state == WINDOW_STATE_SHOW)
2159 angle = _candidate_angle;
2161 angle = efl_get_app_window_angle ();
2163 if (_aux_area_visible && _candidate_area_1_visible) {
2164 if (angle == 90 || angle == 270)
2165 height = _candidate_land_height_min_2;
2167 height = _candidate_port_height_min_2;
2169 if (angle == 90 || angle == 270)
2170 height = _candidate_land_height_min;
2172 height = _candidate_port_height_min;
2179 * @brief Resize candidate window size.
2181 * @param new_width New width for candidate window.
2182 * @param new_height New height for candidate window.
2184 static void ui_candidate_window_resize (int new_width, int new_height)
2186 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " width:" << new_width << " height:" << new_height << "\n";
2188 if (!_candidate_window)
2193 LOGD ("%s (w: %d, h: %d)", __func__, new_width, new_height);
2194 evas_object_resize (_aux_line, new_width, 2);
2195 _candidate_width = new_width;
2196 _candidate_height = new_height;
2197 if (_candidate_state == WINDOW_STATE_SHOW)
2198 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2200 if (_candidate_state == WINDOW_STATE_SHOW && _candidate_mode == FIXED_CANDIDATE_WINDOW) {
2201 height = ui_candidate_get_valid_height ();
2202 if ((_ise_width == 0 && _ise_height == 0) ||
2203 (_ise_height > 0 && _candidate_valid_height != height) ||
2204 (_ise_height > 0 && (_candidate_height - height) > _ise_height) ||
2205 ((_candidate_angle == 90 || _candidate_angle == 270) && (_ise_width < _screen_height)) ||
2206 ((_candidate_angle == 0 || _candidate_angle == 180) && (_ise_width > _screen_width ))) {
2208 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2210 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2214 /* Get height for portrait and landscape */
2215 int port_width = _candidate_port_width;
2216 int port_height = _candidate_port_height_min;
2217 int land_width = _candidate_land_width;
2218 int land_height = _candidate_land_height_min;
2219 if (_candidate_angle == 90 || _candidate_angle == 270) {
2220 land_height = new_height;
2221 if (land_height == _candidate_land_height_min_2) {
2222 port_height = _candidate_port_height_min_2;
2223 } else if (land_height == _candidate_land_height_max) {
2224 port_height = _candidate_port_height_max;
2225 } else if (land_height == _candidate_land_height_max_2) {
2226 port_height = _candidate_port_height_max_2;
2229 port_height = new_height;
2230 if (port_height == _candidate_port_height_min_2) {
2231 land_height = _candidate_land_height_min_2;
2232 } else if (port_height == _candidate_port_height_max) {
2233 land_height = _candidate_land_height_max;
2234 } else if (port_height == _candidate_port_height_max_2) {
2235 land_height = _candidate_land_height_max_2;
2239 LOGD ("window_rotation_geometry_set (_candidate_window), port (%d, %d), land (%d, %d)",
2240 port_width, port_height, land_width, land_height);
2244 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2245 0, 0, 0, port_width, port_height);
2246 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2247 90, 0, 0, land_height, land_width);
2248 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2249 180, 0, 0, port_width, port_height);
2250 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2251 270, 0, 0, land_height, land_width);
2254 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2255 0, 0, 0, port_width, port_height);
2256 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2257 90, 0, 0, land_height, land_width);
2258 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2259 180, 0, 0, port_width, port_height);
2260 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2261 270, 0, 0, land_height, land_width);
2266 * @brief This function will show/hide widgets of candidate window,
2267 * and resize candidate window size according to aux_area/candidate_area.
2269 static void ui_candidate_window_adjust (void)
2271 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2272 if (!_candidate_window)
2275 int x = 0, y = 0, width = 0, height = 0;
2277 /* Get candidate window size */
2280 if (_candidate_angle == 90 || _candidate_angle == 270) {
2281 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2282 &x, &y, &height, &width);
2284 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2285 &x, &y, &width, &height);
2289 if (_candidate_angle == 90 || _candidate_angle == 270)
2290 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &height, &width);
2292 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
2295 if (_aux_area_visible && _candidate_area_2_visible) {
2296 evas_object_show (_aux_line);
2297 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);
2298 if (_candidate_angle == 90 || _candidate_angle == 270) {
2299 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2300 _ise_height > _candidate_land_height_max_2 - _candidate_land_height_min_2)
2301 ui_candidate_window_resize (width, _candidate_land_height_min_2 + _ise_height);
2303 ui_candidate_window_resize (width, _candidate_land_height_max_2);
2304 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2305 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min_2);
2306 evas_object_move (_scroller_bg, 0, _candidate_land_height_min_2);
2307 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2309 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2310 _ise_height > _candidate_port_height_max_2 - _candidate_port_height_min_2)
2311 ui_candidate_window_resize (width, _candidate_port_height_min_2 + _ise_height);
2313 ui_candidate_window_resize (width, _candidate_port_height_max_2);
2314 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2315 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min_2);
2316 evas_object_move (_scroller_bg, 0, _candidate_port_height_min_2);
2317 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2319 } else if (_aux_area_visible && _candidate_area_1_visible) {
2320 evas_object_show (_aux_line);
2321 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);
2322 if (_candidate_angle == 90 || _candidate_angle == 270) {
2323 ui_candidate_window_resize (width, _candidate_land_height_min_2);
2324 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2325 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2327 ui_candidate_window_resize (width, _candidate_port_height_min_2);
2328 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2329 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2331 } else if (_aux_area_visible) {
2332 evas_object_hide (_aux_line);
2333 ui_candidate_window_resize (width, _aux_height + 2);
2334 evas_object_resize (_candidate_bg, width, _aux_height + 2);
2335 } else if (_candidate_area_2_visible) {
2336 evas_object_hide (_aux_line);
2337 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2338 if (_candidate_angle == 90 || _candidate_angle == 270) {
2339 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2340 _ise_height > _candidate_land_height_max - _candidate_land_height_min)
2341 ui_candidate_window_resize (width, _candidate_land_height_min + _ise_height);
2343 ui_candidate_window_resize (width, _candidate_land_height_max);
2344 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3]);
2345 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min);
2346 evas_object_move (_scroller_bg, 0, _candidate_land_height_min);
2347 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2349 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2350 _ise_height > _candidate_port_height_max - _candidate_port_height_min)
2351 ui_candidate_window_resize (width, _candidate_port_height_min + _ise_height);
2353 ui_candidate_window_resize (width, _candidate_port_height_max);
2354 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
2355 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min);
2356 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
2357 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2360 evas_object_hide (_aux_line);
2361 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2362 if (_candidate_angle == 90 || _candidate_angle == 270) {
2363 ui_candidate_window_resize (width, _candidate_land_height_min);
2364 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3]);
2365 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2367 ui_candidate_window_resize (width, _candidate_port_height_min);
2368 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
2369 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2375 * @brief Rotate candidate window.
2377 * @param angle The angle of candidate window.
2379 static void ui_candidate_window_rotate (int angle)
2381 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2382 if (!_candidate_window)
2385 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
2387 if (angle == 90 || angle == 270) {
2388 _candidate_scroll_width = _candidate_scroll_width_max;
2389 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
2390 evas_object_resize (_aux_area, _aux_land_width, _aux_height);
2391 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_max, _item_min_height);
2392 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_min);
2393 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_min + 6);
2395 _candidate_scroll_width = _candidate_scroll_width_min;
2396 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
2397 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
2398 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
2399 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_max);
2400 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
2403 evas_object_hide (_candidate_area_2);
2404 _candidate_area_2_visible = false;
2405 ui_candidate_window_adjust ();
2406 if (_candidate_area_1_visible) {
2407 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2408 ui_tts_focus_rect_hide ();
2414 * @brief This function is used to judge whether candidate window should be hidden.
2416 * @return true if candidate window should be hidden, otherwise return false.
2418 static bool ui_candidate_can_be_hide (void)
2420 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2422 if (_aux_area_visible || _candidate_area_1_visible || _candidate_area_2_visible)
2429 * @brief Delete check candidate window size timer.
2433 static void ui_candidate_delete_check_size_timer (void)
2435 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2437 if (_check_size_timer != NULL) {
2438 ecore_timer_del (_check_size_timer);
2439 _check_size_timer = NULL;
2444 * @brief Callback function for check candidate window size timer.
2446 * @param data Data to pass when it is called.
2448 * @return ECORE_CALLBACK_CANCEL
2450 static Eina_Bool ui_candidate_check_size_timeout (void *data)
2452 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2454 ui_candidate_delete_check_size_timer ();
2455 ui_candidate_window_resize (_candidate_width, _candidate_height);
2456 ui_settle_candidate_window ();
2457 return ECORE_CALLBACK_CANCEL;
2461 * @brief Delete longpress timer.
2465 static void ui_candidate_delete_longpress_timer (void)
2467 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2469 if (_longpress_timer != NULL) {
2470 ecore_timer_del (_longpress_timer);
2471 _longpress_timer = NULL;
2476 * @brief Callback function for candidate longpress timer.
2478 * @param data Data to pass when it is called.
2480 * @return ECORE_CALLBACK_CANCEL
2482 static Eina_Bool ui_candidate_longpress_timeout (void *data)
2484 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2486 int index = (int)GPOINTER_TO_INT (data);
2487 ui_candidate_delete_longpress_timer ();
2489 _info_manager->send_longpress_event (_click_object, index);
2490 return ECORE_CALLBACK_CANCEL;
2494 * @brief Delete destroy timer.
2498 static void ui_candidate_delete_destroy_timer (void)
2500 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2502 if (_destroy_timer != NULL) {
2503 ecore_timer_del (_destroy_timer);
2504 _destroy_timer = NULL;
2509 * @brief Callback function for destroy timer.
2511 * @param data Data to pass when it is called.
2513 * @return ECORE_CALLBACK_CANCEL
2515 static Eina_Bool ui_candidate_destroy_timeout (void *data)
2517 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2519 ui_candidate_delete_destroy_timer ();
2520 ui_destroy_candidate_window ();
2521 return ECORE_CALLBACK_CANCEL;
2523 #endif /* CANDIDATE */
2527 * @brief Callback function for off_prepare_done.
2529 * @param data Data to pass when it is called.
2531 * @return ECORE_CALLBACK_CANCEL
2533 static Eina_Bool off_prepare_done_timeout (void *data)
2535 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2537 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
2538 // WILL_HIDE_REQUEST_DONE Ack to WM
2539 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
2540 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
2541 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
2542 root_window, _control_window);
2543 _off_prepare_done_timer = NULL;
2545 return ECORE_CALLBACK_CANCEL;
2547 #endif /* HAVE_ECOREX */
2549 #if ISF_BUILD_CANDIDATE_UI
2551 * @brief Delete candidate hide timer.
2555 static void delete_candidate_hide_timer (void)
2557 LOGD ("deleting candidate_hide_timer");
2558 if (_candidate_hide_timer) {
2559 ecore_timer_del (_candidate_hide_timer);
2560 _candidate_hide_timer = NULL;
2564 static void candidate_window_hide (void)
2566 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2568 delete_candidate_hide_timer ();
2569 _candidate_state = WINDOW_STATE_HIDE;
2571 LOGD ("evas_object_hide (_candidate_window, %p)", elm_win_xwindow_get (_candidate_window));
2573 if (_candidate_window) {
2574 /* There are cases that when there are rapid ISE_HIDE and ISE_SHOW requests,
2575 candidate window should be displayed but STATE_OFF for the first ISE_HIDE
2576 calls this function, so when the candidate window is shown by the following
2577 STATE_ON message, a blank area is displayed in candidate window -
2578 so we let the _candidate_area_1 as the default area that would be displayed */
2579 //evas_object_hide (_candidate_area_1);
2580 //evas_object_hide (_more_btn);
2581 _candidate_area_1_visible = false;
2583 evas_object_hide (_candidate_window);
2584 SCIM_DEBUG_MAIN (3) << " Hide candidate window\n";
2589 * @brief Callback function for candidate hide timer
2591 * @param data Data to pass when it is called.
2593 * @return ECORE_CALLBACK_CANCEL
2595 static Eina_Bool candidate_hide_timer (void *data)
2597 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2599 LOGD ("calling candidate_window_hide ()");
2600 candidate_window_hide ();
2602 return ECORE_CALLBACK_CANCEL;
2607 * @brief Delete candidate show handler.
2611 static void delete_candidate_show_handler (void)
2613 if (_candidate_show_handler) {
2614 ecore_event_handler_del (_candidate_show_handler);
2615 _candidate_show_handler = NULL;
2620 * @brief Callback function for window show completion event
2622 * @param data Data to pass when it is called.
2624 * @return ECORE_CALLBACK_CANCEL
2627 static Eina_Bool x_event_window_show_cb (void *data, int ev_type, void *event)
2629 delete_candidate_show_handler ();
2631 Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
2632 if (_candidate_state == WINDOW_STATE_WILL_SHOW) {
2633 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2634 LOGD ("Candidate window show callback");
2636 /* If our candidate window is in WILL_SHOW state and this show callback was called,
2637 now we are finally displayed on to the screen */
2638 _candidate_state = WINDOW_STATE_SHOW;
2640 /* Update the geometry information for auto scrolling */
2641 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2642 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2643 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2645 /* And the state event */
2646 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2648 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2649 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2650 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2651 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2656 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2657 LOGD ("Candidate window show callback, but _candidate_state is %d", _candidate_state);
2661 return ECORE_CALLBACK_CANCEL;
2663 #endif /* HAVE_ECOREX */
2666 * @brief Show candidate window.
2668 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2670 static void ui_candidate_show (bool bSetVirtualKbd)
2672 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2674 delete_candidate_hide_timer ();
2676 if (!_candidate_window) return;
2677 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
2680 /* FIXME : SHOULD UNIFY THE METHOD FOR CHECKING THE HW KEYBOARD EXISTENCE */
2681 /* If the ISE is not visible currently, wait for the ISE to be opened and then show our candidate window */
2682 _candidate_show_requested = true;
2683 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) && (_ise_state != WINDOW_STATE_SHOW)) {
2684 LOGD ("setting _show_candidate_requested to TRUE");
2688 /* If the ISE angle is valid, respect the value to make sure
2689 the candidate window always have the same angle with ISE */
2690 if (_ise_angle != -1) {
2691 _candidate_angle = _ise_angle;
2693 ui_candidate_window_rotate (_candidate_angle);
2695 /* If the candidate window was about to hide, turn it back to SHOW state now */
2696 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
2697 _candidate_state = WINDOW_STATE_SHOW;
2700 /* Change to WILL_SHOW state only when we are not currently in SHOW state */
2701 if (_candidate_state != WINDOW_STATE_SHOW) {
2702 _candidate_state = WINDOW_STATE_WILL_SHOW;
2706 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2707 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
2708 // Unset conformant area
2709 Ecore_X_Window current_app_window = efl_get_app_window ();
2710 if (_app_window != current_app_window) {
2711 struct rectinfo info = {0, 0, 0, 0};
2712 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
2713 set_keyboard_geometry_atom_info (_app_window, info);
2714 LOGD ("Conformant reset for window %x", _app_window);
2715 _app_window = current_app_window;
2719 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2720 if (bSetVirtualKbd) {
2721 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2724 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
2727 ui_candidate_delete_check_size_timer ();
2728 _check_size_timer = ecore_timer_add (0.02, ui_candidate_check_size_timeout, NULL);
2730 SCIM_DEBUG_MAIN (3) << " Show candidate window\n";
2732 if (_ise_state == WINDOW_STATE_SHOW) {
2733 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
2734 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
2736 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
2737 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
2740 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2741 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2742 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2743 LOGD ("sending ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW");
2744 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
2748 if (_candidate_state != WINDOW_STATE_SHOW) {
2750 if (_candidate_show_handler) {
2751 LOGD ("Was still waiting for CANDIDATE_WINDOW_SHOW....");
2753 delete_candidate_show_handler ();
2754 LOGD ("Registering ECORE_X_EVENT_WINDOW_SHOW event, %d", _candidate_state);
2755 _candidate_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_window_show_cb, NULL);
2759 LOGD ("The candidate window was already in SHOW state, update geometry information");
2760 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2761 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2763 /* And the state event */
2764 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2766 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2767 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2768 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2769 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2774 evas_object_show (_candidate_window);
2778 * @brief Hide candidate window.
2780 * @param bForce The flag to hide candidate window by force.
2781 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2783 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd, bool will_hide)
2785 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " bForce:" << bForce << " bSetVirtualKbd:" << bSetVirtualKbd << " will_hide:" << will_hide << "...\n";
2787 if (!_candidate_window)
2791 if (_candidate_area_2 && _candidate_area_2_visible) {
2792 evas_object_hide (_candidate_area_2);
2793 _candidate_area_2_visible = false;
2794 evas_object_hide (_scroller_bg);
2795 evas_object_hide (_close_btn);
2796 _info_manager->candidate_more_window_hide ();
2797 ui_candidate_window_adjust ();
2801 if (bForce || ui_candidate_can_be_hide ()) {
2803 LOGD ("candidate_state = WILL_HIDE");
2804 _candidate_state = WINDOW_STATE_WILL_HIDE;
2806 delete_candidate_hide_timer ();
2807 _candidate_hide_timer = ecore_timer_add (2.0, candidate_hide_timer, NULL);
2810 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2811 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2812 /* FIXME : should check if bSetVirtualKbd flag is really needed in this case */
2814 if (_ise_state == WINDOW_STATE_SHOW) {
2815 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2817 if (bSetVirtualKbd) {
2818 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2822 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2823 _info_manager->update_input_panel_event
2824 ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_HIDE);
2828 /* Update the new keyboard geometry first, and then send the candidate hide event */
2829 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_HIDE);
2832 /* If we are not in will_hide state, hide the candidate window immediately */
2833 candidate_window_hide ();
2835 if (_preedit_window)
2836 evas_object_hide (_preedit_window);
2842 * @brief Callback function for more button.
2844 * @param data Data to pass when it is called.
2845 * @param e The evas for current event.
2846 * @param button The evas object for current event.
2847 * @param event_info The information for current event.
2849 static void ui_candidate_window_more_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2851 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2853 _info_manager->candidate_more_window_show ();
2855 if (candidate_expanded == false) {
2856 candidate_expanded = true;
2857 int number = SCIM_LOOKUP_TABLE_MAX_PAGESIZE;
2858 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
2859 if (_candidate_0 [i] == NULL) {
2864 if (g_isf_candidate_table.get_current_page_size () != number)
2865 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2868 if (_candidate_angle == 180) {
2869 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2870 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2871 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2872 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2874 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2875 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2876 * for avoiding this situation.
2878 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2879 ecore_evas_move_resize (ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2880 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2881 ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2884 evas_object_show (_candidate_area_2);
2885 _candidate_area_2_visible = true;
2886 evas_object_show (_scroller_bg);
2887 evas_object_hide (_more_btn);
2888 evas_object_show (_close_btn);
2890 ui_candidate_window_adjust ();
2891 ui_settle_candidate_window ();
2896 * @brief Callback function for close button.
2898 * @param data Data to pass when it is called.
2899 * @param e The evas for current event.
2900 * @param button The evas object for current event.
2901 * @param event_info The information for current event.
2903 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2905 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2907 if (_candidate_area_2 == NULL || !_candidate_area_2_visible)
2910 _info_manager->candidate_more_window_hide ();
2912 evas_object_hide (_candidate_area_2);
2913 _candidate_area_2_visible = false;
2914 evas_object_hide (_scroller_bg);
2915 evas_object_hide (_close_btn);
2917 candidate_expanded = false;
2918 evas_object_show (_candidate_area_1);
2919 _candidate_area_1_visible = true;
2920 evas_object_show (_more_btn);
2922 elm_scroller_region_show (_candidate_area_2, 0, 0, _candidate_scroll_width, 100);
2923 if (_candidate_angle == 180) {
2924 Ecore_Evas *ee= ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2925 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2926 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2927 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2929 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2930 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2931 * for avoiding this situation.
2933 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2934 ecore_evas_move_resize (ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2935 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2936 ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2939 ui_candidate_window_adjust ();
2940 ui_settle_candidate_window ();
2945 * @brief Callback function for mouse button press.
2947 * @param data Data to pass when it is called.
2948 * @param e The evas for current event.
2949 * @param button The evas object for current event.
2950 * @param event_info The information for current event.
2952 static void ui_mouse_button_pressed_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2954 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2956 _click_object = GPOINTER_TO_INT (data) & 0xFF;
2959 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
2962 _click_down_pos [0] = ev->canvas.x;
2963 _click_down_pos [1] = ev->canvas.y;
2965 if (_click_object == ISF_EFL_CANDIDATE_0 || _click_object == ISF_EFL_CANDIDATE_ITEMS) {
2966 int index = (int)GPOINTER_TO_INT (data) >> 8;
2968 #ifdef HAVE_FEEDBACK
2969 if (feedback_initialized) {
2970 int feedback_result = 0;
2971 bool sound_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_SOUND_FEEDBACK, false);
2973 if (sound_feedback) {
2974 feedback_result = feedback_play_type (FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_SIP);
2976 if (FEEDBACK_ERROR_NONE == feedback_result)
2977 LOGD ("Sound play successful");
2979 LOGW ("Cannot play feedback sound : %d", feedback_result);
2982 bool vibrate_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_VIBRATION_FEEDBACK, false);
2984 if (vibrate_feedback) {
2985 feedback_result = feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
2987 if (FEEDBACK_ERROR_NONE == feedback_result)
2988 LOGD ("Vibration play successful");
2990 LOGW ("Cannot play feedback vibration : %d", feedback_result);
2995 ui_candidate_delete_longpress_timer ();
2996 _longpress_timer = ecore_timer_add (1.0, ui_candidate_longpress_timeout, (void *)index);
3001 * @brief Callback function for mouse button release.
3003 * @param data Data to pass when it is called.
3004 * @param e The evas for current event.
3005 * @param button The evas object for current event.
3006 * @param event_info The information for current event.
3008 static void ui_mouse_button_released_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3010 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " index:" << GPOINTER_TO_INT (data) << "...\n";
3012 ui_candidate_delete_longpress_timer ();
3014 int index = GPOINTER_TO_INT (data);
3015 if (_click_object == ISF_EFL_AUX && _is_click) {
3017 const char *buf = edje_object_part_state_get (button, "aux", &ret);
3018 if (strcmp ("selected", buf)) {
3019 for (unsigned int i = 0; i < _aux_items.size (); i++) {
3020 buf = edje_object_part_state_get (_aux_items [i], "aux", &ret);
3021 if (!strcmp ("selected", buf))
3022 edje_object_signal_emit (_aux_items [i], "aux,state,unselected", "aux");
3024 edje_object_signal_emit (button, "aux,state,selected", "aux");
3025 _info_manager->select_aux (index);
3027 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
3028 edje_object_color_class_get (_aux_items [index], "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
3029 // Normal item is clicked
3030 if (!(r == 62 && g == 207 && b == 255)) {
3031 for (unsigned int i = 0; i < _aux_items.size (); i++) {
3032 edje_object_color_class_set (_aux_items [i], "text_color", 249, 249, 249, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3034 edje_object_color_class_set (_aux_items [index], "text_color", 62, 207, 255, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3035 _info_manager->select_aux (index);
3037 } else if (_click_object == ISF_EFL_CANDIDATE_0 && _is_click) {
3038 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3039 _info_manager->select_candidate (index);
3040 } else if (_click_object == ISF_EFL_CANDIDATE_ITEMS && _is_click) {
3041 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3042 _info_manager->select_candidate (index);
3047 * @brief Callback function for mouse move.
3049 * @param data Data to pass when it is called.
3050 * @param e The evas for current event.
3051 * @param button The evas object for current event.
3052 * @param event_info The information for current event.
3054 static void ui_mouse_moved_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3056 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3058 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
3061 _click_up_pos [0] = ev->canvas.x;
3062 _click_up_pos [1] = ev->canvas.y;
3064 if (abs (_click_up_pos [0] - _click_down_pos [0]) >= (int)(15 * _height_rate) ||
3065 abs (_click_up_pos [1] - _click_down_pos [1]) >= (int)(15 * _height_rate)) {
3067 ui_candidate_delete_longpress_timer ();
3072 * @brief Show rect for candidate focus object when screen reader is enabled.
3074 * @param x Rect X position.
3075 * @param y Rect Y position.
3076 * @param w Rect width.
3077 * @param h Rect height.
3079 static void ui_tts_focus_rect_show (int x, int y, int w, int h)
3081 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3082 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
3085 if (_tts_focus_rect == NULL) {
3086 _tts_focus_rect = evas_object_rectangle_add (evas_object_evas_get ((Evas_Object*)_candidate_window));
3087 evas_object_color_set (_tts_focus_rect, 0, 0, 0, 0);
3088 elm_access_highlight_set (elm_access_object_register (_tts_focus_rect, (Evas_Object*)_candidate_window));
3090 evas_object_move (_tts_focus_rect, x, y);
3091 evas_object_resize (_tts_focus_rect, w, h);
3092 evas_object_raise (_tts_focus_rect);
3093 evas_object_show (_tts_focus_rect);
3097 * @brief Hide rect for candidate focus object when screen reader is enabled.
3099 static void ui_tts_focus_rect_hide (void)
3101 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3103 if (_tts_focus_rect) {
3104 //evas_object_hide (_tts_focus_rect);
3105 evas_object_move (_tts_focus_rect, -1000, -1000);
3110 * @brief Callback function for candidate scroller stop event.
3112 * @param data Data to pass when it is called.
3113 * @param obj The evas object for current event.
3114 * @param event_info The information for current event.
3116 static void ui_candidate_scroller_stop_cb (void *data, Evas_Object *obj, void *event_info)
3118 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3119 if (!_wait_stop_event)
3122 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
3123 if (_candidate_0 [_candidate_tts_focus_index]) {
3125 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
3126 ui_tts_focus_rect_show (x, y, w, h);
3129 _wait_stop_event = false;
3133 * @brief Create preedit window.
3135 static void ui_create_preedit_window (void)
3137 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3139 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3142 _preedit_width = 100;
3143 _preedit_height = _preedit_height * _height_rate;
3144 if (_preedit_window == NULL) {
3145 _preedit_window = efl_create_window ("ISF Popup", "Preedit Window");
3146 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
3147 int rots [4] = {0, 90, 180, 270};
3148 elm_win_wm_rotation_available_rotations_set (_preedit_window, rots, 4);
3149 int preedit_font_size = (int)(32 * _width_rate);
3151 _preedit_text = edje_object_add (evas_object_evas_get (_preedit_window));
3152 edje_object_file_set (_preedit_text, _candidate_edje_file.c_str (), "preedit_text");
3153 evas_object_size_hint_fill_set (_preedit_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
3154 evas_object_size_hint_weight_set (_preedit_text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3155 elm_win_resize_object_add (_preedit_window, _preedit_text);
3156 evas_object_show (_preedit_text);
3158 _tmp_preedit_text = evas_object_text_add (evas_object_evas_get (_preedit_window));
3159 evas_object_text_font_set (_tmp_preedit_text, _candidate_font_name.c_str (), preedit_font_size);
3164 * @brief Create native style candidate window.
3166 static void ui_create_native_candidate_window (void)
3168 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3169 _more_btn_width = 80 * (_width_rate > 1 ? 1 : _width_rate);
3170 _more_btn_height = 64 * _height_rate;
3172 _candidate_port_width = _screen_width;
3173 _candidate_port_height_min = 84 * _height_rate * _candidate_port_line;
3174 _candidate_port_height_min_2 = 84 * _height_rate + _candidate_port_height_min;
3175 _candidate_port_height_max = 426 * _height_rate + _candidate_port_height_min;
3176 _candidate_port_height_max_2 = 84 * _height_rate + _candidate_port_height_max;
3177 _candidate_land_width = _screen_height;
3178 _candidate_land_height_min = 84 * _width_rate;
3179 _candidate_land_height_min_2 = 168 * _width_rate;
3180 _candidate_land_height_max = 342 * _width_rate;
3181 _candidate_land_height_max_2 = 426 * _width_rate;
3183 _candidate_scroll_0_width_min= _screen_width;
3184 _candidate_scroll_0_width_max= _screen_height;
3185 _candidate_scroll_width_min = _screen_width;
3186 _candidate_scroll_width_max = _screen_height;
3187 _candidate_scroll_height_min = 252 * _width_rate;
3188 _candidate_scroll_height_max = 420 * _height_rate;
3190 _candidate_area_1_pos [0] = 0 * _width_rate;
3191 _candidate_area_1_pos [1] = 2 * _height_rate;
3192 _more_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3193 _more_btn_pos [1] = 12 * _height_rate;
3194 _more_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3195 _more_btn_pos [3] = 12 * _width_rate;
3196 _close_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3197 _close_btn_pos [1] = 12 * _height_rate;
3198 _close_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3199 _close_btn_pos [3] = 12 * _width_rate;
3201 _aux_height = 84 * _height_rate - 2;
3202 _aux_port_width = _screen_width;
3203 _aux_land_width = _screen_height;
3205 _item_min_height = 84 * _height_rate - 2;
3207 /* Create candidate window */
3208 if (_candidate_window == NULL) {
3209 _candidate_window = efl_create_window ("ISF Popup", "Prediction Window");
3210 int rots [4] = {0, 90, 180, 270};
3211 elm_win_wm_rotation_available_rotations_set (_candidate_window, rots, 4);
3212 if (_candidate_angle == 90 || _candidate_angle == 270) {
3213 _candidate_width = _candidate_land_width;
3214 _candidate_height = _candidate_land_height_min;
3216 _candidate_width = _candidate_port_width;
3217 _candidate_height = _candidate_port_height_min;
3221 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3222 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3223 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3224 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3225 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3226 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3227 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3228 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3231 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3232 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3233 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3234 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3235 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3236 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3237 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3238 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3240 /* Add dim background */
3241 Evas_Object *dim_bg = elm_bg_add (_candidate_window);
3242 evas_object_color_set (dim_bg, 0, 0, 0, 153);
3243 elm_win_resize_object_add (_candidate_window, dim_bg);
3244 evas_object_show (dim_bg);
3246 /* Add candidate background */
3247 _candidate_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3248 edje_object_file_set (_candidate_bg, _candidate_edje_file.c_str (), "candidate_bg");
3249 evas_object_size_hint_weight_set (_candidate_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3250 evas_object_resize (_candidate_bg, _candidate_port_width, _candidate_port_height_min);
3251 evas_object_move (_candidate_bg, 0, 0);
3252 evas_object_show (_candidate_bg);
3254 /* Create _candidate_0 scroller */
3255 _candidate_0_scroll = elm_scroller_add (_candidate_window);
3256 elm_scroller_bounce_set (_candidate_0_scroll, EINA_TRUE, EINA_FALSE);
3257 elm_scroller_policy_set (_candidate_0_scroll, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3258 evas_object_resize (_candidate_0_scroll, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
3259 evas_object_move (_candidate_0_scroll, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3261 /* Create candidate table */
3262 _candidate_0_table = elm_table_add (_candidate_window);
3263 evas_object_size_hint_weight_set (_candidate_0_table, 0.0, 0.0);
3264 evas_object_size_hint_align_set (_candidate_0_table, 0.0, 0.0);
3265 elm_table_padding_set (_candidate_0_table, 0, 0);
3266 elm_object_content_set (_candidate_0_scroll, _candidate_0_table);
3267 evas_object_show (_candidate_0_table);
3268 _candidate_area_1 = _candidate_0_scroll;
3270 /* Create more button */
3271 _more_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3272 if (_ise_width == 0 && _ise_height == 0)
3273 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
3275 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
3276 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
3277 evas_object_resize (_more_btn, _more_btn_width, _more_btn_height);
3278 evas_object_event_callback_add (_more_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_more_button_cb, NULL);
3280 /* Add scroller background */
3281 _candidate_scroll_width = _candidate_scroll_width_min;
3282 _scroller_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3283 edje_object_file_set (_scroller_bg, _candidate_edje_file.c_str (), "scroller_bg");
3284 evas_object_size_hint_weight_set (_scroller_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3285 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3286 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
3288 /* Create vertical scroller */
3289 _candidate_scroll = elm_scroller_add (_candidate_window);
3290 elm_scroller_bounce_set (_candidate_scroll, 0, 1);
3291 elm_scroller_policy_set (_candidate_scroll, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
3292 evas_object_resize (_candidate_scroll, _candidate_scroll_width, _candidate_scroll_height_max);
3293 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3294 elm_scroller_page_size_set (_candidate_scroll, 0, _item_min_height+_v_padding);
3295 evas_object_move (_candidate_scroll, 0, _candidate_port_height_min);
3297 /* Create candidate table */
3298 _candidate_table = elm_table_add (_candidate_window);
3299 evas_object_size_hint_weight_set (_candidate_table, 0.0, 0.0);
3300 evas_object_size_hint_align_set (_candidate_table, 0.0, 0.0);
3301 elm_table_padding_set (_candidate_table, 0, 0);
3302 elm_object_content_set (_candidate_scroll, _candidate_table);
3303 evas_object_show (_candidate_table);
3304 _candidate_area_2 = _candidate_scroll;
3305 evas_object_smart_callback_add (_candidate_scroll, "scroll,anim,stop", ui_candidate_scroller_stop_cb, NULL);
3307 /* Create close button */
3308 _close_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3309 if (_ise_width == 0 && _ise_height == 0)
3310 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
3312 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
3313 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
3314 evas_object_resize (_close_btn, _more_btn_width, _more_btn_height);
3315 evas_object_event_callback_add (_close_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_close_button_cb, NULL);
3317 _tmp_candidate_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3318 evas_object_text_font_set (_tmp_candidate_text, _candidate_font_name.c_str (), _candidate_font_size);
3321 _aux_area = elm_scroller_add (_candidate_window);
3322 elm_scroller_bounce_set (_aux_area, 1, 0);
3323 elm_scroller_policy_set (_aux_area, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3324 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
3325 evas_object_move (_aux_area, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3327 _aux_table = elm_table_add (_candidate_window);
3328 elm_object_content_set (_aux_area, _aux_table);
3329 elm_table_padding_set (_aux_table, 0, 0);
3330 evas_object_size_hint_weight_set (_aux_table, 0.0, 0.0);
3331 evas_object_size_hint_align_set (_aux_table, 0.0, 0.0);
3332 evas_object_show (_aux_table);
3334 _aux_line = edje_object_add (evas_object_evas_get (_candidate_window));
3335 edje_object_file_set (_aux_line, _candidate_edje_file.c_str (), "popup_line");
3336 evas_object_resize (_aux_line, _candidate_port_width, 2);
3337 evas_object_move (_aux_line, 0, _aux_height + 2);
3339 _tmp_aux_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3340 evas_object_text_font_set (_tmp_aux_text, _candidate_font_name.c_str (), _aux_font_size);
3342 evas_object_hide (_candidate_window);
3349 * @brief Create candidate window.
3353 static void ui_create_candidate_window (void)
3355 check_time ("\nEnter ui_create_candidate_window");
3356 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3357 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3362 _candidate_angle = 0;
3364 ui_create_native_candidate_window ();
3367 unsigned int set = 1;
3369 ecore_x_window_prop_card32_set (elm_win_xwindow_get (_candidate_window),
3370 ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
3373 int angle = efl_get_app_window_angle ();
3374 if (_candidate_angle != angle) {
3375 _candidate_angle = angle;
3376 ui_candidate_window_rotate (angle);
3378 ui_settle_candidate_window ();
3381 candidate_expanded = false;
3383 check_time ("Exit ui_create_candidate_window");
3387 * @brief Destroy candidate window.
3391 static void ui_destroy_candidate_window (void)
3393 check_time ("Enter ui_destroy_candidate_window");
3394 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3396 /* Delete candidate items, popup lines and seperator items */
3397 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3398 if (_candidate_0 [i]) {
3399 evas_object_del (_candidate_0 [i]);
3400 _candidate_0 [i] = NULL;
3402 if (_seperate_0 [i]) {
3403 evas_object_del (_seperate_0 [i]);
3404 _seperate_0 [i] = NULL;
3406 if (_seperate_items [i]) {
3407 evas_object_del (_seperate_items [i]);
3408 _seperate_items [i] = NULL;
3411 evas_object_del (_line_0 [i]);
3414 if (_line_items [i]) {
3415 evas_object_del (_line_items [i]);
3416 _line_items [i] = NULL;
3420 _aux_items.clear ();
3421 _aux_seperates.clear ();
3422 /* Delete candidate window */
3423 if (_candidate_window) {
3424 LOGD ("calling ui_candidate_hide (true)");
3425 ui_candidate_hide (true);
3427 evas_object_del (_candidate_window);
3428 _candidate_window = NULL;
3430 _candidate_area_1 = NULL;
3431 _candidate_area_2 = NULL;
3434 if (_tts_focus_rect) {
3435 evas_object_del (_tts_focus_rect);
3436 _tts_focus_rect = NULL;
3439 if (_candidate_bg) {
3440 evas_object_del (_candidate_bg);
3441 _candidate_bg = NULL;
3445 evas_object_del (_more_btn);
3450 evas_object_del (_scroller_bg);
3451 _scroller_bg = NULL;
3455 evas_object_del (_close_btn);
3460 evas_object_del (_aux_line);
3464 if (_tmp_candidate_text) {
3465 evas_object_del (_tmp_candidate_text);
3466 _tmp_candidate_text = NULL;
3469 if (_tmp_preedit_text) {
3470 evas_object_del (_tmp_preedit_text);
3471 _tmp_preedit_text = NULL;
3474 if (_tmp_aux_text) {
3475 evas_object_del (_tmp_aux_text);
3476 _tmp_aux_text = NULL;
3479 if (_preedit_text) {
3480 evas_object_del (_preedit_text);
3481 _preedit_text = NULL;
3484 if (_preedit_window) {
3485 evas_object_hide (_preedit_window);
3486 evas_object_del (_preedit_window);
3487 _preedit_window = NULL;
3491 check_time ("Exit ui_destroy_candidate_window");
3495 * @brief Settle candidate window position.
3497 static void ui_settle_candidate_window (void)
3499 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3501 if (!_candidate_window)
3504 /* If both ISE and candidate window are going to be hidden,
3505 let's just not move our candidate window */
3506 if (_ise_state == WINDOW_STATE_WILL_HIDE && _candidate_state == WINDOW_STATE_WILL_HIDE)
3510 int x, y, width, height;
3511 int ise_width = 0, ise_height = 0;
3512 bool get_geometry_result = false;
3514 /* Get candidate window position */
3515 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
3519 int pos_x = 0, pos_y = 0;
3520 if (_candidate_angle == 90 || _candidate_angle == 270)
3521 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_height, &ise_width);
3523 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_width, &ise_height);
3528 ise_width = _ise_width;
3529 ise_height = _ise_height;
3530 get_geometry_result = true;
3532 if ((_ise_state != WINDOW_STATE_SHOW && _ise_state != WINDOW_STATE_WILL_HIDE) ||
3533 (get_geometry_result == false) || (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
3538 int height2 = ui_candidate_get_valid_height ();
3540 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
3541 if (_candidate_angle == 90) {
3542 spot_x = _screen_width - ise_height - height2;
3544 } else if (_candidate_angle == 270) {
3545 spot_x = ise_height - (_candidate_height - height2);
3547 } else if (_candidate_angle == 180) {
3549 spot_y = ise_height - (_candidate_height - height2);
3552 spot_y = _screen_height - ise_height - height2;
3555 spot_x = _spot_location_x;
3556 spot_y = _spot_location_y;
3558 rectinfo ise_rect = {0, 0, (uint32)ise_width, (uint32)ise_height};
3559 if (_candidate_angle == 90 || _candidate_angle == 270) {
3560 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32)_screen_width)
3561 ise_rect.height = ISE_DEFAULT_HEIGHT_LANDSCAPE * _width_rate;
3563 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32) _screen_height)
3564 ise_rect.height = ISE_DEFAULT_HEIGHT_PORTRAIT * _height_rate;
3567 int nOffset = _candidate_port_height_min / 3;
3568 if (_candidate_angle == 270) {
3569 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3570 spot_x = _screen_width - _spot_location_top_y - (_candidate_height - height2);
3572 spot_x = _screen_width - _spot_location_y - _candidate_height;
3574 } else if (_candidate_angle == 90) {
3575 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3576 spot_x = _spot_location_top_y - height2;
3580 } else if (_candidate_angle == 180) {
3581 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3582 spot_y = _screen_height - _spot_location_top_y - (_candidate_height - height2);
3584 spot_y = _screen_height - _spot_location_y - _candidate_height;
3587 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3588 spot_y = _spot_location_top_y - height2;
3593 if (_candidate_angle == 90) {
3594 spot_y = (_screen_height - _candidate_width) / 2;
3595 spot_x = spot_x < _indicator_height ? _indicator_height : spot_x;
3596 if (spot_x > _screen_width - _candidate_height)
3597 spot_x = _screen_width - _candidate_height;
3598 } else if (_candidate_angle == 270) {
3599 spot_y = (_screen_height - _candidate_width) / 2;
3600 spot_x = spot_x < 0 ? 0 : spot_x;
3601 if (spot_x > _screen_width - (_indicator_height+_candidate_height))
3602 spot_x = _screen_width - (_indicator_height+_candidate_height);
3603 } else if (_candidate_angle == 180) {
3604 spot_x = (_screen_width - _candidate_width) / 2;
3605 spot_y = spot_y < 0 ? 0 : spot_y;
3606 if (spot_y > _screen_height - (_indicator_height+_candidate_height))
3607 spot_y = _screen_height - (_indicator_height+_candidate_height);
3609 spot_x = (_screen_width - _candidate_width) / 2;
3610 spot_y = spot_y < _indicator_height ? _indicator_height : spot_y;
3611 if (spot_y > _screen_height - _candidate_height)
3612 spot_y = _screen_height - _candidate_height;
3615 if (spot_x != x || spot_y != y) {
3616 _candidate_x = spot_x;
3617 _candidate_y = spot_y;
3618 evas_object_move (_candidate_window, spot_x, spot_y);
3619 LOGD ("Moving candidate window to : %d %d", spot_x, spot_y);
3620 if (_preedit_window) {
3621 if (_candidate_angle == 90) {
3622 spot_x -= _preedit_height;
3623 spot_y = _screen_height - _preedit_width;
3624 } else if (_candidate_angle == 270) {
3626 } else if (_candidate_angle == 180) {
3627 spot_x = _screen_width - _preedit_width;
3630 spot_y -= _preedit_height;
3632 evas_object_move (_preedit_window, spot_x, spot_y);
3634 if (_candidate_state == WINDOW_STATE_SHOW) {
3635 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
3639 #endif /* CANDIDATE */
3642 * @brief Set soft candidate geometry.
3644 * @param x The x position in screen.
3645 * @param y The y position in screen.
3646 * @param width The candidate window width.
3647 * @param height The candidate window height.
3649 static void set_soft_candidate_geometry (int x, int y, int width, int height)
3651 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
3653 LOGD ("candidate geometry x: %d , y: %d , width: %d , height: %d, _ise_state: %d, candidate_mode: %d", x, y, width, height, _ise_state, _candidate_mode);
3655 if ((_candidate_mode != SOFT_CANDIDATE_WINDOW) || (_info_manager->get_current_toolbar_mode () != TOOLBAR_KEYBOARD_MODE))
3659 _soft_candidate_width = width;
3660 _soft_candidate_height = height;
3661 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry());
3663 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
3666 #if ISF_BUILD_CANDIDATE_UI
3667 //////////////////////////////////////////////////////////////////////
3668 // End of Candidate Functions
3669 //////////////////////////////////////////////////////////////////////
3672 * @brief Set transient for app window.
3674 * @param window The Ecore_X_Window handler of app window.
3676 static void efl_set_transient_for_app_window (Ecore_X_Window window)
3678 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3680 /* Set a transient window for window stack */
3681 Ecore_X_Window xAppWindow = efl_get_app_window ();
3682 ecore_x_icccm_transient_for_set (window, xAppWindow);
3684 LOGD ("win : %x, forwin : %x", window, xAppWindow);
3687 static int efl_get_window_rotate_angle (Ecore_X_Window win)
3689 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3694 unsigned char *prop_data = NULL;
3696 ret = ecore_x_window_prop_property_get (win,
3697 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
3698 if (ret && prop_data) {
3699 memcpy (&angle, prop_data, sizeof (int));
3700 LOGD ("WINDOW angle of %p is %d", win, angle);
3702 std::cerr << "ecore_x_window_prop_property_get () is failed!!!\n";
3703 LOGW ("WINDOW angle of %p FAILED!", win);
3710 #endif /* HAVE_ECOREX */
3713 * @brief Get angle for app window.
3715 * @param win_obj The Evas_Object handler of application window.
3717 * @return The angle of app window.
3719 static int efl_get_app_window_angle ()
3721 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3723 return efl_get_window_rotate_angle (efl_get_app_window ());
3729 #endif /* CANDIDATE */
3732 * @brief Get angle for ise window.
3734 * @param win_obj The Evas_Object handler of ise window.
3736 * @return The angle of ise window.
3738 static int efl_get_ise_window_angle ()
3740 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3742 return efl_get_window_rotate_angle (_ise_window);
3749 #if ISF_BUILD_CANDIDATE_UI
3752 * @brief Get angle of quickpanel window.
3754 * @return The angle of quickpanel window.
3756 static int efl_get_quickpanel_window_angle ()
3758 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3759 return efl_get_window_rotate_angle (efl_get_quickpanel_window ());
3764 * @brief Set showing effect for application window.
3766 * @param win The Evas_Object handler of application window.
3767 * @param strEffect The pointer of effect string.
3769 static void efl_set_showing_effect_for_app_window (Evas_Object *win, const char* strEffect)
3771 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3773 ecore_x_icccm_name_class_set (elm_win_xwindow_get (static_cast<Evas_Object*>(win)), strEffect, "ISF");
3778 * @brief Create elementary window.
3780 * @param strWinName The window name.
3781 * @param strEffect The window effect string.
3783 * @return The window pointer
3785 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect)
3787 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3789 Evas_Object *win = elm_win_add (NULL, strWinName, ELM_WIN_UTILITY);
3790 elm_win_title_set (win, strWinName);
3792 /* set window properties */
3793 elm_win_autodel_set (win, EINA_TRUE);
3794 elm_object_focus_allow_set (win, EINA_FALSE);
3795 elm_win_borderless_set (win, EINA_TRUE);
3796 elm_win_alpha_set (win, EINA_TRUE);
3797 elm_win_prop_focus_skip_set (win, EINA_TRUE);
3798 efl_set_showing_effect_for_app_window (win, strEffect);
3802 #endif /* CANDIDATE */
3806 * @brief Create elementary control window.
3808 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3810 static Eina_Bool efl_create_control_window (void)
3812 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3814 /* WMSYNC, #1 Creating and registering control window */
3815 if (ecore_x_display_get () == NULL)
3818 Ecore_X_Window root = ecore_x_window_root_first_get ();
3819 _control_window = ecore_x_window_input_new (root, -100, -100, 1, 1);
3820 //ecore_x_e_virtual_keyboard_control_window_set (root, _control_window, 0, EINA_TRUE);
3822 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_CONTROL_WINDOW");
3823 ecore_x_window_prop_xid_set (root, atom, ECORE_X_ATOM_WINDOW, &_control_window, 1);
3829 * @brief Get an window's x window id.
3831 * @param name the property name.
3832 * @return X window id.
3834 static Ecore_X_Window efl_get_window (const char *name)
3836 /* Gets the XID of the window from the root window property */
3840 unsigned long nitems_return;
3841 unsigned long bytes_after_return;
3842 unsigned char *data = NULL;
3843 Ecore_X_Window window = 0;
3845 ret = XGetWindowProperty ((Display *)ecore_x_display_get (),
3846 ecore_x_window_root_get (_control_window),
3847 ecore_x_atom_get (name),
3848 0, G_MAXLONG, False, XA_WINDOW, &type_return,
3849 &format_return, &nitems_return, &bytes_after_return,
3852 if (ret == Success) {
3853 if ((type_return == XA_WINDOW) && (format_return == 32) && (data)) {
3854 window = *(Window *)data;
3857 std::cerr << "XGetWindowProperty () is failed!!!\n";
3867 * @brief Get app window's x window id.
3869 * @return the X window id of application to have focus or to request to show IME.
3871 static Ecore_X_Window efl_get_app_window (void)
3873 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3875 return efl_get_window ("_ISF_ACTIVE_WINDOW");
3879 * @brief Get clipboard window's x window id.
3881 * @return the X window id of clipboard.
3883 static Ecore_X_Window efl_get_clipboard_window (void)
3885 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3887 return efl_get_window ("CBHM_ELM_WIN");
3891 * @brief Get global navigation window's x window id.
3893 * @return the X window id of global navigation.
3895 static Ecore_X_Window efl_get_global_navigation_window (void)
3897 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3899 return efl_get_window ("GNB_WIN");
3903 * @brief Get app window's x window id.
3905 * @return the X window id of quick panel.
3907 static Ecore_X_Window efl_get_quickpanel_window (void)
3909 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3911 Ecore_X_Window rootWin = ecore_x_window_root_first_get ();
3912 Ecore_X_Window qpwin;
3913 ecore_x_window_prop_xid_get (rootWin, ecore_x_atom_get ("_E_ILLUME_QUICKPANEL_WINDOW_LIST"), ECORE_X_ATOM_WINDOW, &qpwin, 1);
3919 * @brief Get default zone geometry.
3921 * @param x The zone x position.
3922 * @param y The zone y position.
3923 * @param w The zone width.
3924 * @param h The zone height.
3926 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3928 static Eina_Bool efl_get_default_zone_geometry_info (Ecore_X_Window root, uint *x, uint *y, uint *w, uint *h)
3930 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3932 Ecore_X_Atom zone_geometry_atom;
3933 Ecore_X_Window *zone_lists;
3938 zone_geometry_atom = ecore_x_atom_get ("_E_ILLUME_ZONE_GEOMETRY");
3939 if (!zone_geometry_atom) {
3945 num_zone_lists = ecore_x_window_prop_window_list_get (root, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, &zone_lists);
3946 if (num_zone_lists > 0) {
3947 num_ret = ecore_x_window_prop_card32_get (zone_lists[0], zone_geometry_atom, geom, 4);
3949 if (x) *x = geom[0];
3950 if (y) *y = geom[1];
3951 if (w) *w = geom[2];
3952 if (h) *h = geom[3];
3958 /* if there is no zone available */
3963 /* We must free zone_lists */
3969 #endif /* HAVE_ECOREX */
3971 #if ISF_BUILD_CANDIDATE_UI
3973 * @brief Get screen resolution.
3975 * @param width The screen width.
3976 * @param height The screen height.
3978 static void efl_get_screen_resolution (int &width, int &height)
3980 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3982 static Evas_Coord scr_w = 0, scr_h = 0;
3983 if (scr_w == 0 || scr_h == 0) {
3986 if (efl_get_default_zone_geometry_info (ecore_x_window_root_first_get (), NULL, NULL, &w, &h)) {
3990 ecore_x_window_size_get (ecore_x_window_root_first_get (), &scr_w, &scr_h);
3993 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3995 ecore_wl2_display_screen_size_get(wl2_display, &scr_w, &scr_h);
4002 #endif /* CANDIDATE */
4004 //////////////////////////////////////////////////////////////////////
4005 // Start of PanelAgent Functions
4006 //////////////////////////////////////////////////////////////////////
4009 * @brief Initialize panel agent.
4011 * @param config The config string for PanelAgent.
4012 * @param display The current display.
4013 * @param resident The variable indicates whether panel will be resident.
4015 * @return true if initialize is successful, otherwise return false.
4017 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident)
4019 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4021 LOGD ("initializing panel agent");
4023 _info_manager = new InfoManager ();
4025 if (!_info_manager || !_info_manager->initialize (_info_manager, config, display, resident)) {
4026 ISF_SAVE_LOG ("panel_agent initialize fail!");
4030 _info_manager->signal_connect_focus_in (slot (slot_focus_in));
4031 _info_manager->signal_connect_focus_out (slot (slot_focus_out));
4032 _info_manager->signal_connect_expand_candidate (slot (slot_expand_candidate));
4033 _info_manager->signal_connect_contract_candidate (slot (slot_contract_candidate));
4034 _info_manager->signal_connect_set_candidate_ui (slot (slot_set_candidate_style));
4035 _info_manager->signal_connect_update_factory_info (slot (slot_update_factory_info));
4036 _info_manager->signal_connect_update_spot_location (slot (slot_update_spot_location));
4037 _info_manager->signal_connect_update_input_context (slot (slot_update_input_context));
4038 _info_manager->signal_connect_update_ise_geometry (slot (slot_update_ise_geometry));
4039 #if ISF_BUILD_CANDIDATE_UI
4040 _info_manager->signal_connect_show_preedit_string (slot (slot_show_preedit_string));
4041 _info_manager->signal_connect_show_aux_string (slot (slot_show_aux_string));
4043 _info_manager->signal_connect_show_lookup_table (slot (slot_show_candidate_table));
4044 _info_manager->signal_connect_hide_preedit_string (slot (slot_hide_preedit_string));
4045 _info_manager->signal_connect_hide_aux_string (slot (slot_hide_aux_string));
4046 _info_manager->signal_connect_hide_lookup_table (slot (slot_hide_candidate_table));
4047 _info_manager->signal_connect_update_preedit_string (slot (slot_update_preedit_string));
4048 _info_manager->signal_connect_update_preedit_caret (slot (slot_update_preedit_caret));
4049 _info_manager->signal_connect_update_aux_string (slot (slot_update_aux_string));
4050 _info_manager->signal_connect_update_lookup_table (slot (slot_update_candidate_table));
4051 _info_manager->signal_connect_select_candidate (slot (slot_select_candidate));
4052 _info_manager->signal_connect_get_candidate_geometry (slot (slot_get_candidate_geometry));
4053 _info_manager->signal_connect_get_input_panel_geometry (slot (slot_get_input_panel_geometry));
4054 _info_manager->signal_connect_set_active_ise_by_uuid (slot (slot_set_active_ise));
4055 _info_manager->signal_connect_get_ise_list (slot (slot_get_ise_list));
4056 _info_manager->signal_connect_get_all_helper_ise_info (slot (slot_get_all_helper_ise_info));
4057 _info_manager->signal_connect_set_has_option_helper_ise_info(slot (slot_set_has_option_helper_ise_info));
4058 _info_manager->signal_connect_set_enable_helper_ise_info (slot (slot_set_enable_helper_ise_info));
4059 _info_manager->signal_connect_show_helper_ise_list (slot (slot_show_helper_ise_list));
4060 _info_manager->signal_connect_show_helper_ise_selector (slot (slot_show_helper_ise_selector));
4061 _info_manager->signal_connect_is_helper_ise_enabled (slot (slot_is_helper_ise_enabled));
4062 _info_manager->signal_connect_get_ise_information (slot (slot_get_ise_information));
4063 _info_manager->signal_connect_get_keyboard_ise_list (slot (slot_get_keyboard_ise_list));
4064 _info_manager->signal_connect_get_language_list (slot (slot_get_language_list));
4065 _info_manager->signal_connect_get_all_language (slot (slot_get_all_language));
4066 _info_manager->signal_connect_get_ise_language (slot (slot_get_ise_language));
4067 _info_manager->signal_connect_get_ise_info_by_uuid (slot (slot_get_ise_info));
4068 _info_manager->signal_connect_set_keyboard_ise (slot (slot_set_keyboard_ise));
4069 _info_manager->signal_connect_get_keyboard_ise (slot (slot_get_keyboard_ise));
4070 _info_manager->signal_connect_accept_connection (slot (slot_accept_connection));
4071 _info_manager->signal_connect_close_connection (slot (slot_close_connection));
4072 _info_manager->signal_connect_exit (slot (slot_exit));
4074 _info_manager->signal_connect_register_helper (slot(slot_register_helper));
4075 _info_manager->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
4076 _info_manager->signal_connect_show_ise (slot (slot_show_ise));
4077 _info_manager->signal_connect_hide_ise (slot (slot_hide_ise));
4079 _info_manager->signal_connect_will_hide_ack (slot (slot_will_hide_ack));
4081 _info_manager->signal_connect_set_keyboard_mode (slot (slot_set_keyboard_mode));
4083 _info_manager->signal_connect_candidate_will_hide_ack (slot (slot_candidate_will_hide_ack));
4084 _info_manager->signal_connect_get_ise_state (slot (slot_get_ise_state));
4085 _info_manager->signal_connect_start_default_ise (slot (slot_start_default_ise));
4086 _info_manager->signal_connect_stop_default_ise (slot (slot_stop_default_ise));
4087 _info_manager->signal_connect_show_panel (slot (slot_show_helper_ise_selector));
4088 #if ENABLE_REMOTE_INPUT
4089 _info_manager->signal_connect_remoteinput_send_input_message(slot (slot_send_remote_input_message));
4090 _info_manager->signal_connect_remoteinput_send_surrounding_text(slot (slot_recv_remote_surrounding_text));
4092 _info_manager->signal_connect_get_recent_ise_geometry (slot (slot_get_recent_ise_geometry));
4093 _info_manager->signal_connect_check_privilege_by_sockfd (slot (slot_check_privilege_by_sockfd));
4095 _info_manager->signal_connect_run_helper (slot (slot_run_helper));
4096 _info_manager->signal_connect_launch_option_application (slot (slot_launch_option_application));
4097 _info_manager->signal_connect_get_ise_setting_appid (slot (slot_get_ise_setting_appid));
4098 _info_manager->signal_connect_set_preloading_ise (slot (slot_set_preloading_ise));
4100 LOGD ("initializing panel agent succeeded");
4105 static void delete_ise_hide_timer (void)
4107 LOGD ("deleting ise_hide_timer");
4108 if (_ise_hide_timer) {
4109 ecore_timer_del (_ise_hide_timer);
4110 _ise_hide_timer = NULL;
4114 static void hide_ise ()
4116 LOGD ("send request to hide helper");
4117 String uuid = _info_manager->get_current_helper_uuid ();
4118 _info_manager->hide_helper (uuid);
4120 /* Only if we are not already in HIDE state */
4121 if (_ise_state != WINDOW_STATE_HIDE) {
4122 /* From this point, slot_get_input_panel_geometry should return hidden state geometry */
4123 _ise_state = WINDOW_STATE_WILL_HIDE;
4125 _updated_hide_state_geometry = false;
4129 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
4131 #if ISF_BUILD_CANDIDATE_UI
4132 if (_candidate_window) {
4133 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)
4134 ui_candidate_hide (true, true, true);
4136 ui_candidate_hide (true, false, true);
4138 #endif /* CANDIDATE */
4141 #ifdef HAVE_NOTIFICATION
4142 delete_notification (&ise_selector_module_noti);
4147 #if ENABLE_MULTIWINDOW_SUPPORT
4148 static Eina_Bool ise_hide_timeout (void *data)
4150 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4152 delete_ise_hide_timer ();
4155 return ECORE_CALLBACK_CANCEL;
4160 * @brief Insert data to ime_info table.
4162 * @param list The list to store uuid
4164 * @return true if it is successful, otherwise return false.
4166 static bool update_ise_list (std::vector<String> &list)
4168 std::vector<String> uuids;
4169 std::vector<TOOLBAR_MODE_T> modes;
4170 std::vector<ImeInfoDB>::iterator iter;
4173 if (_ime_info.size() == 0) {
4174 if (isf_pkg_select_all_ime_info_db(_ime_info) == 0)
4178 /* Update _groups */
4180 std::vector<String> ise_langs;
4181 for (size_t i = 0; i < _ime_info.size (); ++i) {
4182 scim_split_string_list(ise_langs, _ime_info[i].languages);
4183 for (size_t j = 0; j < ise_langs.size (); j++) {
4184 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
4185 _groups[ise_langs[j]].push_back (i);
4190 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
4191 uuids.push_back(iter->appid);
4192 modes.push_back(iter->mode);
4195 if (uuids.size() > 0) {
4199 _info_manager->update_ise_list (list);
4201 if (_initial_ise_uuid.length () > 0) {
4202 String active_uuid = _initial_ise_uuid;
4203 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
4204 if (std::find (uuids.begin (), uuids.end (), default_uuid) == uuids.end ()) {
4205 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (modes[get_ise_index (_initial_ise_uuid)] != TOOLBAR_KEYBOARD_MODE)) {
4206 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4209 if (set_active_ise (active_uuid, _soft_keyboard_launched) == false) {
4210 if (_initial_ise_uuid.compare (active_uuid)) {
4211 LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
4212 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
4215 } else if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) { // Check whether keyboard engine is installed
4216 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
4217 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
4218 if (std::find (uuids.begin (), uuids.end (), keyboard_uuid) == uuids.end ()) {
4219 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4220 _info_manager->change_factory (active_uuid);
4221 _config->write (IMENGINE_KEY, active_uuid);
4228 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
4230 if (_ime_info.size () > 0 && _ime_info[0].display_lang.compare(lang_str) == 0)
4231 _locale_string = String (lang_str);
4237 LOGW ("No IME list");
4239 #ifdef HAVE_PKGMGR_INFO
4241 int ret = package_manager_create (&pkgmgr);
4242 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4243 ret = package_manager_set_event_cb (pkgmgr, _package_manager_event_cb, NULL);
4244 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4245 LOGD ("package_manager_set_event_cb succeeded.");
4248 LOGE ("package_manager_set_event_cb failed(%d)", ret);
4252 LOGE ("package_manager_create failed(%d)", ret);
4261 * @brief Focus in slot function for PanelAgent.
4263 static void slot_focus_in (void)
4265 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4268 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
4269 if (_launch_ise_on_request && !_soft_keyboard_launched) {
4270 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
4271 if (uuid.length () > 0 && (_ime_info[get_ise_index(uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
4272 LOGD ("Start helper (%s)", uuid.c_str ());
4274 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
4275 if (_info_manager->start_helper (uuid))
4276 _soft_keyboard_launched = true;
4281 #if ISF_BUILD_CANDIDATE_UI
4282 ui_candidate_delete_destroy_timer ();
4283 #endif /* CANDIDATE */
4287 * @brief Focus out slot function for PanelAgent.
4289 static void slot_focus_out (void)
4291 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4295 #if ISF_BUILD_CANDIDATE_UI
4296 ui_candidate_delete_destroy_timer ();
4297 _destroy_timer = ecore_timer_add (ISF_CANDIDATE_DESTROY_DELAY, ui_candidate_destroy_timeout, NULL);
4298 #endif /* CANDIDATE */
4302 * @brief Expand candidate slot function for PanelAgent.
4304 static void slot_expand_candidate (void)
4306 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4307 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4310 #if ISF_BUILD_CANDIDATE_UI
4311 if (_candidate_area_2 && !_candidate_area_2_visible)
4312 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
4313 #endif /* CANDIDATE */
4317 * @brief Contract candidate slot function for PanelAgent.
4319 static void slot_contract_candidate (void)
4321 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4323 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4326 #if ISF_BUILD_CANDIDATE_UI
4327 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
4328 #endif /* CANDIDATE */
4332 * @brief Set candidate style slot function for PanelAgent.
4334 * @param portrait_line The displayed line number for portrait.
4335 * @param mode The candidate mode.
4337 static void slot_set_candidate_style (int portrait_line, int mode)
4339 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " display_line:" << portrait_line << " mode:" << mode << "\n";
4340 #if ISF_BUILD_CANDIDATE_UI
4341 if ((portrait_line != _candidate_port_line) || (mode != _candidate_mode)) {
4342 _candidate_mode = (ISF_CANDIDATE_MODE_T)mode;
4343 _candidate_port_line = (ISF_CANDIDATE_PORTRAIT_LINE_T)portrait_line;
4344 _soft_candidate_width = 0;
4345 _soft_candidate_height = 0;
4347 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4348 if (_candidate_window)
4349 ui_destroy_candidate_window ();
4354 if (_candidate_window)
4355 ui_create_candidate_window ();
4357 #endif /* CANDIDATE */
4360 #if defined(HAVE_NOTIFICATION) || defined(HAVE_ECOREX)
4361 static unsigned int get_ise_count (TOOLBAR_MODE_T mode, bool valid_helper)
4363 unsigned int ise_count = 0;
4364 for (unsigned int i = 0; i < _ime_info.size (); i++) {
4365 if (mode == _ime_info[i].mode) {
4366 if (mode == TOOLBAR_KEYBOARD_MODE || !valid_helper)
4368 else if (_ime_info[i].is_enabled)
4378 * @brief Update keyboard ISE information slot function for PanelAgent.
4380 * @param info The information of current Keyboard ISE.
4382 static void slot_update_factory_info (const PanelFactoryInfo &info)
4384 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4386 String ise_name = info.name;
4388 String old_ise = _info_manager->get_current_ise_name ();
4389 #if ISF_BUILD_CANDIDATE_UI
4390 if (old_ise != ise_name) {
4391 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && _candidate_window) {
4392 ui_destroy_candidate_window ();
4395 #endif /* CANDIDATE */
4397 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
4399 if (TOOLBAR_HELPER_MODE == mode)
4400 ise_name = _ime_info[get_ise_index (_info_manager->get_current_helper_uuid())].label;
4402 if (ise_name.length () > 0)
4403 _info_manager->set_current_ise_name (ise_name);
4405 #ifdef HAVE_NOTIFICATION
4406 if (_MOBILE || _COMMON) {
4407 if (old_ise != ise_name) {
4408 if (TOOLBAR_KEYBOARD_MODE == mode) {
4409 char noti_msg[256] = {0};
4410 unsigned int keyboard_ise_count = get_ise_count (TOOLBAR_KEYBOARD_MODE, false);
4411 if (keyboard_ise_count == 0) {
4412 LOGD ("the number of keyboard ise is %d", keyboard_ise_count);
4415 else if (keyboard_ise_count >= 2) {
4416 snprintf (noti_msg, sizeof (noti_msg), _("%s selected"), ise_name.c_str ());
4418 else if (keyboard_ise_count == 1) {
4419 snprintf (noti_msg, sizeof (noti_msg), _("Only %s available"), ise_name.c_str ());
4422 notification_status_message_post (noti_msg);
4423 LOGD ("%s", noti_msg);
4431 * @brief Update cursor position slot function for PanelAgent.
4433 * @param x The x position of current cursor.
4434 * @param y The bottom y position of current cursor.
4435 * @param top_y The top y position of current cursor.
4437 static void slot_update_spot_location (int x, int y, int top_y)
4439 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4441 #if ISF_BUILD_CANDIDATE_UI
4442 if (x >= 0 && x < _screen_height && y >= 0 && y < _screen_height) {
4443 _spot_location_x = x;
4444 _spot_location_y = y;
4445 _spot_location_top_y = top_y;
4447 ui_settle_candidate_window ();
4449 #endif /* CANDIDATE */
4453 * @brief The input context of ISE is changed.
4455 * @param type The event type.
4456 * @param value The event value.
4458 static void slot_update_input_context (int type, int value)
4463 * @brief Update ise geometry.
4465 * @param x The x position in screen.
4466 * @param y The y position in screen.
4467 * @param width The ISE window width.
4468 * @param height The ISE window height.
4470 static void slot_update_ise_geometry (int x, int y, int width, int height)
4472 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
4474 LOGD ("x : %d , y : %d , width : %d , height : %d, _ise_state : %d", x, y, width, height, _ise_state);
4476 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
4477 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4478 /*IF ISE sent the ise_geometry information when the current_keyboard_mode is H/W mode and candidate_mode is SOFT_CANDIDATE,
4479 It means that given geometry information is for the candidate window */
4480 set_soft_candidate_geometry (x, y, width, height);
4488 #if ISF_BUILD_CANDIDATE_UI
4490 _ise_height = height;
4492 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
4493 ui_settle_candidate_window ();
4495 #endif /* CANDIDATE */
4497 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
4498 _ise_reported_geometry.valid = true;
4499 _ise_reported_geometry.angle = efl_get_ise_window_angle ();
4500 _ise_reported_geometry.geometry.pos_x = x;
4501 _ise_reported_geometry.geometry.pos_y = y;
4502 _ise_reported_geometry.geometry.width = width;
4503 _ise_reported_geometry.geometry.height = height;
4504 if (_ise_state == WINDOW_STATE_SHOW) {
4506 set_keyboard_geometry_atom_info (_app_window, _ise_reported_geometry.geometry);
4508 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
4513 #if ISF_BUILD_CANDIDATE_UI
4515 * @brief Show preedit slot function for PanelAgent.
4517 static void slot_show_preedit_string (void)
4519 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4521 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4524 if (_preedit_window == NULL) {
4525 ui_create_preedit_window ();
4527 /* Move preedit window according to candidate window position */
4528 if (_candidate_window) {
4529 /* Get candidate window position */
4530 int x, y, width, height;
4531 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
4533 int height2 = ui_candidate_get_valid_height ();
4534 int angle = efl_get_app_window_angle ();
4537 x -= _preedit_height;
4538 y = _screen_height - _preedit_width;
4539 } else if (_candidate_angle == 270) {
4541 } else if (_candidate_angle == 180) {
4542 x = _screen_width - _preedit_width;
4545 y -= _preedit_height;
4548 if (_preedit_window)
4549 evas_object_move (_preedit_window, x, y);
4553 if (_preedit_window && evas_object_visible_get (_preedit_window))
4556 slot_show_candidate_table ();
4558 if (_preedit_window)
4559 evas_object_show (_preedit_window);
4563 * @brief Show aux slot function for PanelAgent.
4565 static void slot_show_aux_string (void)
4567 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4569 if (_candidate_window == NULL)
4570 ui_create_candidate_window ();
4572 if (_aux_area == NULL || _aux_area_visible)
4575 evas_object_show (_aux_area);
4576 _aux_area_visible = true;
4577 ui_candidate_window_adjust ();
4579 LOGD ("calling ui_candidate_show ()");
4580 ui_candidate_show ();
4581 ui_settle_candidate_window ();
4582 ui_candidate_delete_destroy_timer ();
4585 #endif /* CANDIDATE */
4588 * @brief Show candidate table slot function for PanelAgent.
4590 static void slot_show_candidate_table (void)
4592 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4593 _info_manager->helper_candidate_show ();
4597 #if ISF_BUILD_CANDIDATE_UI
4598 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4599 if (_candidate_window == NULL)
4600 ui_create_candidate_window ();
4603 if (_candidate_state == WINDOW_STATE_SHOW &&
4604 (_candidate_area_1_visible || _candidate_area_2_visible)) {
4605 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
4610 evas_object_show (_candidate_area_1);
4611 _candidate_area_1_visible = true;
4612 ui_candidate_window_adjust ();
4614 LOGD ("calling ui_candidate_show ()");
4615 ui_candidate_show ();
4616 ui_settle_candidate_window ();
4617 ui_candidate_delete_destroy_timer ();
4619 #ifdef HAVE_FEEDBACK
4620 int feedback_result = feedback_initialize ();
4622 if (FEEDBACK_ERROR_NONE == feedback_result) {
4623 LOGD ("Feedback initialize successful");
4624 feedback_initialized = true;
4626 LOGW ("Feedback initialize fail : %d", feedback_result);
4627 feedback_initialized = false;
4629 #endif /* HAVE_FEEDBACK */
4630 #endif /* CANDIDATE */
4634 * @brief Hide preedit slot function for PanelAgent.
4636 static void slot_hide_preedit_string (void)
4638 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4640 #if ISF_BUILD_CANDIDATE_UI
4641 if (!_preedit_window || !evas_object_visible_get (_preedit_window))
4644 evas_object_hide (_preedit_window);
4645 #endif /* CANDIDATE */
4649 * @brief Hide aux slot function for PanelAgent.
4651 static void slot_hide_aux_string (void)
4653 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4655 #if ISF_BUILD_CANDIDATE_UI
4656 if (!_aux_area || !_aux_area_visible)
4659 evas_object_hide (_aux_area);
4660 _aux_area_visible = false;
4661 elm_scroller_region_show (_aux_area, 0, 0, 10, 10);
4662 ui_candidate_window_adjust ();
4664 LOGD ("calling ui_candidate_hide (false, true, true)");
4665 ui_candidate_hide (false, true, true);
4666 ui_settle_candidate_window ();
4668 if (ui_candidate_can_be_hide ()) {
4669 _candidate_show_requested = false;
4670 LOGD ("setting _show_candidate_requested to FALSE");
4672 #endif /* CANDIDATE */
4676 * @brief Hide candidate table slot function for PanelAgent.
4678 static void slot_hide_candidate_table (void)
4680 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4682 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4683 _info_manager->helper_candidate_hide ();
4687 #if ISF_BUILD_CANDIDATE_UI
4688 if (!_candidate_area_1 || _candidate_state == WINDOW_STATE_WILL_HIDE)
4691 if (_candidate_area_1_visible || _candidate_area_2_visible) {
4692 bool bForce = false;
4693 if (_candidate_area_1_visible) {
4694 if (_aux_area_visible) {
4695 evas_object_hide (_candidate_area_1);
4696 _candidate_area_1_visible = false;
4697 evas_object_hide (_more_btn);
4699 /* Let's not actually hide the _candidate_area_1 object, for the case that
4700 even if the application replies CANDIDATE_WILL_HIDE_ACK a little late,
4701 it is better to display the previous candidates instead of blank screen */
4702 _candidate_area_1_visible = false;
4706 if (_candidate_area_2_visible) {
4707 evas_object_hide (_candidate_area_2);
4708 _candidate_area_2_visible = false;
4709 evas_object_hide (_scroller_bg);
4710 evas_object_hide (_close_btn);
4711 _info_manager->candidate_more_window_hide ();
4713 ui_candidate_window_adjust ();
4715 LOGD ("calling ui_candidate_hide (%d, true, true)", bForce);
4716 ui_candidate_hide (bForce, true, true);
4717 ui_settle_candidate_window ();
4720 #ifdef HAVE_FEEDBACK
4721 int feedback_result = feedback_deinitialize ();
4723 if (FEEDBACK_ERROR_NONE == feedback_result)
4724 LOGD ("Feedback deinitialize successful");
4726 LOGW ("Feedback deinitialize fail : %d", feedback_result);
4728 feedback_initialized = false;
4731 if (ui_candidate_can_be_hide ()) {
4732 _candidate_show_requested = false;
4733 LOGD ("setting _show_candidate_requested to FALSE");
4735 #endif /* CANDIDATE */
4739 * @brief Update preedit slot function for PanelAgent.
4741 * @param str The new preedit string.
4742 * @param attrs The attribute list of new preedit string.
4744 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret)
4746 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " string=" << str << "\n";
4748 #if ISF_BUILD_CANDIDATE_UI
4749 if (str.length () <= 0)
4752 if (_preedit_window == NULL || !evas_object_visible_get (_preedit_window)) {
4753 slot_show_preedit_string ();
4756 int x, y, width, height, candidate_width;
4757 evas_object_text_text_set (_tmp_preedit_text, str.c_str ());
4758 evas_object_geometry_get (_tmp_preedit_text, &x, &y, &width, &height);
4759 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &candidate_width, &height);
4760 _preedit_width = (width + ISF_PREEDIT_BORDER * 2) < candidate_width ? (width + ISF_PREEDIT_BORDER * 2) : candidate_width;
4762 /* Resize preedit window and avoid text blink */
4763 int old_width, old_height;
4764 evas_object_geometry_get (_preedit_window, &x, &y, &old_width, &old_height);
4765 if (old_width < _preedit_width) {
4766 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4767 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4769 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4770 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4773 /* Move preedit window */
4774 if (_candidate_angle == 90 || _candidate_angle == 180) {
4775 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_preedit_window)), &x, &y, &width, &height);
4776 if (_candidate_angle == 90) {
4777 y = _screen_height - _preedit_width;
4778 } else if (_candidate_angle == 180) {
4779 x = _screen_width - _preedit_width;
4781 evas_object_move (_preedit_window, x, y);
4783 #endif /* CANDIDATE */
4787 * @brief Update caret slot function for PanelAgent.
4789 * @param caret The caret position.
4791 static void slot_update_preedit_caret (int caret)
4793 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " caret=" << caret << "\n";
4796 #if ISF_BUILD_CANDIDATE_UI
4798 * @brief Set highlight text color and background color for edje object.
4800 * @param item The edje object pointer.
4801 * @param nForeGround The text color.
4802 * @param nBackGround The background color.
4803 * @param bSetBack The flag for background color.
4805 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack)
4807 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4809 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
4810 if (edje_object_color_class_get (item, "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4811 r = SCIM_RGB_COLOR_RED (nForeGround);
4812 g = SCIM_RGB_COLOR_GREEN (nForeGround);
4813 b = SCIM_RGB_COLOR_BLUE (nForeGround);
4814 edje_object_color_class_set (item, "text_color", r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
4816 if (bSetBack && edje_object_color_class_get (item, "rect_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4817 r = SCIM_RGB_COLOR_RED (nBackGround);
4818 g = SCIM_RGB_COLOR_GREEN (nBackGround);
4819 b = SCIM_RGB_COLOR_BLUE (nBackGround);
4820 edje_object_color_class_set (item, "rect_color", r, g, b, 255, r2, g2, b2, a2, r3, g3, b3, a3);
4823 #endif /* CANDIDATE */
4826 * @brief Update aux slot function for PanelAgent.
4828 * @param str The new aux string.
4829 * @param attrs The attribute list of new aux string.
4831 static void slot_update_aux_string (const String &str, const AttributeList &attrs)
4833 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4834 #if ISF_BUILD_CANDIDATE_UI
4835 if (_candidate_window == NULL)
4836 ui_create_candidate_window ();
4838 if (!_aux_area || (str.length () <= 0))
4841 if (!_aux_area_visible) {
4842 LOGD ("calling ui_candidate_show ()");
4843 ui_candidate_show ();
4844 slot_show_aux_string ();
4847 int x, y, width, height, item_width = 0;
4848 unsigned int window_width = 0, count = 0, i;
4850 Evas_Object *aux_edje = NULL;
4852 /* Get highlight item index */
4853 int aux_index = -1, aux_start = 0, aux_end = 0;
4854 String strAux = str;
4855 bool bSetBack = false;
4856 uint32 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
4857 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
4858 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4859 if (aux_index == -1 && ait->get_type () == SCIM_ATTR_DECORATE) {
4860 aux_index = ait->get_value ();
4861 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
4862 nForeGround = ait->get_value ();
4863 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
4864 nBackGround = ait->get_value ();
4869 std::vector<String> aux_list;
4870 scim_split_string_list (aux_list, strAux, '|');
4872 if (_aux_items.size () > 0) {
4873 for (i = 0; i < _aux_items.size (); i++)
4874 evas_object_del (_aux_items [i]);
4875 _aux_items.clear ();
4877 if (_aux_seperates.size () > 0) {
4878 for (i = 0; i < _aux_seperates.size (); i++)
4879 evas_object_del (_aux_seperates [i]);
4880 _aux_seperates.clear ();
4883 int seperate_width = 4;
4884 int seperate_height = 52 * _height_rate;
4885 Evas *evas = evas_object_evas_get (_candidate_window);
4886 for (i = 0; i < aux_list.size (); i++) {
4888 Evas_Object *seperate_item = edje_object_add (evas);
4889 edje_object_file_set (seperate_item, _candidate_edje_file.c_str (), "seperate_line");
4890 evas_object_size_hint_min_set (seperate_item, seperate_width, seperate_height);
4891 elm_table_pack (_aux_table, seperate_item, 2 * i - 1, 0, 1, 1);
4892 evas_object_show (seperate_item);
4893 _aux_seperates.push_back (seperate_item);
4897 aux_edje = edje_object_add (evas);
4898 edje_object_file_set (aux_edje, _candidate_edje_file.c_str (), "aux");
4899 edje_object_part_text_set (aux_edje, "aux", aux_list [i].c_str ());
4900 edje_object_text_class_set (aux_edje, "tizen", _candidate_font_name.c_str (), _aux_font_size);
4901 elm_table_pack (_aux_table, aux_edje, 2 * i, 0, 1, 1);
4902 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_AUX));
4903 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
4904 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_AUX));
4905 evas_object_show (aux_edje);
4906 _aux_items.push_back (aux_edje);
4907 /* if (i == (unsigned int)aux_index)
4908 edje_object_signal_emit (aux_edje, "aux,state,selected", "aux");
4910 edje_object_signal_emit (aux_edje, "aux,state,unselected", "aux");
4912 evas_object_text_text_set (_tmp_aux_text, aux_list [i].c_str ());
4913 evas_object_geometry_get (_tmp_aux_text, &x, &y, &width, &height);
4914 item_width = width + 2*_blank_width;
4915 item_width = item_width > _item_min_width ? item_width : _item_min_width;
4916 evas_object_size_hint_min_set (aux_edje, item_width, _aux_height);
4917 if (aux_index == (int)i || (aux_index == -1 && i == 0)) {
4918 aux_start = window_width;
4919 aux_end = window_width + item_width;
4921 window_width = window_width + item_width + 4;
4924 // Set highlight item
4925 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4926 if (ait->get_type () == SCIM_ATTR_DECORATE) {
4927 unsigned int index = ait->get_value ();
4928 if (index < _aux_items.size ())
4929 set_highlight_color (_aux_items [index], nForeGround, nBackGround, bSetBack);
4934 elm_scroller_region_get (_aux_area, &x, &y, &w, &h);
4935 item_width = aux_end - aux_start;
4936 if (item_width > 0) {
4937 if (item_width >= w)
4938 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4939 else if (aux_end > x + w)
4940 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4941 else if (aux_start < x)
4942 elm_scroller_region_show (_aux_area, aux_start, y, w, h);
4945 #endif /* CANDIDATE */
4948 #if ISF_BUILD_CANDIDATE_UI
4950 * @brief Update candidate/associate table.
4952 * @param table_type The table type.
4953 * @param table The lookup table for candidate or associate.
4955 static void update_table (int table_type, const LookupTable &table)
4957 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << table.get_current_page_size () << ")\n";
4959 int item_num = table.get_current_page_size ();
4966 AttributeList attrs;
4967 int i, x, y, item_0_width = 0;
4971 int seperate_width = 2;
4972 int seperate_height = 52 * _height_rate;
4973 int line_width = _candidate_scroll_width;
4974 int line_height = _v_padding;
4975 int total_width = 0;
4976 int current_width = 0;
4979 int more_item_count = 0;
4980 int scroll_0_width = _candidate_scroll_0_width_min;
4981 int cursor_pos = table.get_cursor_pos ();
4982 int cursor_line = 0;
4984 if (_candidate_angle == 90 || _candidate_angle == 270)
4985 scroll_0_width = _screen_height - _more_btn_width - _h_padding;
4987 scroll_0_width = _screen_width - _more_btn_width - _h_padding;
4989 _candidate_image_count = 0;
4990 _candidate_text_count = 0;
4991 _candidate_pop_image_count = 0;
4992 _candidate_display_number = 0;
4993 _candidate_row_items.clear ();
4995 Evas *evas = evas_object_evas_get (_candidate_window);
4996 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
4997 if (_candidate_0 [i]) {
4998 evas_object_del (_candidate_0 [i]);
4999 _candidate_0 [i] = NULL;
5001 if (_seperate_0 [i]) {
5002 evas_object_del (_seperate_0 [i]);
5003 _seperate_0 [i] = NULL;
5005 if (_seperate_items [i]) {
5006 evas_object_del (_seperate_items [i]);
5007 _seperate_items [i] = NULL;
5010 evas_object_del (_line_0 [i]);
5013 if (_line_items [i]) {
5014 evas_object_del (_line_items [i]);
5015 _line_items [i] = NULL;
5019 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
5021 bool bHighLight = false;
5022 bool bSetBack = false;
5023 uint32 nForeGround = SCIM_RGB_COLOR (249, 249, 249);
5024 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
5025 attrs = table.get_attributes_in_current_page (i);
5026 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5027 if (ait->get_type () == SCIM_ATTR_DECORATE && ait->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
5029 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
5030 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
5032 nForeGround = ait->get_value ();
5033 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
5035 nBackGround = ait->get_value ();
5039 wcs = table.get_candidate_in_current_page (i);
5040 mbs = utf8_wcstombs (wcs);
5042 if (!_candidate_0 [i] && total_width <= scroll_0_width) {
5043 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5044 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));
5045 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5046 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_0));
5048 /* Check whether this item is the last one */
5049 if (i == item_num - 1) {
5050 if (_candidate_angle == 90 || _candidate_angle == 270)
5051 scroll_0_width = _candidate_land_width;
5053 scroll_0_width = _candidate_port_width;
5056 /* Add first item */
5058 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5059 evas_object_show (_candidate_0 [i]);
5060 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5061 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, 0, item_0_width, _item_min_height);
5062 total_width += item_0_width;
5063 _candidate_display_number++;
5066 total_width += (item_0_width + seperate_width);
5067 if (total_width <= scroll_0_width) {
5068 _seperate_0 [i] = edje_object_add (evas);
5069 edje_object_file_set (_seperate_0 [i], _candidate_edje_file.c_str (), "seperate_line");
5070 evas_object_size_hint_min_set (_seperate_0 [i], seperate_width, seperate_height);
5071 elm_table_pack (_candidate_0_table, _seperate_0 [i],
5072 total_width - item_0_width - seperate_width,
5073 line_0*(_item_min_height+line_height) + (_item_min_height - seperate_height)/2,
5074 seperate_width, seperate_height);
5075 evas_object_show (_seperate_0 [i]);
5076 evas_object_show (_candidate_0 [i]);
5077 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5078 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);
5079 _candidate_display_number++;
5081 } else if ((_candidate_angle == 0 || _candidate_angle == 180) &&
5082 (_candidate_port_line > 1 && (line_0 + 1) < _candidate_port_line)) {
5084 scroll_0_width = _candidate_scroll_0_width_min;
5085 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5086 evas_object_show (_candidate_0 [i]);
5087 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5088 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
5089 total_width = item_0_width;
5090 _candidate_display_number++;
5092 _candidate_row_items.push_back (i - nLast);
5096 _candidate_row_items.push_back (i - nLast);
5102 if (!_candidate_0 [i]) {
5103 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5104 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));
5105 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5106 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_ITEMS));
5108 if (current_width > 0 && current_width + item_0_width > _candidate_scroll_width) {
5112 _candidate_row_items.push_back (i - nLast);
5114 if (cursor_pos >= i)
5117 if (current_width == 0 && !_line_items [i]) {
5118 _line_items [i] = edje_object_add (evas);
5119 edje_object_file_set (_line_items [i], _candidate_edje_file.c_str (), "popup_line");
5120 evas_object_size_hint_min_set (_line_items [i], line_width, line_height);
5122 y = line_count*(_item_min_height+line_height);
5123 elm_table_pack (_candidate_table, _line_items [i], x, y, line_width, line_height);
5124 evas_object_show (_line_items [i]);
5126 if (current_width != 0 && !_seperate_items [i]) {
5127 _seperate_items [i] = edje_object_add (evas);
5128 edje_object_file_set (_seperate_items [i], _candidate_edje_file.c_str (), "seperate_line");
5129 evas_object_size_hint_min_set (_seperate_items [i], seperate_width, seperate_height);
5131 y = line_count*(_item_min_height+line_height) + line_height + (_item_min_height - seperate_height)/2;
5132 elm_table_pack (_candidate_table, _seperate_items [i], x, y, seperate_width, seperate_height);
5133 evas_object_show (_seperate_items [i]);
5134 current_width += seperate_width;
5137 y = line_count*(_item_min_height+line_height) + line_height;
5138 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5139 evas_object_show (_candidate_0 [i]);
5140 elm_table_pack (_candidate_table, _candidate_0 [i], x, y, item_0_width, _item_min_height);
5141 current_width += item_0_width;
5143 if (candidate_expanded == false && !bHighLight)
5146 candidate_expanded = true;
5150 for (i = 1; i < _candidate_port_line; i++) {
5151 if ((_candidate_angle == 0 || _candidate_angle == 180)) {
5152 if (_line_0 [i] == NULL) {
5153 _line_0 [i] = edje_object_add (evas);
5154 edje_object_file_set (_line_0 [i], _candidate_edje_file.c_str (), "popup_line");
5155 evas_object_size_hint_min_set (_line_0 [i], line_width, line_height);
5157 y = i * (_item_min_height + line_height) - line_height;
5158 elm_table_pack (_candidate_0_table, _line_0 [i], x, y, line_width, line_height);
5159 evas_object_show (_line_0 [i]);
5162 // Create blank line
5163 if (line_0 + 1 < _candidate_port_line && i > line_0) {
5164 int nIndex = item_num + i;
5165 nIndex = nIndex < SCIM_LOOKUP_TABLE_MAX_PAGESIZE ? nIndex : SCIM_LOOKUP_TABLE_MAX_PAGESIZE - 1;
5166 _seperate_0 [nIndex] = edje_object_add (evas);
5167 edje_object_file_set (_seperate_0 [nIndex], _candidate_edje_file.c_str (), "seperate_line");
5168 evas_object_size_hint_min_set (_seperate_0 [nIndex], seperate_width, _item_min_height);
5169 elm_table_pack (_candidate_0_table, _seperate_0 [nIndex],
5170 0, i*(_item_min_height+line_height), seperate_width, _item_min_height);
5172 } else if (_line_0 [i]) {
5173 evas_object_del (_line_0 [i]);
5178 _candidate_row_items.push_back (item_num - nLast); /* Add the number of last row */
5179 _info_manager->update_displayed_candidate_number (_candidate_display_number);
5180 _info_manager->update_candidate_item_layout (_candidate_row_items);
5181 if (more_item_count == 0) {
5182 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
5183 evas_object_hide (_more_btn);
5184 evas_object_hide (_close_btn);
5185 } else if (!_candidate_area_2_visible) {
5186 evas_object_show (_more_btn);
5187 evas_object_hide (_close_btn);
5189 evas_object_hide (_more_btn);
5190 evas_object_show (_close_btn);
5194 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
5196 int line_h = _item_min_height + _v_padding;
5197 int cursor_y = cursor_line * line_h;
5199 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
5200 } else if (cursor_y >= y + h) {
5201 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
5206 #endif /* CANDIDATE */
5209 * @brief Update candidate table slot function for PanelAgent.
5211 * @param table The lookup table for candidate.
5213 static void slot_update_candidate_table (const LookupTable &table)
5215 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5217 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5218 _info_manager->update_helper_lookup_table (table);
5222 #if ISF_BUILD_CANDIDATE_UI
5223 if (_candidate_window == NULL)
5224 ui_create_candidate_window ();
5226 if (!_candidate_window || table.get_current_page_size () < 0)
5229 if (evas_object_visible_get (_candidate_area_2)) {
5230 candidate_expanded = true;
5232 candidate_expanded = false;
5235 update_table (ISF_CANDIDATE_TABLE, table);
5236 ui_tts_focus_rect_hide ();
5237 #endif /* CANDIDATE */
5241 * @brief Send selected candidate index.
5243 * @param selected candidate string index number.
5245 static void slot_select_candidate (int index)
5247 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5248 _info_manager->select_candidate (index);
5252 * @brief Get candidate geometry slot function for PanelAgent.
5254 * @param info The data is used to store candidate position and size.
5256 static void slot_get_candidate_geometry (struct rectinfo &info)
5263 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5267 info.height = height;
5271 #if ISF_BUILD_CANDIDATE_UI
5272 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5273 /* Get candidate window position */
5274 /*ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);*/
5275 /* Get exact candidate window size */
5277 evas_object_geometry_get (_candidate_window, &x2, &y2, &width, &height);*/
5281 width = _candidate_width;
5282 height = _candidate_height;
5284 #endif /* CANDIDATE */
5289 info.height = height;
5291 LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5292 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5293 << " width:" << info.width << " height:" << info.height << "\n";
5297 * @brief Get input panel geometry slot function for PanelAgent.
5299 * @param info The data is used to store input panel position and size.
5301 static void slot_get_input_panel_geometry (struct rectinfo &info)
5303 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
5308 #if ISF_BUILD_CANDIDATE_UI
5309 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5310 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5311 info.width = _candidate_width;
5312 info.height = _candidate_height;
5314 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5315 info.width = _soft_candidate_width;
5316 info.height = _soft_candidate_height;
5318 int angle = efl_get_app_window_angle ();
5319 if (angle == 90 || angle == 270)
5320 info.pos_y = _screen_width - info.height;
5322 info.pos_y = _screen_height - info.height;
5324 info = get_ise_geometry ();
5325 if (_ise_state != WINDOW_STATE_SHOW) {
5329 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5330 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5331 int height = ui_candidate_get_valid_height ();
5333 if ((_candidate_height - height) > _ise_height) {
5334 info.pos_y = info.pos_y + info.height - _candidate_height;
5335 info.height = _candidate_height;
5337 info.pos_y -= height;
5338 info.height += height;
5343 #endif /* CANDIDATE */
5346 LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5347 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5348 << " width:" << info.width << " height:" << info.height << "\n";
5352 * @brief Get the recent input panel geometry slot function for PanelAgent.
5354 * @param angle the rotation angle of application window.
5355 * @param info The data is used to store input panel position and size.
5357 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info)
5359 LOGD ("slot_get_recent_ise_geometry");
5361 /* If we have geometry reported by ISE, use the geometry information */
5366 if (angle == 0 || angle == 180) {
5367 if (_portrait_recent_ise_geometry.valid) {
5368 info = _portrait_recent_ise_geometry.geometry;
5373 if (_landscape_recent_ise_geometry.valid) {
5374 info = _landscape_recent_ise_geometry.geometry;
5385 static bool slot_check_privilege_by_sockfd (int client_id, String privilege)
5387 PrivilegeChecker privilegeChecker (client_id);
5389 bool priv_ret = privilegeChecker.checkPrivilege (privilege.c_str ());
5391 if (priv_ret == false)
5392 LOGW ("Failed to check privilege (%s)", privilege.c_str ());
5394 LOGD ("Succeeded to check privilege (%s)", privilege.c_str ());
5400 * @brief Set active ISE slot function for PanelAgent.
5402 * @param uuid The active ISE's uuid.
5403 * @param changeDefault The flag for changing default ISE.
5405 static void slot_set_active_ise (const String &uuid, bool changeDefault)
5407 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << uuid << ")\n";
5409 bool invalid = false;
5411 #ifdef HAVE_PKGMGR_INFO
5412 /* When changing the active (default) keyboard, initialize ime_info DB if appid is invalid.
5413 This may be necessary if IME packages are changed while panel process is terminated. */
5414 pkgmgrinfo_appinfo_h handle = NULL;
5415 /* Try to get in global packages */
5416 int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
5417 if (ret != PMINFO_R_OK) {
5418 LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
5419 /* This might happen if IME is uninstalled while the panel process is inactive.
5420 The variable uuid would be invalid, so set_active_ise() would return false. */
5425 pkgmgrinfo_appinfo_destroy_appinfo (handle);
5429 _initialize_ime_info ();
5430 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5432 else if (set_active_ise (uuid, _soft_keyboard_launched) == false) {
5433 if (_initial_ise_uuid.compare (uuid))
5434 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5439 * @brief Get all ISEs list slot function for PanelAgent.
5441 * @param list The list is used to store all ISEs.
5443 * @return true if this operation is successful, otherwise return false.
5445 static bool slot_get_ise_list (std::vector<String> &list)
5447 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5449 bool result = false;
5451 std::vector<String> uuids;
5452 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5453 uuids.push_back(iter->appid);
5455 if (_ime_info.size () > 0) {
5460 result = update_ise_list (list);
5467 * @brief Get all Helper ISE information from ime_info DB.
5469 * @param info This is used to store all Helper ISE information.
5471 * @return true if this operation is successful, otherwise return false.
5473 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info)
5475 bool result = false;
5476 String active_ime_appid;
5478 info.appid.clear ();
5479 info.label.clear ();
5480 info.is_enabled.clear ();
5481 info.is_preinstalled.clear ();
5482 info.has_option.clear ();
5484 if (_ime_info.size() == 0)
5485 isf_pkg_select_all_ime_info_db (_ime_info);
5487 //active_ime_appid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5488 if (_info_manager) {
5489 active_ime_appid = _info_manager->get_current_helper_uuid ();
5492 if (_ime_info.size () > 0) {
5493 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
5494 if (iter->mode == TOOLBAR_HELPER_MODE) {
5495 info.appid.push_back (iter->appid);
5496 info.label.push_back (iter->label);
5497 info.is_enabled.push_back (iter->is_enabled);
5498 info.is_preinstalled.push_back (iter->is_preinstalled);
5499 info.has_option.push_back (static_cast<uint32>(iter->has_option));
5509 * @brief Update "has_option" column of ime_info DB by Application ID
5511 * @param[in] appid Application ID of IME to enable or disable
5512 * @param[in] has_option @c true to have IME option(setting), otherwise @c false
5514 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option)
5516 if (appid.length() == 0) {
5517 LOGW ("Invalid appid");
5521 if (_ime_info.size() == 0)
5522 isf_pkg_select_all_ime_info_db(_ime_info);
5524 if (isf_db_update_has_option_by_appid(appid.c_str(), has_option)) { // Update ime_info DB
5525 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5526 if (appid == _ime_info[i].appid) {
5527 _ime_info[i].has_option = static_cast<uint32>(has_option); // Update global variable
5534 * @brief Update "is_enable" column of ime_info DB by Application ID
5536 * @param[in] appid Application ID of IME to enable or disable
5537 * @param[in] is_enabled @c true to enable the IME, otherwise @c false
5539 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled)
5541 if (appid.length() == 0) {
5542 LOGW ("Invalid appid");
5546 if (_ime_info.size() == 0)
5547 isf_pkg_select_all_ime_info_db(_ime_info);
5549 if (isf_db_update_is_enabled_by_appid(appid.c_str(), is_enabled)) { // Update ime_info DB
5550 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5551 if (appid == _ime_info[i].appid) {
5552 _ime_info[i].is_enabled = static_cast<uint32>(is_enabled); // Update global variable
5558 #ifdef HAVE_PKGMGR_INFO
5560 * @brief Finds appid with specific category
5562 * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative
5564 static int _find_appid_from_category (const pkgmgrinfo_appinfo_h handle, void *user_data)
5567 char **result = static_cast<char **>(user_data);
5572 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
5573 if (ret == PMINFO_R_OK) {
5574 *result = strdup (appid);
5577 LOGW ("pkgmgrinfo_appinfo_get_appid failed!");
5581 LOGW ("user_data is null!");
5584 return -1; // This callback is no longer called.
5589 * @brief Requests to open the installed IME list application.
5591 static void slot_show_helper_ise_list (void)
5593 // Launch IME List application; e.g., org.tizen.inputmethod-setting-list
5594 char *app_id = NULL;
5595 #ifdef HAVE_PKGMGR_INFO
5596 pkgmgrinfo_appinfo_filter_h handle;
5599 if (ime_list_app.length() < 1) {
5600 ret = pkgmgrinfo_appinfo_filter_create (&handle);
5601 if (ret == PMINFO_R_OK) {
5602 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-list");
5603 if (ret == PMINFO_R_OK) {
5604 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
5606 pkgmgrinfo_appinfo_filter_destroy (handle);
5609 ime_list_app = String (app_id);
5613 app_id = strdup (ime_list_app.c_str());
5617 app_control_launch (app_id);
5621 SECURE_LOGW ("AppID with http://tizen.org/category/ime-list category is not available.");
5626 * @brief Requests to open the installed IME selector application.
5628 static void slot_show_helper_ise_selector (void)
5630 // Launch IME Selector application; e.g., org.tizen.inputmethod-setting-selector
5631 char *app_id = NULL;
5632 #ifdef HAVE_PKGMGR_INFO
5633 pkgmgrinfo_appinfo_filter_h handle;
5636 if (ime_selector_app.length() < 1) {
5637 ret = pkgmgrinfo_appinfo_filter_create(&handle);
5638 if (ret == PMINFO_R_OK) {
5639 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
5640 if (ret == PMINFO_R_OK) {
5641 pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, _find_appid_from_category, &app_id);
5643 pkgmgrinfo_appinfo_filter_destroy(handle);
5646 ime_selector_app = String(app_id);
5650 app_id = strdup(ime_selector_app.c_str());
5654 app_control_launch (app_id);
5658 SECURE_LOGW ("AppID with http://tizen.org/category/ime-selector category is not available.");
5662 static bool slot_is_helper_ise_enabled (String appid, int &enabled)
5664 bool is_enabled = false;
5666 if (appid.length() == 0) {
5667 LOGW ("Invalid appid.");
5671 if (_ime_info.size() == 0)
5672 isf_pkg_select_all_ime_info_db(_ime_info);
5674 if (isf_db_select_is_enabled_by_appid(appid.c_str(), &is_enabled)) {
5675 enabled = static_cast<int>(is_enabled);
5684 * @brief Get the ISE's information.
5686 * @param uuid The ISE's uuid.
5687 * @param name The ISE's name.
5688 * @param language The ISE's language.
5689 * @param type The ISE's type.
5690 * @param option The ISE's option.
5692 * @return true if this operation is successful, otherwise return false.
5694 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name)
5696 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5698 if (uuid.length () > 0) {
5699 // update all ISE names according to the display languages
5700 // sometimes get_ise_information is called before vconf display language changed callback is called.
5701 update_ise_locale ();
5703 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5704 if (uuid == _ime_info[i].appid) {
5705 name = _ime_info[i].label;
5706 language = _ime_info[i].languages;
5707 type = _ime_info[i].mode;
5708 option = _ime_info[i].options;
5709 module_name = _ime_info[i].module_name;
5715 std::cerr << __func__ << " is failed!!!\n";
5720 * @brief Get keyboard ISEs list slot function for PanelAgent.
5722 * @param name_list The list is used to store keyboard ISEs.
5724 * @return true if this operation is successful, otherwise return false.
5726 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list)
5728 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5730 isf_load_ise_information (ALL_ISE, _config);
5732 std::vector<String> lang_list, uuid_list;
5733 isf_get_all_languages (lang_list);
5734 isf_get_keyboard_ises_in_languages (lang_list, uuid_list, name_list, false);
5736 _info_manager->update_ise_list (uuid_list);
5741 * @brief Get enable languages list slot function for PanelAgent.
5743 * @param list The list is used to store languages.
5745 static void slot_get_language_list (std::vector<String> &list)
5747 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5750 MapStringVectorSizeT::iterator iter = _groups.begin ();
5752 for (; iter != _groups.end (); iter++) {
5753 lang_name = scim_get_language_name (iter->first);
5754 list.push_back (lang_name);
5759 * @brief Get all languages list slot function for PanelAgent.
5761 * @param lang The list is used to store languages.
5763 static void slot_get_all_language (std::vector<String> &lang)
5765 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5767 isf_get_all_languages (lang);
5771 * @brief Get specific ISE language list slot function for PanelAgent.
5773 * @param name The ISE name.
5774 * @param list The list is used to store ISE languages.
5776 static void slot_get_ise_language (char *name, std::vector<String> &list)
5778 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5783 std::vector<String> list_tmp;
5785 for (unsigned int i = 0; i < _ime_info.size(); i++) {
5786 if (!strcmp (_ime_info[i].label.c_str (), name)) {
5787 scim_split_string_list (list_tmp, _ime_info[i].languages, ',');
5788 for (i = 0; i < list_tmp.size (); i++)
5789 list.push_back (scim_get_language_name (list_tmp[i]));
5796 * @brief Get ISE information slot function for PanelAgent.
5798 * @param uuid The ISE uuid.
5799 * @param info The variable is used to store ISE information.
5801 * @return true if this operation is successful, otherwise return false.
5803 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info)
5805 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5807 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5808 if (!uuid.compare (_ime_info[i].appid)) {
5809 info.uuid = _ime_info[i].appid;
5810 info.name = _ime_info[i].label;
5811 info.icon = _ime_info[i].iconpath;
5812 info.lang = _ime_info[i].languages;
5813 info.option = _ime_info[i].options;
5814 info.type = _ime_info[i].mode;
5823 * @brief Set keyboard ISE slot function for PanelAgent.
5825 * @param uuid The variable is ISE uuid.
5827 static void slot_set_keyboard_ise (const String &uuid)
5829 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << uuid << "\n";
5831 std::vector<String> uuids;
5832 std::vector<ImeInfoDB>::iterator iter;
5833 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5834 uuids.push_back(iter->appid);
5837 if (uuid.length () <= 0 || std::find (uuids.begin (), uuids.end (), uuid) == uuids.end ())
5840 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5841 if (_ime_info[get_ise_index (default_uuid)].mode == TOOLBAR_KEYBOARD_MODE)
5844 uint32 ise_option = 0;
5845 String ise_uuid, ise_name;
5846 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5847 if (ise_uuid == uuid)
5850 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
5851 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
5855 _info_manager->change_factory (uuid);
5859 * @brief Get current keyboard ISE name and uuid slot function for PanelAgent.
5861 * @param ise_name The variable is used to store ISE name.
5862 * @param ise_uuid The variable is used to store ISE uuid.
5864 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid)
5866 uint32 ise_option = 0;
5867 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5869 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << ise_uuid << "\n";
5873 * @brief Accept connection slot function for PanelAgent.
5875 * @param fd The file descriptor to connect.
5877 static void slot_accept_connection (int fd)
5879 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5882 get_input_window ();
5887 * @brief Close connection slot function for PanelAgent.
5889 * @param fd The file descriptor to connect.
5891 static void slot_close_connection (int fd)
5893 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5897 * @brief Exit panel process slot function for PanelAgent.
5899 static void slot_exit (void)
5901 std::cerr << __FUNCTION__ << "...\n";
5902 ISF_SAVE_LOG ("exit");
5904 #if ISF_BUILD_CANDIDATE_UI
5907 ecore_main_loop_quit ();
5908 #endif /* CANDIDATE */
5911 static void delete_ise_check_pid_alive_timer(void)
5913 LOGD("deleting ise_check_alive_timer");
5914 if (_ise_check_pid_alive_timer) {
5915 ecore_timer_del(_ise_check_pid_alive_timer);
5916 _ise_check_pid_alive_timer = NULL;
5920 static Eina_Bool ise_check_pid_alive_timer(void *data)
5922 Eina_Bool ret = ECORE_CALLBACK_RENEW;
5923 Eina_Bool retry = EINA_FALSE;
5925 int status = aul_app_get_status (_ise_check_pid_alive_uuid.c_str ());
5926 LOGD ("STATUS : %d", status);
5927 if (status >= STATUS_LAUNCHING) {
5928 /* If the status is not one of STATUS_LAUNCHING, STATUS_VISIBLE, STATUS_BG */
5929 if (status >= STATUS_DYING) {
5930 LOGE ("aul_app_get_status reports %d", status);
5935 /* Status query not successful, the ISE could have failed launching */
5936 LOGE ("aul_app_get_status failed. %d", status);
5941 _soft_keyboard_launched = false;
5942 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
5943 /* The start_helper() function below will going to call slot_run_helper,
5944 which will going to assign a new timer handle to the _ise_check_pid_alive_timer variable.
5946 LOGW ("The previous attempt to launch %s seems to be failed, restarting",
5947 _ise_check_pid_alive_uuid.c_str ());
5948 if (_info_manager->start_helper (uuid))
5949 _soft_keyboard_launched = true;
5950 ret = ECORE_CALLBACK_CANCEL;
5956 static void slot_register_helper(int id, const HelperInfo& info)
5958 LOGD ("app id : %s", info.uuid.c_str ());
5959 /* Do we need to check whether the pid of this helper is the one we are watching? */
5960 if (info.uuid.compare(_ise_check_pid_alive_uuid) == 0) {
5961 delete_ise_check_pid_alive_timer();
5965 static void slot_register_helper_properties (int id, const PropertyList &props)
5967 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5969 /* WMSYNC, #2 Receiving X window ID from ISE */
5970 /* FIXME : We should add an API to set window id of ISE */
5971 Property prop = props[0];
5972 if (prop.get_label ().compare ("XID") == 0) {
5973 Ecore_X_Window xwindow = atoi (prop.get_key ().c_str ());
5974 _ise_window = xwindow;
5975 LOGD ("ISE XID : %x", _ise_window);
5977 /* Just in case for the helper sent this message later than show_ise request */
5978 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
5979 efl_set_transient_for_app_window (_ise_window);
5982 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_ISE_WINDOW");
5983 if (atom && _control_window && _ise_window) {
5984 ecore_x_window_prop_xid_set (_control_window, atom, ECORE_X_ATOM_WINDOW, &_ise_window, 1);
5986 #ifdef HAVE_NOTIFICATION
5987 delete_notification (&ise_selector_module_noti);
5993 #if ENABLE_REMOTE_INPUT
5994 static void slot_send_remote_input_message (const String &msg, bool len)
5996 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5998 String con = msg.c_str ();
5999 ISE_MESSAGE message = CISEMessageSerializer::deserialize(con);
6001 if (remote_input_impl == NULL) {
6002 remote_input_impl = Remote_Input::get_instance();
6005 if (remote_input_impl)
6006 remote_input_impl->handle_websocket_message(message);
6009 static void slot_recv_remote_surrounding_text (int cursor, const String &text)
6011 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6013 if (remote_input_impl == NULL) {
6014 remote_input_impl = Remote_Input::get_instance();
6017 if (remote_input_impl)
6018 remote_input_impl->handle_recv_panel_message(3, text.c_str (), cursor);
6022 static void slot_show_ise (void)
6024 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6026 /* If the current toolbar mode is not HELPER_MODE, do not proceed */
6027 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
6028 LOGD ("Current toolbar mode should be TOOLBAR_HELPER_MODE but is %d, returning",
6029 _info_manager->get_current_toolbar_mode ());
6033 LOGD ("slot_show_ise ()");
6035 delete_ise_hide_timer ();
6037 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
6038 // Unset conformant area
6039 Ecore_X_Window current_app_window = efl_get_app_window ();
6040 if (_app_window != current_app_window) {
6041 struct rectinfo info = {0, 0, 0, 0};
6042 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
6043 set_keyboard_geometry_atom_info (_app_window, info);
6044 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6045 LOGD ("Conformant reset for window %x", _app_window);
6046 _app_window = current_app_window;
6048 /* If the target window has changed but our ISE is still in visible state,
6049 update the keyboard geometry information */
6050 if (_ise_state == WINDOW_STATE_SHOW) {
6051 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6055 /* If the candidate was already in SHOW state, respect the current angle */
6056 if (_candidate_state != WINDOW_STATE_SHOW) {
6057 /* FIXME : Need to check if candidate_angle and window_angle should be left as separated */
6058 _candidate_angle = efl_get_app_window_angle ();
6060 /* If the ise was already in SHOW state, respect the current angle */
6061 if (_ise_state != WINDOW_STATE_SHOW) {
6062 _ise_angle = efl_get_app_window_angle ();
6065 ecore_x_event_mask_set (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6066 efl_set_transient_for_app_window (_ise_window);
6068 /* Make clipboard window to have transient_for information on ISE window,
6069 so that the clipboard window will always be above ISE window */
6070 Ecore_X_Window clipboard_window = efl_get_clipboard_window ();
6071 if (_ise_window && clipboard_window) {
6072 ecore_x_icccm_transient_for_set (clipboard_window, _ise_window);
6075 /* If our ISE was already in SHOW state, skip state transition to WILL_SHOW */
6076 if (_ise_state != WINDOW_STATE_SHOW) {
6077 _ise_state = WINDOW_STATE_WILL_SHOW;
6081 #if ISF_BUILD_CANDIDATE_UI
6082 _candidate_angle = 0;
6083 #endif /* CANDIDATE */
6084 _ise_state = WINDOW_STATE_SHOW;
6086 #ifdef HAVE_NOTIFICATION
6087 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6088 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6089 show_ime_selector_notification ();
6096 static void slot_hide_ise (void)
6098 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6100 LOGD ("slot_hide_ise ()");
6102 if (!_ise_hide_timer)
6106 static void slot_will_hide_ack (void)
6108 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6110 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
6111 // WILL_HIDE_REQUEST_DONE Ack to WM
6112 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6113 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
6114 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
6115 root_window, _control_window);
6116 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6117 LOGD ("calling ui_candidate_hide (true, false)");
6118 ui_candidate_hide (true, false);
6121 /* WILL_HIDE_ACK means that the application finished redrawing the autoscroll area,
6122 now hide the candidate window right away if it is also in WILL_HIDE state */
6123 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6124 candidate_window_hide ();
6127 if (_off_prepare_done_timer) {
6128 ecore_timer_del (_off_prepare_done_timer);
6129 _off_prepare_done_timer = NULL;
6134 static void slot_candidate_will_hide_ack (void)
6136 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6138 LOGD ("candidate_will_hide_ack");
6139 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6140 candidate_window_hide ();
6145 static void slot_set_keyboard_mode (int mode)
6147 LOGD ("slot_set_keyboard_mode called (TOOLBAR_MODE : %d)", mode);
6149 change_keyboard_mode ((TOOLBAR_MODE_T)mode);
6152 static void slot_get_ise_state (int &state)
6154 if (_ise_state == WINDOW_STATE_SHOW ||
6155 ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (_candidate_state == WINDOW_STATE_SHOW))) {
6156 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6158 /* Currently we don't have WILL_HIDE / HIDE state distinction in Ecore_IMF */
6159 switch (_ise_state) {
6160 case WINDOW_STATE_SHOW :
6161 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6163 case WINDOW_STATE_WILL_SHOW :
6164 state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
6166 case WINDOW_STATE_WILL_HIDE :
6167 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6169 case WINDOW_STATE_HIDE :
6170 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6173 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6176 LOGD ("state = %d", state);
6177 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " state = " << state << "\n";
6180 static void slot_start_default_ise (void)
6182 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6184 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE)) {
6185 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6186 int pid = aul_app_get_pid (uuid.c_str ());
6188 if (STATUS_DYING == aul_app_get_status (uuid.c_str ()))
6191 if ((_launch_ise_on_request || !_enable_auto_restart) && !_soft_keyboard_launched && pid < 0) {
6192 LOGD ("Start helper (%s)", uuid.c_str ());
6193 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
6195 if (_info_manager->start_helper (uuid))
6196 _soft_keyboard_launched = true;
6198 LOGW ("Failed to start helper (%s)", uuid.c_str ());
6203 static void slot_stop_default_ise (bool is_exist)
6205 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6208 if (_launch_ise_on_request && _auto_destroy_ise && _soft_keyboard_launched) {
6209 String uuid = _info_manager->get_current_helper_uuid ();
6211 if (uuid.length () > 0) {
6212 _info_manager->hide_helper (uuid);
6213 _info_manager->stop_helper (uuid);
6214 _soft_keyboard_launched = false;
6215 LOGD ("stop helper (%s)", uuid.c_str ());
6219 if (_soft_keyboard_launched)
6220 _soft_keyboard_launched = false;
6224 static void launch_helper (const char* exec, const char *name, const char *appid, const char *config, const char *display)
6230 if (pid < 0) return;
6233 const char *argv [] = { exec,
6236 "--display", display,
6237 const_cast<char*> (name),
6238 const_cast<char*> (appid),
6241 SCIM_DEBUG_MAIN (2) << " Call scim-helper-launcher.\n";
6242 ISF_SAVE_LOG ("Exec scim_helper_launcher(%s %s)", name, appid);
6244 unsetenv ("ELM_THEME");
6245 unsetenv ("ELM_SCALE");
6248 LOGD ("launch execpath : %s", exec);
6249 execv (exec, const_cast<char **>(argv));
6250 #if ISF_BUILD_CANDIDATE_UI
6253 ecore_main_loop_quit ();
6254 #endif /* CANDIDATE */
6258 static bool app_control_launch (const char *app_id)
6260 app_control_h app_control;
6263 ret = app_control_create (&app_control);
6264 if (ret != APP_CONTROL_ERROR_NONE) {
6265 LOGW ("app_control_create returned %08x", ret);
6269 ret = app_control_set_operation (app_control, APP_CONTROL_OPERATION_DEFAULT);
6270 if (ret != APP_CONTROL_ERROR_NONE) {
6271 LOGW ("app_control_set_operation returned %08x", ret);
6272 app_control_destroy (app_control);
6276 ret = app_control_set_app_id (app_control, app_id);
6277 if (ret != APP_CONTROL_ERROR_NONE) {
6278 LOGW ("app_control_set_app_id returned %08x", ret);
6279 app_control_destroy (app_control);
6283 if (_TV && _preloading_ise) {
6284 ret = app_control_add_extra_data(app_control, "Preloading", "true");
6285 if (ret != APP_CONTROL_ERROR_NONE) {
6286 LOGW ("app_control_add_extra_data returned %08x", ret);
6292 if (tries != 0) usleep(1000000); /* If we are retrying to launch, pause for a while */
6293 ret = app_control_send_launch_request(app_control, NULL, NULL);
6294 LOGW ("app_control_send_launch_request returned %08x, app_id=%s", ret, app_id);
6295 } while (ret != APP_CONTROL_ERROR_NONE && (++tries) < 3);
6297 app_control_destroy (app_control);
6299 if (ret != APP_CONTROL_ERROR_NONE) {
6300 LOGW ("Failed to launch IME. appid(%s). reason(%s)", app_id, get_error_message(ret));
6302 LOGD ("Succeeded to launch IME. appid(%s)", app_id);
6305 return (ret == APP_CONTROL_ERROR_NONE);
6308 static void add_ise_check_pid_alive_timer(const String &uuid) {
6309 delete_ise_check_pid_alive_timer ();
6310 LOGD ("Register check_alive timer for uuid : %s", uuid.c_str ());
6311 _ise_check_pid_alive_uuid = uuid;
6312 _ise_check_pid_alive_timer = ecore_timer_add (_ise_check_pid_alive_time,
6313 ise_check_pid_alive_timer, NULL);
6316 static void terminate_active_ise (const String uuid)
6318 /* Check if IME with the same AppID is alive */
6319 int status_ret = aul_app_get_status (uuid.c_str ());
6320 if (status_ret >= STATUS_LAUNCHING) {
6321 /* Request to terminate IME */
6322 int ime_pid = aul_app_get_pid (uuid.c_str ());
6323 status_ret = aul_terminate_pid (ime_pid);
6324 if (status_ret < AUL_R_OK) {
6325 LOGE ("aul_terminate_pid(%d) failed: %d", ime_pid, status_ret);
6328 LOGD ("Requested to terminate IME(%s)", uuid.c_str ());
6334 static void set_cpu_boosting ()
6336 resource_pid_t resource_st;
6337 resource_st.pid = getpid();
6338 int ret = resource_set_cpu_boosting(resource_st, CPU_BOOSTING_LEVEL_STRONG, CPU_BOOSTING_RESET_ON_FORK, -1);
6340 LOGE("Failed to set cpu boosting");
6343 static void clear_cpu_boosting ()
6345 resource_pid_t resource_st;
6346 resource_st.pid = getpid();
6347 int ret = resource_clear_cpu_boosting(resource_st);
6349 LOGE("Failed to clear cpu boosting");
6352 static void slot_run_helper (const String &uuid, const String &config, const String &display)
6354 ISF_SAVE_LOG ("time:%ld pid:%d %s %s uuid(%s)",
6355 time (0), getpid (), __FILE__, __func__, uuid.c_str ());
6357 String scim_helper_path;
6359 delete_ise_check_pid_alive_timer ();
6361 #ifdef HAVE_PKGMGR_INFO
6362 char *execpath = NULL;
6364 pkgmgrinfo_appinfo_h appinfo_handle;
6366 /* get app info handle */
6367 /* Try to get in global packages */
6368 ret = pkgmgr_get_appinfo (uuid.c_str (), &appinfo_handle);
6369 if (ret != PMINFO_R_OK) {
6370 LOGE ("pkgmgr_get_appinfo failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6371 add_ise_check_pid_alive_timer (uuid);
6376 ret = pkgmgrinfo_appinfo_get_exec (appinfo_handle, &execpath);
6377 if (ret != PMINFO_R_OK) {
6378 LOGE ("pkgmgrinfo_appinfo_get_exec failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6379 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6380 add_ise_check_pid_alive_timer (uuid);
6384 LOGD ("exec path : %s %zu", execpath, _ime_info.size ());
6385 scim_helper_path = String (execpath);
6387 if (appinfo_handle) {
6388 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6389 appinfo_handle = NULL;
6392 scim_helper_path = String (SCIM_HELPER_LAUNCHER_PROGRAM);
6395 for (size_t i = 0; i < _ime_info.size (); ++i) {
6396 if (_ime_info[i].appid == uuid && _ime_info[i].module_name.length ()) {
6397 if (scim_helper_path != String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
6398 terminate_active_ise (uuid);
6399 /* execute type IME */
6400 LOGD ("Try to launch IME (%s)", uuid.c_str ());
6401 app_control_launch (uuid.c_str ());
6403 /* ISE check alive only works for AUL based IMEs */
6404 add_ise_check_pid_alive_timer (uuid);
6407 /* shared object (so) type IME */
6408 launch_helper (scim_helper_path.c_str(), _ime_info[i].module_name.c_str (), uuid.c_str (), config.c_str (), display.c_str ());
6411 _soft_keyboard_launched = true;
6416 SCIM_DEBUG_MAIN (2) << " exit run_helper ().\n";
6419 static bool slot_launch_option_application (String ime_appid)
6421 String ime_setting_app = isf_pkg_get_setting_app (ime_appid);
6423 LOGD ("IME appid(%s), IME setting app id(%s)", ime_appid.c_str (), ime_setting_app.c_str ());
6425 if (ime_setting_app.length () > 0) {
6426 app_control_launch (ime_setting_app.c_str ());
6433 static bool slot_get_ise_setting_appid (String ime_appid, String &ime_setting_appid)
6435 ime_setting_appid = isf_pkg_get_setting_app (ime_appid);
6437 LOGD ("IME appid : %s, IME setting app ID : %s", ime_appid.c_str(), ime_setting_appid.c_str());
6438 return ime_setting_appid.length () > 0 ? true : false;
6441 static void slot_set_preloading_ise (bool preloading)
6443 _preloading_ise = preloading;
6446 //////////////////////////////////////////////////////////////////////
6447 // End of PanelAgent-Functions
6448 //////////////////////////////////////////////////////////////////////
6452 * @brief Callback function for abnormal signal.
6454 * @param sig The signal.
6456 static void signalhandler (int sig)
6458 std::cerr << __FUNCTION__ << " Signal=" << sig << "\n";
6459 ISF_SAVE_LOG ("Signal=%d", sig);
6461 #if ISF_BUILD_CANDIDATE_UI
6464 ecore_main_loop_quit ();
6465 #endif /* CANDIDATE */
6469 static void update_ise_locale (const char *language)
6474 strLang = String (language);
6477 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
6479 if (_locale_string.compare(lang_str) == 0) {
6484 strLang = String (lang_str);
6490 LOGD ("update all ISE names according to display language : %s", strLang.c_str ());
6491 set_language_and_locale (strLang.c_str ());
6493 bool need_to_init_db = false;
6494 #ifdef HAVE_PKGMGR_INFO
6498 pkgmgrinfo_appinfo_h handle = NULL;
6500 /* Read DB from ime_info table */
6501 isf_load_ise_information(ALL_ISE, _config);
6503 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6504 ret = pkgmgr_get_appinfo (_ime_info[i].appid.c_str(), &handle);
6506 if (ret == PMINFO_R_OK) {
6507 ret = pkgmgrinfo_appinfo_is_category_exist(handle, "http://tizen.org/category/ime", &exist);
6508 if (ret == PMINFO_R_OK && exist) {
6509 ret = pkgmgrinfo_appinfo_get_label(handle, &label);
6510 if (ret == PMINFO_R_OK && label) {
6511 _ime_info[i].label = String(label);
6512 /* Update label column in ime_info db table */
6513 if (isf_db_update_label_by_appid(_ime_info[i].appid.c_str(), label)) {
6514 _ime_info[i].label = label;
6519 // The appid is invalid.. Need to initialize ime_info DB.
6520 need_to_init_db = true;
6522 pkgmgrinfo_appinfo_destroy_appinfo(handle);
6525 // The appid is invalid.. Need to initialize ime_info DB.
6526 need_to_init_db = true;
6531 if (need_to_init_db) {
6532 _initialize_ime_info ();
6535 if (strLang.length () > 0) {
6536 isf_db_update_disp_lang (strLang.c_str ());
6537 _locale_string = strLang;
6542 * @brief Set language and locale.
6546 static void set_language_and_locale (const char *lang_str)
6548 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6553 LOGD ("language : %s", lang_str);
6554 #if ISF_BUILD_CANDIDATE_UI
6555 elm_language_set (lang_str);
6556 #endif /* CANDIDATE */
6558 snprintf (language, sizeof (language), "%s:en_US:en_GB:en", lang_str);
6559 setenv ("LANGUAGE", language, 1);
6560 setenv ("LANG", lang_str, 1);
6561 setlocale (LC_MESSAGES, lang_str);
6563 setenv ("LANG", "en_US.utf8", 1);
6564 setlocale (LC_MESSAGES, "en_US.utf8");
6569 * @brief Callback function for display language change.
6571 * @param key The key node.
6572 * @param data The data to pass to this callback.
6576 static void display_language_changed_cb (keynode_t *key, void* data)
6578 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6580 char *lang_str = vconf_keynode_get_str (key);
6581 LOGD ("lang : %s", lang_str);
6582 set_language_and_locale (lang_str);
6584 /* Update all ISE names according to display language */
6585 update_ise_locale ();
6587 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
6588 unsigned int ise_idx = get_ise_index (default_uuid);
6590 if (ise_idx < _ime_info.size ()) {
6591 String default_name = _ime_info[ise_idx].label;
6592 _info_manager->set_current_ise_name (default_name);
6598 * @brief Callback function for keyboard mode change.
6600 * @param key The key node.
6601 * @param data The data to pass to this callback.
6605 static void keyboard_mode_changed_cb (keynode_t *key, void* data)
6607 bool val = vconf_keynode_get_bool (key);
6610 _info_manager->reset_keyboard_ise ();
6611 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6612 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6617 static void set_hw_keyboard_input_detect_flag(bool flag)
6620 int input_detect = false;
6622 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect) == 0) {
6623 if (input_detect != flag) {
6624 if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, flag) != 0)
6625 LOGW ("Failed to set vconf key");
6627 LOGD ("Succeeded to set vconf key");
6634 * @brief Change keyboard mode.
6636 * @param mode The keyboard mode.
6640 static void change_keyboard_mode (TOOLBAR_MODE_T mode)
6642 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6645 bool _support_hw_keyboard_mode = false;
6647 unsigned int val = 0;
6650 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6651 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6652 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
6654 if (mode == TOOLBAR_KEYBOARD_MODE && _support_hw_keyboard_mode) {
6655 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6656 LOGD ("HARDWARE_KEYBOARD_MODE return");
6660 LOGD ("HARDWARE KEYBOARD MODE");
6661 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 1);
6664 if (_ime_info[get_ise_index(default_uuid)].mode == TOOLBAR_HELPER_MODE) {
6665 /* Get the keyboard ISE */
6666 isf_get_keyboard_ise (_config, uuid, name, option);
6667 if (option & SCIM_IME_NOT_SUPPORT_HARDWARE_KEYBOARD) {
6668 uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
6669 std::cerr << __FUNCTION__ << ": Keyboard ISE (" << name << ") can not support hardware keyboard!!!\n";
6671 /* Try to find reasonable keyboard ISE according to helper ISE language */
6672 if (uuid == String (SCIM_COMPOSE_KEY_FACTORY_UUID)) {
6673 String helper_language = _ime_info[get_ise_index(default_uuid)].languages;
6674 if (helper_language.length () > 0) {
6675 std::vector<String> ise_langs;
6676 scim_split_string_list (ise_langs, helper_language);
6677 for (size_t i = 0; i < _groups[ise_langs[0]].size (); ++i) {
6678 int j = _groups[ise_langs[0]][i];
6679 if (_ime_info[j].appid != uuid && _ime_info[j].mode == TOOLBAR_KEYBOARD_MODE) {
6680 uuid = _ime_info[j].appid;
6688 uuid = default_uuid;
6690 #if ISF_BUILD_CANDIDATE_UI
6691 _soft_candidate_width = 0;
6692 _soft_candidate_height = 0;
6693 #endif /* CANDIDATE */
6694 _ise_state = WINDOW_STATE_HIDE;
6695 _info_manager->set_current_toolbar_mode (TOOLBAR_KEYBOARD_MODE);
6696 _info_manager->hide_helper (helper_uuid);
6698 /* Check whether stop soft keyboard */
6699 if (_focus_in && (_ime_info[get_ise_index (helper_uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
6700 /* If focus in and soft keyboard can support hardware key event, then don't stop it */
6702 } else if (_launch_ise_on_request && _soft_keyboard_launched) {
6703 _info_manager->stop_helper (helper_uuid);
6704 _soft_keyboard_launched = false;
6707 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6710 #ifdef HAVE_NOTIFICATION
6711 LOGI("Input detected from H/W keyboard");
6712 if (_MOBILE || _COMMON) {
6713 notification_status_message_post (_("Input detected from hardware keyboard"));
6715 /* Read configurations for notification app (isf-kbd-mode-changer) */
6716 String kbd_mode_changer = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_KBD_MODE_CHANGER_PROGRAM), String (""));
6717 hwkbd_module_noti.launch_app = kbd_mode_changer;
6718 LOGD ("Create kbd_mode_changer notification with : %s", kbd_mode_changer.c_str ());
6719 create_notification (&hwkbd_module_noti);
6723 set_hw_keyboard_input_detect_flag(true);
6724 } else if (mode == TOOLBAR_HELPER_MODE) {
6725 LOGD ("SOFTWARE KEYBOARD MODE");
6726 /* When switching back to S/W keyboard mode, let's hide candidate window first */
6727 #if ISF_BUILD_CANDIDATE_UI
6728 LOGD ("calling ui_candidate_hide (true, true, true)");
6729 ui_candidate_hide (true, true, true);
6730 #endif /* CANDIDATE */
6731 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
6733 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6734 uuid = helper_uuid.length () > 0 ? helper_uuid : _initial_ise_uuid;
6735 if (_launch_ise_on_request) {
6736 if (set_active_ise (uuid, false) == false) {
6737 if (_initial_ise_uuid.compare(uuid))
6738 set_active_ise (_initial_ise_uuid, false);
6742 if (set_active_ise (uuid, true) == false) {
6743 if (_initial_ise_uuid.compare(uuid)) {
6744 LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
6745 set_active_ise (_initial_ise_uuid, true);
6751 #ifdef HAVE_NOTIFICATION
6752 delete_notification (&hwkbd_module_noti);
6755 set_hw_keyboard_input_detect_flag(false);
6760 #ifdef HAVE_NOTIFICATION
6761 static void show_ime_selector_notification ()
6765 if (!_MOBILE && !_COMMON) return;
6767 unsigned int idx = get_ise_index (_info_manager->get_current_helper_uuid ());
6768 if (idx < _ime_info.size ())
6769 ise_name = _ime_info[idx].label;
6771 String noti_icon_path = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_QUICK_PANEL_ICON_PATH), String (SCIM_ICONDIR));
6772 noti_icon_path += ISF_ISE_SELECTOR_ICON_FILE;
6774 LOGD("IME selector icon path : %s", noti_icon_path.c_str ());
6776 ise_selector_module_noti.icon = noti_icon_path;
6777 ise_selector_module_noti.content = ise_name;
6779 /* Find IME Selector appid for notification */
6780 if (ime_selector_app.length () < 1) {
6781 char *app_id = NULL;
6782 pkgmgrinfo_appinfo_filter_h handle;
6783 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
6784 if (ret == PMINFO_R_OK) {
6785 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
6786 if (ret == PMINFO_R_OK) {
6787 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
6789 pkgmgrinfo_appinfo_filter_destroy (handle);
6792 ime_selector_app = String (app_id);
6799 if (ime_selector_app.length () > 0) {
6800 ise_selector_module_noti.launch_app = ime_selector_app;
6801 LOGD ("Create ise_selector notification with : %s", ime_selector_app.c_str ());
6802 create_notification (&ise_selector_module_noti);
6805 LOGW ("AppID with http://tizen.org/category/ime-selector category is not available");
6811 * @brief Callback function for ECORE_X_EVENT_WINDOW_PROPERTY.
6813 * @param data Data to pass when it is called.
6814 * @param ev_type The event type.
6815 * @param ev The information for current message.
6817 * @return ECORE_CALLBACK_PASS_ON
6819 static Eina_Bool x_event_window_property_cb (void *data, int ev_type, void *event)
6821 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6823 Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property *)event;
6826 return ECORE_CALLBACK_PASS_ON;
6828 if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
6829 if (ev->win == _control_window) {
6830 /* WMSYNC, #6 The keyboard window is displayed fully so set the conformant geometry */
6831 LOGD ("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE : win : %p, atom : %d", ev->win, ev->atom);
6832 Ecore_X_Virtual_Keyboard_State state;
6833 state = ecore_x_e_virtual_keyboard_state_get (ev->win);
6834 if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON) {
6835 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_ON");
6836 _ise_state = WINDOW_STATE_SHOW;
6838 /* Make sure that we have the same rotation angle with the keyboard window */
6840 _candidate_angle = efl_get_ise_window_angle ();
6841 _ise_angle = efl_get_ise_window_angle ();
6844 if (_candidate_show_requested) {
6845 LOGD ("calling ui_candidate_show (true)");
6846 ui_candidate_show (true);
6848 if (_candidate_area_1_visible) {
6849 LOGD ("calling ui_candidate_show (false)");
6850 ui_candidate_show (false);
6854 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6855 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6856 _info_manager->update_input_panel_event (
6857 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_SHOW);
6860 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW);
6863 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6864 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6865 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6867 #ifdef HAVE_NOTIFICATION
6868 show_ime_selector_notification ();
6873 _updated_hide_state_geometry = false;
6875 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
6876 } else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) {
6877 /* WMSYNC, #9 The keyboard window is hidden fully so send HIDE state */
6878 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF");
6879 // For now don't send HIDE signal here
6880 //_info_manager->update_input_panel_event (
6881 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6882 _ise_state = WINDOW_STATE_HIDE;
6884 if (!_updated_hide_state_geometry) {
6885 /* When the ISE gets hidden by the window manager forcefully without OFF_PREPARE,
6886 the application might not have updated its autoscroll area */
6887 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6888 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6889 _info_manager->update_input_panel_event (
6890 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6892 _updated_hide_state_geometry = true;
6894 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6895 LOGD ("calling ui_candidate_hide (true, false)");
6896 ui_candidate_hide (true, false);
6898 ui_settle_candidate_window ();
6902 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
6905 #ifdef HAVE_NOTIFICATION
6906 delete_notification (&ise_selector_module_noti);
6909 _ise_reported_geometry.valid = false;
6911 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
6913 ui_settle_candidate_window ();
6915 } else if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
6916 if (ev->win == efl_get_quickpanel_window ()) {
6917 int angle = efl_get_quickpanel_window_angle ();
6918 LOGD ("ev->win : %p, change window angle : %d", ev->win, angle);
6922 return ECORE_CALLBACK_PASS_ON;
6926 * @brief Callback function for X event client message.
6928 * @param data Data to pass when it is called.
6929 * @param type The event type.
6930 * @param event The information for current message.
6932 * @return ECORE_CALLBACK_RENEW
6934 static Eina_Bool x_event_client_message_cb (void *data, int type, void *event)
6936 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6938 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
6941 return ECORE_CALLBACK_RENEW;
6944 if ((ev->win == _control_window)) {
6945 if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST) {
6946 /* WMSYNC, #4 Send WILL_SHOW event when the keyboard window is about to displayed */
6947 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST");
6949 /* WMSYNC, #5 Let the Window Manager to actually show keyboard window */
6950 // WILL_SHOW_REQUEST_DONE Ack to WM
6951 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6952 ecore_x_e_virtual_keyboard_on_prepare_done_send (root_window, _control_window);
6953 LOGD ("_ecore_x_e_virtual_keyboard_on_prepare_done_send (%x, %x)",
6954 root_window, _control_window);
6956 _info_manager->update_input_panel_event (
6957 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
6958 ui_create_candidate_window ();
6960 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_SHOW);
6961 } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST) {
6962 _ise_state = WINDOW_STATE_WILL_HIDE;
6963 /* WMSYNC, #7 Send WILL_HIDE event when the keyboard window is about to hidden */
6964 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST");
6965 // Clear conformant geometry information first
6967 if (_off_prepare_done_timer) {
6968 ecore_timer_del (_off_prepare_done_timer);
6969 _off_prepare_done_timer = NULL;
6971 _off_prepare_done_timer = ecore_timer_add (1.0, off_prepare_done_timeout, NULL);
6973 _ise_reported_geometry.valid = false;
6974 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6975 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6976 _updated_hide_state_geometry = true;
6978 /* If the input panel is getting hidden because of hw keyboard mode while
6979 the candidate window is still opened, it is considered to be an
6980 "input panel being resized" event instead of "input panel being hidden",
6981 since the candidate window will work as an "input panel" afterwards */
6982 bool send_input_panel_hide_event = true;
6983 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6984 LOGD ("_candidate_state : %d", _candidate_state);
6985 if (_candidate_state == WINDOW_STATE_SHOW) {
6986 send_input_panel_hide_event = false;
6989 if (send_input_panel_hide_event) {
6990 _info_manager->update_input_panel_event (
6991 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6993 // For now don't send WILL_HIDE signal here
6994 //_info_manager->update_input_panel_event (
6995 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_HIDE);
6996 // Instead send HIDE signal
6997 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_HIDE);
6998 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE) {
6999 /* WMSYNC, #10 Register size hints for candidate window and set conformant geometry */
7000 // PRE_ROTATE_DONE Ack to WM
7001 _candidate_angle = ev->data.l[1];
7002 _ise_angle = ev->data.l[1];
7003 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE : %d", _candidate_angle);
7005 if (_candidate_angle == 90 || _candidate_angle == 270) {
7006 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
7008 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
7010 if (_ise_state == WINDOW_STATE_SHOW) {
7011 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7012 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7014 ui_settle_candidate_window ();
7015 ui_candidate_window_rotate (_candidate_angle);
7016 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
7017 LOGD ("ecore_x_e_window_rotation_change_prepare_done_send (%d)", _candidate_angle);
7018 ecore_x_e_window_rotation_change_prepare_done_send (root_window,
7019 _control_window, _candidate_angle);
7020 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7021 int ise_angle = (int)ev->data.l[1];
7022 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST for ISE WINDOW : ISE angle : %d, Candidate angle : %d", ise_angle, _candidate_angle);
7023 _candidate_angle = ise_angle;
7024 _ise_angle = ise_angle;
7025 if (_ise_state == WINDOW_STATE_SHOW) {
7026 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7027 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7028 ui_settle_candidate_window ();
7031 } else if (ev->win == elm_win_xwindow_get (_candidate_window)) {
7032 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST || ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE) {
7033 /* WMSYNC, #11 Actual rotate the candidate window */
7034 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7035 _candidate_angle = (int)ev->data.l[1];
7036 ui_candidate_window_rotate (_candidate_angle);
7037 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST : %d", _candidate_angle);
7038 } else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE &&
7039 _ise_state != WINDOW_STATE_SHOW) {
7040 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_TRUE);
7041 _candidate_angle = (int)ev->data.l[0];
7042 if (_candidate_angle == 90 || _candidate_angle == 270) {
7043 evas_object_resize (_candidate_window, _candidate_land_width, _candidate_land_height_min);
7045 evas_object_resize (_candidate_window, _candidate_port_width, _candidate_port_height_min);
7047 ui_candidate_window_rotate (_candidate_angle);
7048 ui_settle_candidate_window ();
7049 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_FALSE);
7050 LOGD ("ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE : %d", _candidate_angle);
7052 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " : ANGLE (" << _candidate_angle << ")\n";
7057 /* Screen reader feature */
7058 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL) {
7059 static int last_pos_x = -10000;
7060 static int last_pos_y = -10000;
7062 if (_candidate_window) {
7063 if ((unsigned int)ev->data.l[0] == elm_win_xwindow_get (_candidate_window)) {
7064 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE) {
7065 // 1 finger double tap
7066 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger double tap focus index = " << _candidate_tts_focus_index << "\n";
7067 ui_mouse_click (_candidate_tts_focus_index);
7068 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ) {
7070 // 1 finger touch & move
7071 last_pos_x = ev->data.l[2];
7072 last_pos_y = ev->data.l[3];
7073 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger touch & move (" << last_pos_x << ", " << last_pos_y << ")\n";
7074 ui_mouse_over (last_pos_x, last_pos_y);
7075 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT ||
7076 (unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV) {
7077 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT) {
7079 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick right\n";
7080 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_display_number - 1))
7081 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : 0;
7082 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7083 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7084 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7085 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7086 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7087 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? 0 : _candidate_row_items[0];
7088 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7089 _candidate_tts_focus_index = _candidate_row_items[0];
7090 else if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < (g_isf_candidate_table.get_current_page_size () - 1))
7091 _candidate_tts_focus_index++;
7092 else if (_candidate_tts_focus_index == (g_isf_candidate_table.get_current_page_size () - 1))
7093 _candidate_tts_focus_index = 0;
7096 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick left\n";
7097 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == 0)
7098 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : _candidate_display_number - 1;
7099 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7100 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7101 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7102 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7103 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7104 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7105 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7106 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7107 else if (_candidate_tts_focus_index > 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ())
7108 _candidate_tts_focus_index--;
7109 else if (_candidate_tts_focus_index == 0)
7110 _candidate_tts_focus_index = g_isf_candidate_table.get_current_page_size () - 1;
7113 int x = 0, y = 0, w = 0, h = 0;
7114 _wait_stop_event = false;
7115 if (candidate_expanded) {
7117 int cursor_line = 0;
7118 for (unsigned int i = 0; i < _candidate_row_items.size (); i++) {
7119 total += _candidate_row_items [i];
7120 if (total > (int)_candidate_display_number && _candidate_tts_focus_index >= total)
7124 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
7126 int line_h = _item_min_height + _v_padding;
7127 int cursor_y = cursor_line * line_h;
7129 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
7130 _wait_stop_event = true;
7131 } else if (cursor_y >= y + h) {
7132 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
7133 _wait_stop_event = true;
7138 String strTts = String ("");
7139 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
7140 strTts = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (_candidate_tts_focus_index));
7141 if (_candidate_0 [_candidate_tts_focus_index])
7142 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
7143 } else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX) {
7144 strTts = String (_("more button"));
7145 evas_object_geometry_get (_more_btn, &x, &y, &w, &h);
7146 } else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX) {
7147 strTts = String (_("close button"));
7148 evas_object_geometry_get (_close_btn, &x, &y, &w, &h);
7150 ui_tts_focus_rect_hide ();
7153 if (w > 0 && h > 0) {
7154 if (!_wait_stop_event)
7155 ui_tts_focus_rect_show (x, y, w, h);
7157 ui_tts_focus_rect_hide ();
7164 return ECORE_CALLBACK_RENEW;
7168 Eina_Bool check_focus_out_by_popup_win ()
7170 Eina_Bool ret = EINA_FALSE;
7172 Ecore_X_Window focus_win = ecore_x_window_focus_get ();
7173 Ecore_X_Window_Type win_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
7175 if (!ecore_x_netwm_window_type_get (focus_win, &win_type))
7178 LOGD ("win type : %d", win_type);
7180 if (win_type == ECORE_X_WINDOW_TYPE_POPUP_MENU ||
7181 win_type == ECORE_X_WINDOW_TYPE_NOTIFICATION) {
7190 * @brief Callback function for focus out event of application window
7192 * @param data Data to pass when it is called.
7194 * @return ECORE_CALLBACK_RENEW
7196 static Eina_Bool x_event_window_focus_out_cb (void *data, int ev_type, void *event)
7198 Ecore_X_Event_Window_Focus_Out *e = (Ecore_X_Event_Window_Focus_Out*)event;
7200 if (e && e->win == _app_window) {
7201 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7202 if (check_focus_out_by_popup_win ())
7203 return ECORE_CALLBACK_RENEW;
7205 #if ENABLE_MULTIWINDOW_SUPPORT
7206 unsigned int layout = 0;
7207 LOGD ("Application window focus OUT!");
7208 delete_ise_hide_timer ();
7210 // Check multi window mode
7211 if (ecore_x_window_prop_card32_get (efl_get_app_window (), ECORE_X_ATOM_E_WINDOW_DESKTOP_LAYOUT, &layout, 1) != -1) {
7212 if (layout == 0 || layout == 1) {
7214 LOGD ("Multi window mode. start timer to hide IME");
7216 // Use timer not to hide and show IME again in focus-out and focus-in event between applications
7217 _ise_hide_timer = ecore_timer_add (ISF_ISE_HIDE_DELAY, ise_hide_timeout, NULL);
7221 if (!_ise_hide_timer) {
7222 LOGD ("Panel hides ISE");
7223 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7225 ui_candidate_hide (true, false, false);
7228 LOGD ("Application window focus OUT! Panel hides ISE");
7229 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7231 ui_candidate_hide (true, false, false);
7236 return ECORE_CALLBACK_RENEW;
7240 static void restore_config ()
7242 if (!_config.null ()) {
7243 String uuid = _initial_ise_uuid;
7245 String global_uuid = scim_global_config_read (String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String(""));
7246 if (global_uuid.length () > 0) uuid = global_uuid;
7248 String default_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
7249 if (default_uuid.length() > 0) uuid = default_uuid;
7251 if (global_uuid.length() == 0) {
7252 scim_global_config_write (String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), uuid);
7254 if (default_uuid.length() == 0) {
7255 _config->write (SCIM_CONFIG_DEFAULT_HELPER_ISE, uuid);
7258 scim_global_config_flush ();
7261 scim_global_config_reload ();
7267 * @brief : Launches default soft keyboard for performance enhancement (It's not mandatory)
7269 static void launch_default_soft_keyboard (keynode_t *key, void* data)
7271 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7274 if (!_config.null()) {
7275 helper_uuid = _config->read(SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
7277 if (helper_uuid.length () > 0) {
7278 /* Start default ISE */
7279 change_keyboard_mode (TOOLBAR_HELPER_MODE);
7281 if (!_launch_ise_on_request) {
7282 set_temporary_ise (_initial_ise_uuid);
7288 static String sanitize_string (const char *str, int maxlen = 32)
7291 static char acceptables[] =
7292 "abcdefghijklmnopqrstuvwxyz"
7293 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7296 char *newstr = NULL;
7298 newstr = new char[maxlen + 1];
7302 memset (newstr, 0x00, sizeof (char) * (maxlen + 1));
7305 while (len < maxlen && str[len] != '\0' && strchr (acceptables, str[len]) != NULL) {
7306 newstr[len] = str[len];
7316 static Eina_Bool monitor_user_data_path_timer(void *data)
7318 const char *path = static_cast<const char*>(data);
7319 bool user_data_path_exists = g_file_test (path, G_FILE_TEST_EXISTS);
7320 bool user_data_path_is_dir = g_file_test (path, G_FILE_TEST_IS_DIR);
7321 if (user_data_path_exists && user_data_path_is_dir) {
7322 LOGW ("'%s' exists : %d, is_dir : %d", path,
7323 (user_data_path_exists ? 1 : 0), (user_data_path_is_dir ? 1 : 0));
7325 scim_global_config_reload (true);
7329 /* Read all ime info from db */
7331 isf_pkg_select_all_ime_info_db (_ime_info);
7334 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
7337 if (_launch_ise_on_request) {
7340 String default_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
7342 set_active_ise (default_ise_uuid, launch);
7346 g_monitor_user_data_path_timer = NULL;
7347 return ECORE_CALLBACK_CANCEL;
7350 return ECORE_CALLBACK_RENEW;
7353 int main (int argc, char *argv [])
7355 struct tms tiks_buf;
7356 _clock_start = times (&tiks_buf);
7361 bool daemon = false;
7362 bool should_resident = true;
7365 char **new_argv = new char * [40];
7366 int display_name_c = 0;
7367 ConfigModule *config_module = NULL;
7368 String config_name = String ("simple");
7369 String display_name = String ();
7370 char buf[256] = {0};
7372 String user_data_path = String ();
7373 bool user_data_path_exists = false;
7374 bool user_data_path_is_dir = false;
7377 Ecore_Event_Handler *xclient_message_handler = NULL;
7378 Ecore_Event_Handler *xwindow_property_handler = NULL;
7379 Ecore_Event_Handler *xwindow_focus_out_handler = NULL;
7382 check_time ("\nStarting ISF Panel EFL...... ");
7383 ISF_SAVE_LOG ("Starting ISF Panel EFL......");
7385 DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
7386 DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
7388 /* Parse command options */
7394 if (String ("-c") == argv [i] || String ("--config") == argv [i]) {
7396 std::cerr << "no argument for option " << argv [i-1] << "\n";
7400 config_name = argv [i];
7404 if (String ("-h") == argv [i] || String ("--help") == argv [i]) {
7405 std::cout << "Usage: " << argv [0] << " [option]...\n\n"
7406 << "The options are: \n"
7407 << " --display DISPLAY Run on display DISPLAY.\n"
7408 << " -c, --config NAME Uses specified Config module.\n"
7409 << " -d, --daemon Run " << argv [0] << " as a daemon.\n"
7410 << " -ns, --no-stay Quit if no connected client.\n"
7412 << " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
7413 << " -o, --output FILE Output debug information into FILE.\n"
7415 << " -h, --help Show this help message.\n";
7420 if (String ("-d") == argv [i] || String ("--daemon") == argv [i]) {
7425 if (String ("-ns") == argv [i] || String ("--no-stay") == argv [i]) {
7426 should_resident = false;
7430 if (String ("-v") == argv [i] || String ("--verbose") == argv [i]) {
7432 std::cerr << "no argument for option " << argv [i-1] << "\n";
7436 DebugOutput::set_verbose_level (atoi (argv [i]));
7440 if (String ("-o") == argv [i] || String ("--output") == argv [i]) {
7442 std::cerr << "No argument for option " << argv [i-1] << "\n";
7446 DebugOutput::set_output (sanitize_string (argv [i]));
7450 if (String ("--display") == argv [i]) {
7452 std::cerr << "No argument for option " << argv [i-1] << "\n";
7456 display_name = sanitize_string (argv [i]);
7460 if (String ("--") == argv [i])
7463 std::cerr << "Invalid command line option: " << argv [i] << "\n";
7466 } /* End of command line parsing. */
7469 new_argv [new_argc ++] = argv [0];
7471 /* Store the rest argvs into new_argv. */
7472 for (++i; i < argc && new_argc < 37; ++i) {
7473 new_argv [new_argc ++] = argv [i];
7476 /* Make up DISPLAY env. */
7477 if (display_name.length ()) {
7478 new_argv [new_argc ++] = const_cast <char*> ("--display");
7479 display_name_c = new_argc;
7480 new_argv [new_argc ++] = strdup (display_name.c_str ());
7482 setenv ("DISPLAY", display_name.c_str (), 1);
7485 new_argv [new_argc] = 0;
7488 if (!config_name.length ()) {
7489 std::cerr << "No Config module is available!\n";
7494 /* Get current display. */
7496 const char *p = getenv ("DISPLAY");
7498 display_name = String (p);
7501 snprintf (buf, sizeof (buf), "config_name=%s display_name=%s", config_name.c_str (), display_name.c_str ());
7505 check_time ("ISF Panel EFL run as daemon");
7509 /* No loading default theme to reduce heap memory */
7510 setenv ("ELM_THEME", "", 1);
7512 #if ISF_BUILD_CANDIDATE_UI
7513 elm_init (argc, argv);
7516 ecore_app_args_set(argc, (const char **)argv);
7517 #endif /* CANDIDATE */
7519 check_time ("elm_init");
7523 #if ISF_BUILD_CANDIDATE_UI
7524 elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
7525 #endif /* CANDIDATE */
7527 if (config_name != "dummy") {
7528 /* Load config module */
7529 config_module = new ConfigModule (config_name);
7531 if (!config_module || !config_module->valid ()) {
7532 std::cerr << "Can not load " << config_name << " Config module.\n";
7537 _config = new DummyConfig ();
7540 /* Create config instance */
7541 if (_config.null () && config_module && config_module->valid ())
7542 _config = config_module->create_config ();
7543 if (_config.null ()) {
7544 std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
7548 ConfigBase::set (_config);
7549 check_time ("create config instance");
7554 if (!initialize_panel_agent (_config, display_name, should_resident)) {
7555 check_time ("Failed to initialize Panel Agent!");
7556 std::cerr << "Failed to initialize Panel Agent!\n";
7557 LOGE ("Failed to initialize Panel Agent!");
7561 } catch (scim::Exception & e) {
7562 std::cerr << e.what () << "\n";
7567 check_time ("initialize_panel_agent");
7569 #if ISF_BUILD_CANDIDATE_UI
7570 /* Initialize global variables and pointers for candidate items and etc. */
7571 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; i++) {
7572 _candidate_0 [i] = NULL;
7573 _seperate_0 [i] = NULL;
7574 _seperate_items [i] = NULL;
7576 _line_items [i] = NULL;
7577 _candidate_text [i] = NULL;
7578 _candidate_image [i] = NULL;
7579 _candidate_pop_image [i] = NULL;
7581 #endif /* CANDIDATE */
7583 /* Connect the configuration reload signal. */
7584 _config_connection = _config->signal_connect_reload (slot (config_reload_cb));
7587 if (!efl_create_control_window ()) {
7588 LOGW ("Failed to create control window");
7593 #if ISF_BUILD_CANDIDATE_UI
7594 efl_get_screen_resolution (_screen_width, _screen_height);
7596 _width_rate = (float)(_screen_width / 720.0);
7597 _height_rate = (float)(_screen_height / 1280.0);
7598 _blank_width = (int)(_blank_width * _width_rate);
7599 _item_min_width = (int)(_item_min_width * _width_rate);
7600 _item_min_height = (int)(_item_min_height * _height_rate);
7601 _candidate_width = (int)(_candidate_port_width * _width_rate);
7602 _candidate_height = (int)(_candidate_port_height_min * _height_rate);
7603 _indicator_height = (int)(_indicator_height * _height_rate);
7605 _aux_font_size = (int)(_aux_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7606 _candidate_font_size = (int)(_candidate_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7607 #endif /* CANDIDATE */
7609 /* Load ISF configuration */
7610 user_data_path = scim_get_user_data_dir ();
7611 user_data_path_exists = g_file_test (user_data_path.c_str(), G_FILE_TEST_EXISTS);
7612 user_data_path_is_dir = g_file_test (user_data_path.c_str(), G_FILE_TEST_IS_DIR);
7613 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
7614 if (vconf_set_bool (VCONFKEY_ISF_IME_LAUNCH_ON_DEMAND, _launch_ise_on_request) != 0)
7615 LOGW ("Failed to set vconf key");
7617 if (user_data_path_exists && user_data_path_is_dir) {
7620 LOGW ("'%s' exists : %d, is_dir : %d", user_data_path.c_str (),
7621 (user_data_path_exists ? 1 : 0), (user_data_path_is_dir ? 1 : 0));
7622 g_monitor_user_data_path_timer = ecore_timer_add (1.0, monitor_user_data_path_timer, user_data_path.c_str ());
7624 check_time("load_config");
7628 lang_str = vconf_get_str (VCONFKEY_LANGSET);
7629 set_language_and_locale (lang_str);
7633 /* Add callback function for input language and display language */
7634 vconf_notify_key_changed (VCONFKEY_LANGSET, display_language_changed_cb, NULL);
7635 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
7639 /* Update ISE list */
7640 std::vector<String> list;
7641 update_ise_list (list);
7643 /* Load initial ISE information */
7644 _initial_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_INITIAL_ISE_UUID), String (SCIM_COMPOSE_KEY_FACTORY_UUID));
7646 /* Check if SCIM_CONFIG_DEFAULT_HELPER_ISE is available. If it's not, set it as _initial_ise_uuid.
7647 e.g., This might be necessary when the platform is upgraded from 2.3 to 2.4. */
7648 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
7649 if (_initial_ise_uuid.length() > 0 && helper_uuid != _initial_ise_uuid) {
7651 for (unsigned int u = 0; u < _ime_info.size (); u++) {
7652 if (_ime_info[u].mode == TOOLBAR_HELPER_MODE && helper_uuid == _ime_info[u].appid) {
7658 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), _initial_ise_uuid);
7662 /* Request to terminate active IME */
7663 terminate_active_ise (_initial_ise_uuid);
7665 _preloading_ise = !_launch_ise_on_request;
7667 /* Launches default soft keyboard when all conditions are satisfied */
7668 launch_default_soft_keyboard ();
7670 /* Update the name of each ISE according to display language */
7671 update_ise_locale ();
7672 } catch (scim::Exception & e) {
7673 std::cerr << e.what () << "\n";
7674 } catch (std::logic_error & e) {
7675 std::cerr << e.what () << "\n";
7678 xclient_message_handler = ecore_event_handler_add (ECORE_X_EVENT_CLIENT_MESSAGE, x_event_client_message_cb, NULL);
7679 xwindow_property_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, x_event_window_property_cb, NULL);
7680 xwindow_focus_out_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_FOCUS_OUT, x_event_window_focus_out_cb, NULL);
7683 #if ENABLE_REMOTE_INPUT
7685 launch_remote_input = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_REMOTE_INPUT), launch_remote_input);
7687 /* Create remote input */
7688 if (launch_remote_input) {
7689 LOGD("remote input start");
7690 remote_input_impl = new Remote_Input();
7691 if (remote_input_impl) {
7692 remote_input_impl->init(_info_manager);
7698 #if ISF_BUILD_CANDIDATE_UI
7699 _system_scale = elm_config_scale_get ();
7701 /* Set elementary scale */
7702 if (_screen_width) {
7703 _app_scale = _screen_width / 720.0;
7704 elm_config_scale_set (_app_scale);
7706 snprintf (buf, sizeof (buf), "%4.3f", _app_scale);
7707 setenv ("ELM_SCALE", buf, 1);
7709 #endif /* CANDIDATE */
7711 signal (SIGQUIT, signalhandler);
7712 signal (SIGTERM, signalhandler);
7713 signal (SIGINT, signalhandler);
7714 signal (SIGHUP, signalhandler);
7716 check_time ("EFL Panel launch time");
7718 if (!isf_cynara_initialize())
7719 LOGW ("Failed to initialize cynara");
7721 clear_cpu_boosting();
7723 #if ISF_BUILD_CANDIDATE_UI
7726 ecore_main_loop_begin ();
7727 #endif /* CANDIDATE */
7729 LOGW("out of loop");
7731 isf_cynara_finish();
7736 if (g_monitor_user_data_path_timer) {
7737 ecore_timer_del (g_monitor_user_data_path_timer);
7738 g_monitor_user_data_path_timer = NULL;
7742 if (xclient_message_handler) {
7743 ecore_event_handler_del (xclient_message_handler);
7744 xclient_message_handler = NULL;
7747 if (xwindow_property_handler) {
7748 ecore_event_handler_del (xwindow_property_handler);
7749 xwindow_property_handler = NULL;
7752 if (xwindow_focus_out_handler) {
7753 ecore_event_handler_del (xwindow_focus_out_handler);
7754 xwindow_focus_out_handler = NULL;
7759 /* Remove callback function for input language and display language */
7760 vconf_ignore_key_changed (VCONFKEY_LANGSET, display_language_changed_cb);
7761 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
7765 #if ISF_BUILD_CANDIDATE_UI
7766 ui_destroy_candidate_window ();
7767 ui_candidate_delete_check_size_timer ();
7768 ui_candidate_delete_longpress_timer ();
7769 ui_candidate_delete_destroy_timer ();
7770 #endif /* CANDIDATE */
7771 #ifdef HAVE_PKGMGR_INFO
7773 package_manager_destroy (pkgmgr);
7777 delete_ise_check_pid_alive_timer();
7779 if (_info_manager) {
7781 _info_manager->stop ();
7782 } catch (scim::Exception & e) {
7783 std::cerr << "Exception is thrown from _info_manager->stop (), error is " << e.what () << "\n";
7785 delete _info_manager;
7787 _config_connection.disconnect ();
7788 if (!_config.null ())
7790 ConfigBase::set (0);
7793 delete config_module;
7795 #if ISF_BUILD_CANDIDATE_UI
7799 #endif /* CANDIDATE */
7802 if ((display_name_c > 0) && new_argv [display_name_c]) {
7803 free (new_argv [display_name_c]);
7808 ISF_SAVE_LOG ("ret=%d", ret);
7810 std::cerr << "Successfully exited.\n";
7813 std::cerr << "Abnormally exited.\n";
7819 vi:ts=4:nowrap:expandtab