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);
250 #if ENABLE_REMOTE_INPUT
251 static void slot_send_remote_input_message (const String &msg, bool len);
252 static void slot_recv_remote_surrounding_text (int cursor, const String &text);
256 static Eina_Bool efl_create_control_window (void);
257 static Ecore_X_Window efl_get_app_window (void);
258 static Ecore_X_Window efl_get_quickpanel_window (void);
259 static Ecore_X_Window efl_get_global_navigation_window (void);
262 static void change_keyboard_mode (TOOLBAR_MODE_T mode);
263 static unsigned int get_ise_index (const String uuid);
264 static bool set_active_ise (const String &uuid, bool launch_ise);
265 static bool update_ise_list (std::vector<String> &list);
266 static void update_ise_locale (const char *lang = NULL);
267 #ifdef HAVE_NOTIFICATION
268 static void delete_notification (NotificationData *noti_data);
269 static void create_notification (NotificationData *noti_data);
270 static void show_ime_selector_notification (void);
272 static void set_language_and_locale (const char *lang_str);
273 static bool app_control_launch (const char *app_id);
274 static void terminate_active_ise (const String uuid);
275 static void set_cpu_boosting (void);
276 static void clear_cpu_boosting (void);
278 /////////////////////////////////////////////////////////////////////////////
279 // Declaration of internal variables.
280 /////////////////////////////////////////////////////////////////////////////
281 #if ISF_BUILD_CANDIDATE_UI
282 static Evas_Object *_candidate_window = 0;
283 static Evas_Object *_candidate_area_1 = 0;
284 static Evas_Object *_candidate_area_2 = 0;
285 static Evas_Object *_candidate_bg = 0;
286 static Evas_Object *_candidate_0_scroll = 0;
287 static Evas_Object *_candidate_scroll = 0;
288 static Evas_Object *_scroller_bg = 0;
289 static Evas_Object *_candidate_0_table = 0;
290 static Evas_Object *_candidate_table = 0;
291 static Evas_Object *_candidate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
292 static Evas_Object *_candidate_text [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
293 static Evas_Object *_candidate_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
294 static Evas_Object *_candidate_pop_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
295 static Evas_Object *_seperate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
296 static Evas_Object *_seperate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
297 static Evas_Object *_line_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
298 static Evas_Object *_line_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
299 static Evas_Object *_more_btn = 0;
300 static Evas_Object *_close_btn = 0;
301 static bool _candidate_show_requested = false;
302 #endif /* CANDIDATE */
303 static bool _updated_hide_state_geometry = false;
304 #if ISF_BUILD_CANDIDATE_UI
305 static int _candidate_x = 0;
306 static int _candidate_y = 0;
307 static int _candidate_width = 0;
308 static int _candidate_height = 0;
309 static int _soft_candidate_width = 0;
310 static int _soft_candidate_height = 0;
311 static int _candidate_valid_height = 0;
313 static bool _candidate_area_1_visible = false;
314 static bool _candidate_area_2_visible = false;
315 static bool _aux_area_visible = false;
316 #endif /* CANDIDATE */
318 static ISF_CANDIDATE_MODE_T _candidate_mode = SOFT_CANDIDATE_WINDOW;
319 static ISF_CANDIDATE_PORTRAIT_LINE_T _candidate_port_line = ONE_LINE_CANDIDATE;
321 #if ISF_BUILD_CANDIDATE_UI
322 static int _candidate_port_width = 480;
323 static int _candidate_port_height_min = 76;
324 static int _candidate_port_height_min_2 = 150;
325 static int _candidate_port_height_max = 286;
326 static int _candidate_port_height_max_2 = 350;
327 static int _candidate_land_width = 784;
328 static int _candidate_land_height_min = 84;
329 static int _candidate_land_height_min_2 = 168;
330 static int _candidate_land_height_max = 150;
331 static int _candidate_land_height_max_2 = 214;
332 static int _candidate_area_1_pos [2] = {0, 2};
333 static int _more_btn_pos [4] = {369, 11, 689, 11};
334 static int _close_btn_pos [4] = {362, 211, 682, 75};
335 static int _more_btn_width = 80;
336 static int _more_btn_height = 64;
338 static int _h_padding = 4;
339 static int _v_padding = 2;
340 static int _item_min_width = 99;
341 static int _item_min_height = 82;
343 static int _candidate_scroll_0_width_min = 350;
344 static int _candidate_scroll_0_width_max = 670;
346 static int _candidate_scroll_width = 453;
347 static int _candidate_scroll_width_min = 453;
348 static int _candidate_scroll_width_max = 663;
349 static int _candidate_scroll_height_min = 124;
350 static int _candidate_scroll_height_max = 190;
352 const int MORE_BUTTON_INDEX = -1;
353 const int CLOSE_BUTTON_INDEX = -2;
354 static uint32 _candidate_display_number = 0;
355 static std::vector<uint32> _candidate_row_items;
356 static Evas_Object *_tts_focus_rect = 0;
357 static bool _wait_stop_event = false;
359 static Evas_Object *_preedit_window = 0;
360 static Evas_Object *_preedit_text = 0;
361 static int _preedit_width = 100;
362 static int _preedit_height = 54;
364 static Evas_Object *_aux_area = 0;
365 static Evas_Object *_aux_line = 0;
366 static Evas_Object *_aux_table = 0;
367 static int _aux_height = 0;
368 static int _aux_port_width = 444;
369 static int _aux_land_width = 764;
370 static std::vector<Evas_Object *> _aux_items;
371 static std::vector<Evas_Object *> _aux_seperates;
373 static Evas_Object *_tmp_preedit_text = 0;
374 static Evas_Object *_tmp_aux_text = 0;
375 static Evas_Object *_tmp_candidate_text = 0;
377 static int _spot_location_x = -1;
378 static int _spot_location_y = -1;
379 static int _spot_location_top_y = -1;
380 static int _candidate_angle = 0;
381 static int _ise_width = 0;
382 static int _ise_height = 0;
383 #endif /* CANDIDATE */
385 static int _ise_angle = -1;
386 static int _ise_x = 0;
387 static int _ise_y = 0;
388 static WINDOW_STATE _ise_state = WINDOW_STATE_HIDE;
389 static WINDOW_STATE _candidate_state = WINDOW_STATE_HIDE;
391 #if ISF_BUILD_CANDIDATE_UI
392 static int _indicator_height = 0;//24;
393 static int _screen_width = 720;
394 static int _screen_height = 1280;
395 static float _width_rate = 1.0;
396 static float _height_rate = 1.0;
397 static int _blank_width = 30;
399 static String _candidate_name = String ("candidate");
400 static String _candidate_edje_file = String (EFL_CANDIDATE_THEME1);
402 static String _candidate_font_name = String ("Tizen");
403 static int _candidate_font_size = 38;
404 static int _aux_font_size = 38;
405 static int _click_object = 0;
406 static int _click_down_pos [2] = {0, 0};
407 static int _click_up_pos [2] = {0, 0};
408 static bool _is_click = true;
409 #endif /* CANDIDATE */
410 static String _initial_ise_uuid = String ("");
411 static String _locale_string = String ("");
412 static ConfigPointer _config;
413 static Connection _config_connection;
415 static InfoManager *_info_manager = 0;
417 static clock_t _clock_start;
419 #if ISF_BUILD_CANDIDATE_UI
420 static Ecore_Timer *_check_size_timer = NULL;
421 static Ecore_Timer *_longpress_timer = NULL;
422 static Ecore_Timer *_destroy_timer = NULL;
423 #endif /* CANDIDATE */
424 #if ISF_BUILD_CANDIDATE_UI
425 static Ecore_Timer *_candidate_hide_timer = NULL;
426 #endif /* CANDIDATE */
427 static Ecore_Timer *_ise_hide_timer = NULL;
430 static Ecore_X_Window _ise_window = 0;
431 static Ecore_X_Window _app_window = 0;
432 static Ecore_X_Window _control_window = 0;
433 static Ecore_X_Window _input_win = 0;
436 #ifdef HAVE_PKGMGR_INFO
437 static package_manager_h pkgmgr = NULL;
438 static VectorPairStringUint32 g_pkgids_to_be_uninstalled;
439 static Ecore_Timer *g_release_uninstalled_ime_info_timer = NULL;
440 static String g_stopped_helper_pkgid = "";
441 static Ecore_Timer *g_start_default_helper_timer = NULL;
442 static VectorPairStringUint32 g_pkgids_to_be_updated_and_installed;
443 static String g_updated_helper_pkgid = "";
446 static bool _launch_ise_on_request = false;
447 static bool _auto_destroy_ise = false;
448 static bool _soft_keyboard_launched = false;
449 static bool _focus_in = false;
450 static bool _enable_auto_restart = true;
452 #if ISF_BUILD_CANDIDATE_UI
453 static bool candidate_expanded = false;
454 static int _candidate_image_count = 0;
455 static int _candidate_text_count = 0;
456 static int _candidate_pop_image_count = 0;
457 static int candidate_image_height = 38;
458 static int candidate_play_image_width_height = 19;
460 static const int CANDIDATE_TEXT_OFFSET = 2;
462 static double _app_scale = 1.0;
463 static double _system_scale = 1.0;
464 #endif /* CANDIDATE */
466 #ifdef HAVE_NOTIFICATION
467 static NotificationData hwkbd_module_noti = {"Input detected from hardware keyboard", "Tap to use virtual keyboard", ISF_KEYBOARD_ICON_FILE, "", 0};
468 static NotificationData ise_selector_module_noti = {"Select input method", "", "", "", 0};
471 #if ISF_BUILD_CANDIDATE_UI
474 static bool feedback_initialized = false;
476 #endif /* CANDIDATE */
478 #if ENABLE_REMOTE_INPUT
479 static Remote_Input* remote_input_impl = NULL;
480 static bool launch_remote_input = false;
483 #if ISF_BUILD_CANDIDATE_UI
485 static Ecore_Event_Handler *_candidate_show_handler = NULL;
487 #endif /* CANDIDATE */
489 static String ime_selector_app = "";
490 static String ime_list_app = "";
492 static Ecore_Timer *_ise_check_pid_alive_timer = NULL;
493 static const double _ise_check_pid_alive_time = 3.0f;
494 static String _ise_check_pid_alive_uuid;
496 static Ecore_Timer *g_monitor_user_data_path_timer = NULL;
498 #if ISF_BUILD_CANDIDATE_UI
500 EMOJI_IMAGE_WIDTH = 0,
503 EMOJI_IMAGE_TAG_FLAG,
504 EMOJI_IMAGE_POP_FLAG,
511 int emoji_option[EMOJI_IMAGE_END];
515 /* This structure stores the geometry information reported by ISE */
518 bool valid; /* Whether this information is currently valid */
519 int angle; /* For which angle this information is useful */
520 struct rectinfo geometry; /* Geometry information */
523 static struct GeometryCache _ise_reported_geometry = {0, 0, {0, 0, 0, 0}};
524 static struct GeometryCache _portrait_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
525 static struct GeometryCache _landscape_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
528 static void get_input_window (void)
531 Ecore_X_Atom atom = 0;
533 if (_input_win == 0) {
534 atom = ecore_x_atom_get (E_PROP_DEVICEMGR_INPUTWIN);
535 win_ret = ecore_x_window_prop_window_get (ecore_x_window_root_first_get (), atom, &_input_win, 1);
536 if (_input_win == 0 || win_ret < 1) {
537 LOGW ("Input window is NULL!");
539 ecore_x_event_mask_set (_input_win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
545 static int pkgmgr_get_appinfo (const char *appid, pkgmgrinfo_appinfo_h *handle)
548 /* Try to get in global packages */
549 ret = pkgmgrinfo_appinfo_get_appinfo (appid, handle);
550 if (ret != PMINFO_R_OK) {
551 LOGW ("[pkgmgrinfo_appinfo_get_appinfo] appid : '%s', ret : %d, uid : %d", appid, ret, getuid ());
552 /* Try to get in user packages */
553 ret = pkgmgrinfo_appinfo_get_usr_appinfo (appid, getuid (), handle);
554 if (ret != PMINFO_R_OK)
555 LOGW ("[pkgmgrinfo_appinfo_get_usr_appinfo] appid : '%s', ret : %d", appid, ret);
561 #ifdef HAVE_NOTIFICATION
562 static void delete_notification (NotificationData *noti_data)
564 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
566 if (!_MOBILE && !_COMMON) return;
568 if (noti_data->noti_id != 0) {
569 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
570 LOGD ("deleted notification : %s", noti_data->launch_app.c_str ());
571 noti_data->noti_id = 0;
575 static void create_notification (NotificationData *noti_data)
577 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
579 notification_h notification = NULL;
582 if (!_MOBILE && !_COMMON) return;
584 if (noti_data->noti_id != 0) {
585 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
586 noti_data->noti_id = 0;
589 notification = notification_create (NOTIFICATION_TYPE_ONGOING);
590 if (notification != NULL) {
591 notification_set_pkgname (notification, "isf-panel-efl");
592 notification_set_layout (notification, NOTIFICATION_LY_ONGOING_EVENT);
593 notification_set_image (notification, NOTIFICATION_IMAGE_TYPE_ICON, noti_data->icon.c_str());
594 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_TITLE, _(noti_data->title.c_str()), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
595 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_CONTENT, _(noti_data->content.c_str ()), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
596 notification_set_display_applist (notification, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
598 app_control_h service = NULL;
599 if (app_control_create (&service) == APP_CONTROL_ERROR_NONE) {
600 app_control_set_operation (service, APP_CONTROL_OPERATION_DEFAULT);
601 app_control_set_app_id (service, noti_data->launch_app.c_str ());
603 ret = notification_set_launch_option (notification, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)service);
604 if (ret != NOTIFICATION_ERROR_NONE) {
605 LOGW ("Failed to set launch option. error code : %d", ret);
607 ret = notification_insert (notification, ¬i_data->noti_id);
608 if (ret != NOTIFICATION_ERROR_NONE) {
609 LOGW ("Failed to insert notification. error code : %d", ret);
611 app_control_destroy (service);
614 LOGW ("Failed to create appcontrol");
616 notification_free (notification);
619 LOGW ("Failed to create notification");
622 #endif /* HAVE_NOTIFICATION */
624 #if ISF_BUILD_CANDIDATE_UI
625 static bool tokenize_tag (const String& str, struct image *image_token)
627 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
628 if (str.length () <= 0) {
629 LOGW ("str is empty!!!");
633 char **tag_str = NULL;
635 tag_str = eina_str_split (str.c_str (), "\u3013", 0);
640 for (i = 0; tag_str [i]; i++) {
642 if (str.length () == strlen (tag_str[i])) {
652 image_token->path = String (tag_str[i]);
654 if (i - 1 < EMOJI_IMAGE_END)
655 image_token->emoji_option [i - 1] = atoi (tag_str[i]);
657 LOGW ("emoji option is more than EMOJI_IMAGE_END!!!");
669 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)
671 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
673 struct image image_data;
674 int object_width = 0, text_width = 0, image_width = 0, image_height = 0, max_width = 0, button_width = 0;
676 int image_get_width = 0, image_get_height = 0;
677 char image_key [10] = {0, };
678 char **splited_string = NULL;
679 char **sub_splited_string = NULL;
680 double image_rate = 0.0;
681 bool tokenize_result = false;
682 bool candidate_is_long = false;
684 Evas_Object *candidate_object_table = NULL;
685 Evas_Object *candidate_object_table_bg_rect = NULL;
686 Evas_Object *candidate_left_padding = NULL;
688 candidate_object_table = elm_table_add (parent);
690 candidate_left_padding = evas_object_rectangle_add (evas_object_evas_get (parent));
691 evas_object_size_hint_weight_set (candidate_left_padding, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
692 evas_object_size_hint_align_set (candidate_left_padding, EVAS_HINT_FILL, EVAS_HINT_FILL);
693 evas_object_size_hint_min_set (candidate_left_padding, _blank_width, 1);
694 evas_object_color_set (candidate_left_padding, 0, 0, 0, 0);
695 elm_table_pack (candidate_object_table, candidate_left_padding, 0, 0, _blank_width, 1);
696 evas_object_show (candidate_left_padding);
698 object_width += _blank_width;
699 if (item_num > 1 && item_index == 0)
700 button_width = 92 * _width_rate;
704 splited_string = eina_str_split (str.c_str (), "\uE000", 0);
705 if (splited_string) {
706 for (i = 0; splited_string [i]; i++) {
707 if (candidate_is_long)
709 sub_splited_string = eina_str_split (splited_string [i], "\uE001", 0);
710 if (sub_splited_string) {
711 for (j = 0; sub_splited_string [j]; j++) {
712 if (candidate_is_long)
714 tokenize_result = tokenize_tag (sub_splited_string [j], &image_data);
715 if (tokenize_result && _candidate_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
716 _candidate_image [_candidate_image_count] = elm_image_add (parent);
717 snprintf (image_key, sizeof (image_key), "%d", _candidate_image_count);
718 elm_image_file_set (_candidate_image [_candidate_image_count], image_data.path.c_str (), image_key);
719 elm_image_animated_set (_candidate_image [_candidate_image_count], EINA_TRUE);
720 elm_image_animated_play_set (_candidate_image [_candidate_image_count], EINA_TRUE);
721 elm_image_object_size_get (_candidate_image [_candidate_image_count], &image_get_width, &image_get_height);
722 LOGD ("image_path=%s, key=%s", image_data.path.c_str (), image_key);
724 if (image_get_height > image_get_width)
725 image_rate = ((double)candidate_image_height / (double)image_get_width);
727 image_rate = ((double)candidate_image_height / (double)image_get_height);
729 image_width = (int)((double)image_get_width * image_rate);
730 image_height = candidate_image_height;
732 if (_candidate_angle == 90 || _candidate_angle == 270)
733 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
735 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
737 if (image_width > max_width) {
738 Evas_Object *candidate_end = edje_object_add (evas_object_evas_get (parent));
739 edje_object_file_set (candidate_end, _candidate_edje_file.c_str (), _candidate_name.c_str ());
740 evas_object_show (candidate_end);
741 edje_object_part_text_set (candidate_end, "candidate", "...");
742 edje_object_scale_set (_candidate_text [_candidate_text_count], _height_rate);
744 text_width = max_width;
745 evas_object_size_hint_min_set (candidate_end, text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
746 if (HighLight || SetBack) {
747 set_highlight_color (candidate_end, ForeGround, BackGround, SetBack);
749 elm_table_pack (candidate_object_table, candidate_end, object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
750 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
752 if (_candidate_image [_candidate_image_count]) {
753 evas_object_del (_candidate_image [_candidate_image_count]);
754 _candidate_image [_candidate_image_count] = NULL;
756 candidate_is_long = true;
760 evas_object_resize (_candidate_image [_candidate_image_count], image_width, image_height);
761 evas_object_show (_candidate_image [_candidate_image_count]);
762 evas_object_size_hint_min_set (_candidate_image [_candidate_image_count], image_width, image_height);
764 elm_table_pack (candidate_object_table, _candidate_image [_candidate_image_count], object_width, 1, image_width, image_height);
765 object_width += image_width;
766 _candidate_image_count++;
768 if (image_data.emoji_option [EMOJI_IMAGE_POP_FLAG] == 1 && image_width > 0 && _candidate_pop_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
769 _candidate_pop_image [_candidate_pop_image_count] = elm_image_add (parent);
770 elm_image_file_set (_candidate_pop_image [_candidate_pop_image_count], ISF_POP_PLAY_ICON_FILE, image_key);
771 evas_object_resize (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
772 evas_object_show (_candidate_pop_image [_candidate_pop_image_count]);
773 evas_object_size_hint_min_set (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
775 elm_table_pack (candidate_object_table, _candidate_pop_image [_candidate_pop_image_count],
776 object_width - candidate_play_image_width_height, image_height - candidate_play_image_width_height - 2,
777 candidate_play_image_width_height, candidate_play_image_width_height);
779 _candidate_pop_image_count++;
782 } else if (strlen (sub_splited_string [j]) > 0 && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
783 _candidate_text [_candidate_text_count] = edje_object_add (evas_object_evas_get (parent));
784 edje_object_file_set (_candidate_text [_candidate_text_count], _candidate_edje_file.c_str (), _candidate_name.c_str ());
785 evas_object_show (_candidate_text [_candidate_text_count]);
786 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", sub_splited_string [j]);
787 edje_object_text_class_set (_candidate_text [_candidate_text_count], "tizen",
788 _candidate_font_name.c_str (), _candidate_font_size);
789 evas_object_text_text_set (_tmp_candidate_text, sub_splited_string [j]);
790 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &text_width, NULL);
792 if (_candidate_angle == 90 || _candidate_angle == 270)
793 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
795 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
797 if (text_width > max_width) {
798 candidate_is_long = true;
799 /* In order to avoid overlap issue, calculate show_string */
800 String show_string = String (sub_splited_string [j]);
801 int show_length = text_width;
802 while (show_length > max_width && show_string.length () > 1) {
803 show_string = show_string.substr (0, show_string.length () - 1);
804 evas_object_text_text_set (_tmp_candidate_text, (show_string + String ("...")).c_str ());
805 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &show_length, NULL);
807 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", (show_string + String ("...")).c_str ());
808 text_width = max_width;
811 evas_object_size_hint_min_set (_candidate_text [_candidate_text_count], text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
812 if (HighLight || SetBack) {
813 set_highlight_color (_candidate_text [_candidate_text_count], ForeGround, BackGround, SetBack);
815 elm_table_pack (candidate_object_table, _candidate_text [_candidate_text_count], object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
816 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
817 _candidate_text_count++;
823 if (splited_string [0])
824 free (splited_string [0]);
826 free (splited_string);
829 if (sub_splited_string) {
830 if (sub_splited_string [0])
831 free (sub_splited_string [0]);
833 free (sub_splited_string);
836 *total_width = object_width + _blank_width;
838 candidate_object_table_bg_rect = edje_object_add (evas_object_evas_get (parent));
839 edje_object_file_set (candidate_object_table_bg_rect, _candidate_edje_file.c_str (), "candidate_object_table");
840 evas_object_size_hint_weight_set (candidate_object_table_bg_rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
841 evas_object_size_hint_align_set (candidate_object_table_bg_rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
842 evas_object_size_hint_min_set (candidate_object_table_bg_rect, *total_width, _item_min_height);
843 elm_table_pack (candidate_object_table, candidate_object_table_bg_rect, 0, 0, *total_width, _item_min_height);
844 evas_object_show (candidate_object_table_bg_rect);
846 evas_object_size_hint_align_set (candidate_object_table, EVAS_HINT_FILL, EVAS_HINT_FILL);
847 evas_object_size_hint_weight_set (candidate_object_table, EVAS_HINT_EXPAND, 0.0);
849 return candidate_object_table;
851 #endif /* CANDIDATE */
853 /////////////////////////////////////////////////////////////////////////////
854 // Implementation of internal functions.
855 /////////////////////////////////////////////////////////////////////////////
857 * @brief Print system time point for panel performance.
859 * @param strInfo The output information.
861 static void check_time (const char *strInfo)
863 gettime (_clock_start, strInfo);
864 ISF_LOG ("%s ppid=%d pid=%d\n", strInfo, getppid (), getpid ());
868 * @brief Flush memory for elm.
872 static void flush_memory (void)
874 #if ISF_BUILD_CANDIDATE_UI
875 elm_cache_all_flush ();
880 #if ISF_BUILD_CANDIDATE_UI
882 * @brief Get ISE geometry information.
883 * Returns the "expected" ISE geometry when kbd_state is ON, otherwise w/h set to 0
885 * @param info The data is used to store ISE position and size.
886 * @param kbd_state The keyboard state.
888 static struct rectinfo get_ise_geometry ()
890 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
892 struct rectinfo info = {0, 0, 0, 0};
896 Ecore_X_Window gnb_win = efl_get_global_navigation_window ();
898 ecore_x_window_size_get (gnb_win, &w, &h);
901 int win_w = _screen_width, win_h = _screen_height;
902 int angle = (_ise_angle == -1) ? efl_get_app_window_angle () : _ise_angle;
905 /* The height of global navigation bar */
908 if (angle == 90 || angle == 270) {
909 win_w = _screen_height;
910 win_h = _screen_width;
915 /* If we have geometry reported by ISE, use the geometry information */
916 if (_ise_reported_geometry.valid && _ise_reported_geometry.angle == angle) {
917 info = _ise_reported_geometry.geometry;
918 /* But still, if the current ISE is not in SHOW state, set w/h to 0 */
919 if (_ise_state != WINDOW_STATE_SHOW) {
920 info.pos_y = (win_h > win_w) ? win_h : win_w;
925 /* READ ISE's SIZE HINT HERE */
928 int pos_x, pos_y, width, height;
929 if (ecore_x_e_window_rotation_geometry_get (_ise_window, angle,
930 &pos_x, &pos_y, &width, &height)) {
934 if (angle == 90 || angle == 270) {
939 info.height = height;
942 info.pos_x = (int)info.width > win_w ? 0 : (win_w - info.width) / 2;
943 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
945 info.pos_y = (win_h > win_w) ? win_h : win_w;
949 if (_ise_state == WINDOW_STATE_SHOW) {
950 info.pos_y = win_h - info.height - gnb_height;
952 info.pos_y = (win_h > win_w) ? win_h : win_w;
958 LOGD ("angle : %d, w_angle : %d, mode : %d, Geometry : %d %d %d %d",
960 _info_manager->get_current_toolbar_mode (),
961 info.pos_x, info.pos_y, info.width, info.height);
970 // FIXME: Get the ISE's SIZE.
978 _ise_width = info.width;
979 _ise_height = info.height;
983 #endif /* CANDIDATE */
987 * @brief Set keyboard geometry for autoscroll.
988 * This includes the ISE geometry together with candidate window
990 * @param kbd_state The keyboard state.
992 static void set_keyboard_geometry_atom_info (Ecore_X_Window window, struct rectinfo ise_rect)
994 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
996 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
999 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1000 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1001 ise_rect.width = _candidate_width;
1002 ise_rect.height = _candidate_height;
1004 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
1005 ise_rect.width = _soft_candidate_width;
1006 ise_rect.height = _soft_candidate_height;
1009 int angle = efl_get_app_window_angle ();
1010 if (angle == 90 || angle == 270)
1011 ise_rect.pos_y = _screen_width - ise_rect.height;
1013 ise_rect.pos_y = _screen_height - ise_rect.height;
1015 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1016 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1017 _candidate_valid_height = ui_candidate_get_valid_height ();
1018 if ((_candidate_height - _candidate_valid_height) > _ise_height) {
1019 _candidate_valid_height = _candidate_height;
1020 ise_rect.pos_y = ise_rect.pos_y + ise_rect.height - _candidate_height;
1021 ise_rect.height = _candidate_height;
1023 ise_rect.pos_y -= _candidate_valid_height;
1024 ise_rect.height += _candidate_valid_height;
1030 ecore_x_e_illume_keyboard_geometry_set (window, ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1031 LOGD ("KEYBOARD_GEOMETRY_SET : %d %d %d %d", ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1032 SCIM_DEBUG_MAIN (3) << " KEYBOARD_GEOMETRY x=" << ise_rect.pos_x << " y=" << ise_rect.pos_y
1033 << " width=" << ise_rect.width << " height=" << ise_rect.height << "\n";
1035 /* even the kbd_state is OFF, consider the keyboard is still ON if we have candidate opened */
1036 if (ise_rect.width == 0 && ise_rect.height == 0) {
1037 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1039 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1041 if (_ise_angle == 0 || _ise_angle == 180) {
1042 _portrait_recent_ise_geometry.valid = true;
1043 _portrait_recent_ise_geometry.geometry = ise_rect;
1046 _landscape_recent_ise_geometry.valid = true;
1047 _landscape_recent_ise_geometry.geometry = ise_rect;
1054 * @brief Get ISE index according to uuid.
1056 * @param uuid The ISE uuid.
1058 * @return The ISE index
1060 static unsigned int get_ise_index (const String uuid)
1062 unsigned int index = 0;
1063 if (uuid.length () > 0) {
1064 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1065 if (uuid == _ime_info[i].appid) {
1075 static void set_keyboard_engine (String active_uuid)
1077 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
1078 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
1079 if (active_uuid != keyboard_uuid) {
1080 _info_manager->change_factory (active_uuid);
1081 _config->write (IMENGINE_KEY, active_uuid);
1086 static void _update_ime_info(void)
1088 std::vector<String> ise_langs;
1091 isf_pkg_select_all_ime_info_db(_ime_info);
1093 /* Update _groups */
1095 for (size_t i = 0; i < _ime_info.size (); ++i) {
1096 scim_split_string_list(ise_langs, _ime_info[i].languages);
1097 for (size_t j = 0; j < ise_langs.size (); j++) {
1098 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
1099 _groups[ise_langs[j]].push_back (i);
1105 static void _initialize_ime_info (void)
1107 std::vector<ImeInfoDB>::iterator iter;
1108 VectorPairStringUint32 ime_on_off;
1109 // Store is_enabled values of each keyboard
1110 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1111 if (iter->mode == TOOLBAR_HELPER_MODE) {
1112 ime_on_off.push_back (std::make_pair (iter->appid, iter->is_enabled));
1115 // Delete the whole ime_info DB and reload
1116 isf_db_delete_ime_info ();
1117 _update_ime_info ();
1118 // Restore is_enabled value to valid keyboards
1119 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1120 if (iter->mode == TOOLBAR_HELPER_MODE) {
1121 for (VectorPairStringUint32::iterator it = ime_on_off.begin (); it != ime_on_off.end (); it++) {
1122 if (it->first.compare (iter->appid) == 0) {
1123 if (it->second != iter->is_enabled) {
1124 iter->is_enabled = it->second;
1125 isf_db_update_is_enabled_by_appid (iter->appid.c_str (), static_cast<bool>(iter->is_enabled));
1127 ime_on_off.erase (it);
1135 #ifdef HAVE_PKGMGR_INFO
1137 * @brief Insert or update ime_info data with pkgid.
1139 * @param pkgid pkgid to insert/update ime_info table.
1141 * @return 1 on successful insert, 2 on successful update, -1 if pkgid is not IME package, otherwise return 0.
1143 static int _isf_insert_ime_info_by_pkgid(const char *pkgid)
1146 pkgmgrinfo_pkginfo_h handle = NULL;
1147 int result = 0; // 0: not IME, 1: Inserted, 2: Updated (because of the same appid)
1148 uid_t uid = getuid ();
1152 LOGW ("pkgid is null.");
1156 /* Try to get in global packages */
1157 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &handle);
1158 if (ret != PMINFO_R_OK) {
1159 /* Try to get in user packages */
1160 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, uid, &handle);
1161 if (ret != PMINFO_R_OK) {
1162 LOGW ("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", pkgid, ret, getuid ());
1171 /* Try to get in user packages */
1172 ret = pkgmgrinfo_appinfo_get_usr_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result, uid);
1175 /* Try to get in global packages */
1176 ret = pkgmgrinfo_appinfo_get_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result);
1179 if (ret != PMINFO_R_OK) {
1180 LOGW ("Failed to call %s failed(%d)", user ? "pkgmgrinfo_appinfo_get_usr_list" : "pkgmgrinfo_appinfo_get_list", ret);
1187 pkgmgrinfo_pkginfo_destroy_pkginfo (handle);
1193 * @brief Timer to start initial Helper ISE if the active (selected) 3rd party keyboard is uninstalled.
1195 * @param data User data
1197 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1198 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1200 static Eina_Bool _start_default_helper_timer(void *data)
1202 std::vector<String> total_appids;
1203 std::vector<ImeInfoDB>::iterator it;
1204 VectorPairStringUint32::iterator iter;
1206 /* Let panel know that ISE is deleted... */
1207 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1208 total_appids.push_back(it->appid);
1210 if (total_appids.size() > 0)
1211 _info_manager->update_ise_list (total_appids);
1213 LOGD ("Try to start the initial helper");
1214 set_active_ise(_initial_ise_uuid, true);
1216 for (iter = g_pkgids_to_be_uninstalled.begin (); iter != g_pkgids_to_be_uninstalled.end (); iter++) {
1217 if (iter->first.compare(g_stopped_helper_pkgid) == 0) {
1218 g_pkgids_to_be_uninstalled.erase (iter);
1222 g_stopped_helper_pkgid = "";
1224 g_start_default_helper_timer = NULL;
1225 return ECORE_CALLBACK_CANCEL;
1229 * @brief Timer to release uninstalled IME related info; g_pkgids_to_be_uninstalled has appid and is_enabled.
1231 * @param data User data
1233 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1234 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1236 static Eina_Bool _release_uninstalled_pkginfo_timer(void *data)
1238 g_pkgids_to_be_uninstalled.clear ();
1239 g_release_uninstalled_ime_info_timer = NULL;
1240 return ECORE_CALLBACK_CANCEL;
1244 * @brief Called when the package is installed, uninstalled or updated, and the progress of the request to the package manager changes.
1246 * @param[in] type The type of the package to be installed, uninstalled or updated
1247 * @param[in] package The name of the package to be installed, uninstalled or updated
1248 * @param[in] event_type The type of the request to the package manager
1249 * @param[in] event_state The current state of the request to the package manager
1250 * @param[in] progress The progress for the request that is being processed by the package manager \n
1251 * The range of progress is from 0 to 100
1252 * @param[in] error The error code when the package manager failed to process the request
1253 * @param[in] user_data The user data passed from package_manager_set_event_cb()
1254 * @see package_manager_set_event_cb()
1255 * @see package_manager_unset_event_cb()
1257 INFO: Package install/update/uninstall scenario
1258 Install and Uninstall are obviously simple.
1259 Install: just INSTALL
1260 Uninstall: just UNINSTALL
1261 Update package (change the source codes in IME project and Run As again), there are four scenarios:
1264 2. UNINSTALL -> INSTALL
1265 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1266 and change Application ID in tizen-manifest.xml file and Run As.
1267 3. UPDATE -> INSTALL
1268 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1269 and change Application ID in tizen-manifest.xml file and Run As.
1270 At UPDATE event, pkgid (package parameter) is invalid...
1272 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1273 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1275 If multiple packages (including non-IME pkgs) are uninstalled and installed; Z300H UPS (ultra power saving) mode scenario.
1276 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
1278 Assuming IMEngine won't be changed through this. IMEngine might have multiple appids for one pkgid.
1279 Assuming preinstalled IME won't be changed through this.
1281 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)
1283 String current_ime_appid; // now appid is uuid.
1284 std::vector<String> appids;
1285 std::vector<String> total_appids;
1286 std::vector<ImeInfoDB>::iterator it;
1287 std::vector<String>::iterator it2;
1288 VectorPairStringUint32::iterator it3;
1291 if (!package || !type)
1294 if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
1295 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1296 LOGD ("type=%s package=%s event_type=UPDATE event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1298 ret = _isf_insert_ime_info_by_pkgid (package); // If package is not IME, -1 would be returned.
1299 if (ret == 1) { // In case the package is updated with the changed appid. In this case, there will be two IMEs
1300 ret = isf_db_select_appids_by_pkgid (package, appids);
1302 if (_ime_info.size () > 0 && _ime_info [get_ise_index (appids.front ())].is_enabled)
1303 isf_db_update_is_enabled_by_appid (appids.back ().c_str (), true);
1304 isf_db_delete_ime_info_by_appid (appids.front ().c_str ());
1307 _update_ime_info ();
1309 /* Let panel know that ise list is changed... */
1310 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1311 total_appids.push_back(it->appid);
1313 if (total_appids.size() > 0)
1314 _info_manager->update_ise_list (total_appids);
1316 if (ret > 1 && _soft_keyboard_launched) { // If the previous appid of pkgid is the current IME, restart it with new appid.
1317 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1318 if (current_ime_appid.compare (appids.front ()) == 0) {
1319 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1320 _info_manager->hide_helper (current_ime_appid);
1321 _info_manager->stop_helper (current_ime_appid);
1322 LOGD ("Start IME(%s)", appids.back ().c_str ());
1323 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids.back ());
1324 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1325 _info_manager->start_helper (appids.back ());
1329 else if (ret == 2) { // In case IME package is just updated...
1330 _update_ime_info ();
1332 if (_soft_keyboard_launched) { // If package is the current IME, restart it.
1333 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1334 if (isf_db_select_appids_by_pkgid(package, appids)) {
1335 if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the current ISE package is updated, restart it.
1336 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1337 if (it->mode == TOOLBAR_HELPER_MODE && it->appid.compare(current_ime_appid) == 0) { // Make sure it's Helper ISE...
1338 LOGD ("Restart IME(%s)", current_ime_appid.c_str ());
1339 _info_manager->hide_helper (current_ime_appid);
1340 _info_manager->stop_helper (current_ime_appid);
1341 _info_manager->start_helper (current_ime_appid);
1349 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...
1350 if (isf_db_select_appids_by_pkgid(package, appids) == 1) {
1351 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1352 if (it->pkgid.compare(package) == 0) {
1353 g_pkgids_to_be_updated_and_installed.push_back (std::make_pair (it->pkgid, it->is_enabled));
1357 if (it == _ime_info.end ()) // Probably not going to happen.
1358 g_pkgids_to_be_updated_and_installed.push_back(std::make_pair (String(package), 0));
1360 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1361 if (_soft_keyboard_launched && std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the updated IME is the current ISE...
1362 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1363 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1364 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1365 _info_manager->hide_helper (current_ime_appid);
1366 _info_manager->stop_helper (current_ime_appid);
1367 _soft_keyboard_launched = false;
1368 g_updated_helper_pkgid = package;
1374 if (appids.size () > 0) // Probably appids size is 1.
1375 LOGD ("Delete IME(%s)", appids[0].c_str ());
1376 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1379 /* Let panel know that ise is deleted... */
1380 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1381 total_appids.push_back(it->appid);
1383 if (total_appids.size() > 0)
1384 _info_manager->update_ise_list (total_appids);
1388 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1393 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL) {
1394 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1395 LOGD ("type=%s package=%s event_type=INSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1397 ///////////////// UNINSTALL -> INSTALL and if the uninstalled IME is reinstalled /////////////////
1398 if (g_stopped_helper_pkgid.compare(package) == 0 && g_start_default_helper_timer) {
1399 LOGD ("Cancel timer to start the default IME");
1400 ecore_timer_del(g_start_default_helper_timer);
1401 g_start_default_helper_timer = NULL;
1402 g_stopped_helper_pkgid = "";
1404 ret = _isf_insert_ime_info_by_pkgid(package);
1406 /* Find appid by pkgid. There might be multiple appid, but assume Helper always has one appid.
1407 And appid can be changed, but pkgid won't be changed. */
1408 ret = isf_db_select_appids_by_pkgid(package, appids);
1409 if (ret == 1 && appids.size () == 1) {
1410 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1411 if (it3->first.compare(package) == 0) {
1413 isf_db_update_is_enabled_by_appid(appids[0].c_str (), (bool)it3->second);
1417 /* Let panel know that ise is added... */
1418 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1419 total_appids.push_back(it->appid);
1421 if (total_appids.size() > 0)
1422 _info_manager->update_ise_list (total_appids);
1424 LOGD ("Restart IME(%s)", appids[0].c_str ());
1425 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids[0]);
1426 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1427 _info_manager->start_helper (appids[0]);
1428 _soft_keyboard_launched = true;
1430 g_pkgids_to_be_uninstalled.erase (it3);
1436 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1440 /* Let panel know that ise is added... */
1441 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1442 total_appids.push_back(it->appid);
1444 if (total_appids.size() > 0)
1445 _info_manager->update_ise_list (total_appids);
1449 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1452 else { // If new package is installed...
1453 ret = _isf_insert_ime_info_by_pkgid(package); // If package is not IME, -1 would be returned.
1454 if (ret > 0) { // In case package is IME...
1455 ///////////////// INSTALL /////////////////
1458 /* Let panel know that ise is added... */
1459 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1460 total_appids.push_back(it->appid);
1462 if (total_appids.size() > 0)
1463 _info_manager->update_ise_list (total_appids);
1464 ///////////////// END /////////////////
1466 /* For example, the following happens if appid is changed in IME project and Run As again. The appid would be changed this time.
1467 Assuming only Helper (3rd party) might be installed after update or uninstall and there is one appid per each pkgid...*/
1469 ///////////////// UPDATE -> INSTALL /////////////////
1470 for (it3 = g_pkgids_to_be_updated_and_installed.begin (); it3 != g_pkgids_to_be_updated_and_installed.end (); it3++) {
1471 if (it3->first.compare(package) == 0) {
1473 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1474 if (it->pkgid.compare(package) == 0) {
1475 it->is_enabled = it3->second;
1476 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1481 g_pkgids_to_be_updated_and_installed.erase (it3);
1485 if (g_updated_helper_pkgid.compare(package) == 0) {
1486 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1487 if (it->mode == TOOLBAR_HELPER_MODE && it->pkgid.compare(package) == 0) {
1488 LOGD ("Start IME(%s)", it->appid.c_str ());
1489 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), it->appid);
1490 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1491 _info_manager->start_helper (it->appid);
1492 _soft_keyboard_launched = true;
1496 g_updated_helper_pkgid = "";
1499 ///////////////// END /////////////////
1501 ///////////////// UNINSTALL -> INSTALL /////////////////
1502 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1503 if (it3->first.compare(package) == 0) {
1505 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1506 if (it->pkgid.compare(package) == 0) {
1507 it->is_enabled = it3->second;
1508 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1513 g_pkgids_to_be_uninstalled.erase (it3);
1517 ///////////////// END /////////////////
1519 else if (ret == 0) {
1520 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1525 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL) {
1526 switch (event_state) {
1527 case PACKAGE_MANAGER_EVENT_STATE_STARTED:
1528 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=STARTED progress=%d error=%d", type, package, progress, error);
1530 // Need to check if there is "http://tizen.org/category/ime" category; it can be done by comparing pkgid with ime_info db.
1532 if (_ime_info.size() == 0)
1535 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1536 if (it->pkgid.compare(package) == 0 && it->is_preinstalled == 0) { // Ignore if it's preinstalled IME and IMEngine.
1543 // 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.
1544 LOGD ("%s for pkgid(\"%s\") is about to be deleted", it->appid.c_str (), package);
1545 g_pkgids_to_be_uninstalled.push_back(std::make_pair (String(package), it->is_enabled));
1547 if (_soft_keyboard_launched && isf_db_select_appids_by_pkgid(package, appids)) {
1548 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1549 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.
1550 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1551 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1552 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1553 _info_manager->hide_helper (current_ime_appid);
1554 _info_manager->stop_helper (current_ime_appid);
1555 _soft_keyboard_launched = false;
1556 g_stopped_helper_pkgid = package;
1566 case PACKAGE_MANAGER_EVENT_STATE_COMPLETED:
1567 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1569 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1570 if (it3->first.compare(package) == 0) {
1571 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1575 if (g_stopped_helper_pkgid.compare(package) == 0) { // If the uninstalled ISE is the current ISE, start the initial helper ISE by timer.
1576 if (g_start_default_helper_timer)
1577 ecore_timer_del(g_start_default_helper_timer);
1578 LOGD ("Add timer to start the default IME");
1579 g_start_default_helper_timer = ecore_timer_add(3.0, _start_default_helper_timer, NULL);
1581 else { // Need to clean up g_pkgids_to_be_uninstalled info unless the same package is installed again; e.g., UNINSTALL -> INSTALL case.
1582 if (g_release_uninstalled_ime_info_timer)
1583 ecore_timer_del(g_release_uninstalled_ime_info_timer);
1584 LOGD ("Add timer to release uninstalled IME pkg info");
1585 g_release_uninstalled_ime_info_timer = ecore_timer_add(7.0, _release_uninstalled_pkginfo_timer, NULL);
1588 /* Let panel know that ise is deleted... */
1589 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1590 total_appids.push_back(it->appid);
1592 if (total_appids.size() > 0)
1593 _info_manager->update_ise_list (total_appids);
1600 case PACKAGE_MANAGER_EVENT_STATE_FAILED:
1601 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=FAILED progress=%d error=%d", type, package, progress, error);
1603 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1604 if (it3->first.compare(package) == 0) {
1605 // Update _ime_info for sure...
1608 if (g_stopped_helper_pkgid.compare(package) == 0) {
1609 ret = isf_db_select_appids_by_pkgid(package, appids);
1610 if (ret == 1 && appids.size () == 1) {
1611 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1612 if (it->appid.compare(appids[0]) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1613 LOGD ("Restart IME(%s)", appids[0].c_str ());
1614 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1615 _info_manager->start_helper (appids[0]);
1616 _soft_keyboard_launched = true;
1622 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1624 g_stopped_helper_pkgid = "";
1627 g_pkgids_to_be_uninstalled.erase (it3);
1641 * @brief Set keyboard ISE.
1643 * @param uuid The keyboard ISE's uuid.
1645 * @return false if keyboard ISE change is failed, otherwise return true.
1647 static bool set_keyboard_ise (const String &uuid)
1649 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1651 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1653 if (TOOLBAR_HELPER_MODE == mode) {
1654 String pre_uuid = _info_manager->get_current_helper_uuid ();
1655 _info_manager->hide_helper (pre_uuid);
1656 _info_manager->stop_helper (pre_uuid);
1657 _soft_keyboard_launched = false;
1658 } else if (TOOLBAR_KEYBOARD_MODE == mode) {
1659 uint32 kbd_option = 0;
1660 String kbd_uuid, kbd_name;
1661 isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
1662 if (kbd_uuid == uuid)
1666 _info_manager->change_factory (uuid);
1668 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
1669 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
1675 * @brief Set helper ISE.
1677 * @param uuid The helper ISE's uuid.
1678 * @param launch_ise The flag for launching helper ISE.
1680 * @return false if helper ISE change is failed, otherwise return true.
1682 static bool set_helper_ise (const String &uuid, bool launch_ise)
1684 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1686 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1687 String pre_uuid = _info_manager->get_current_helper_uuid ();
1688 LOGD ("pre_appid=%s, appid=%s, launch_ise=%d, %d", pre_uuid.c_str(), uuid.c_str(), launch_ise, _soft_keyboard_launched);
1689 if (pre_uuid == uuid && _soft_keyboard_launched)
1692 if (TOOLBAR_HELPER_MODE == mode && pre_uuid.length () > 0 && _soft_keyboard_launched) {
1693 _info_manager->hide_helper (pre_uuid);
1694 _info_manager->stop_helper (pre_uuid);
1695 _soft_keyboard_launched = false;
1696 LOGD ("stop helper : %s", pre_uuid.c_str ());
1700 LOGD ("Start helper (%s)", uuid.c_str ());
1702 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1703 if (_info_manager->start_helper (uuid))
1704 _soft_keyboard_launched = true;
1706 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), uuid);
1711 #ifdef HAVE_PKGMGR_INFO
1712 int get_ime_app_list_cb (const pkgmgrinfo_appinfo_h handle, void *user_data)
1715 char *appid = NULL, *pkgid = NULL, *pkgtype = NULL, *exec = NULL, *label = NULL, *path = NULL;
1716 pkgmgrinfo_pkginfo_h pkginfo_handle = NULL;
1718 int *result = static_cast<int*>(user_data);
1720 if (result) /* in this case, need to check category */ {
1722 ret = pkgmgrinfo_appinfo_is_category_exist (handle, "http://tizen.org/category/ime", &exist);
1723 if (ret != PMINFO_R_OK || !exist) {
1729 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
1730 if (ret == PMINFO_R_OK)
1731 ime_db.appid = String (appid ? appid : "");
1733 LOGE ("pkgmgrinfo_appinfo_get_appid failed! error code=%d", ret);
1737 ime_db.iconpath = "";
1740 ret = pkgmgrinfo_appinfo_get_pkgid (handle, &pkgid);
1741 if (ret == PMINFO_R_OK)
1742 ime_db.pkgid = String (pkgid ? pkgid : "");
1744 LOGE ("pkgmgrinfo_appinfo_get_pkgid failed! error code=%d", ret);
1749 ret = pkgmgrinfo_appinfo_get_exec (handle, &exec);
1750 if (ret == PMINFO_R_OK)
1751 ime_db.exec = String (exec ? exec : "");
1753 LOGE ("pkgmgrinfo_appinfo_get_exec failed! error code=%d", ret);
1758 ret = pkgmgrinfo_appinfo_get_label (handle, &label);
1759 if (ret == PMINFO_R_OK)
1760 ime_db.label = String (label ? label : "");
1762 /* get pkgmgrinfo_pkginfo_h */
1763 /* Try to get in global packages */
1764 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &pkginfo_handle);
1765 if (ret != PMINFO_R_OK) {
1766 /* Try to get in user packages */
1767 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, getuid (), &pkginfo_handle);
1770 if (ret == PMINFO_R_OK && pkginfo_handle) {
1772 ret = pkgmgrinfo_pkginfo_get_type (pkginfo_handle, &pkgtype);
1774 if (ret == PMINFO_R_OK)
1775 ime_db.pkgtype = String (pkgtype ? pkgtype : "");
1777 ISF_SAVE_LOG ("pkgtype is not available!");
1778 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1783 pkgmgrinfo_pkginfo_get_root_path (pkginfo_handle, &path);
1786 ime_db.languages = "en";
1787 ime_db.display_lang = "";
1789 if (ime_db.pkgtype.compare ("rpm") == 0 && //1 Inhouse IMEngine ISE(IME)
1790 ime_db.exec.find ("scim-launcher") != String::npos) // Some IMEngine's pkgid doesn't have "ise-engine" prefix.
1792 ime_db.mode = TOOLBAR_KEYBOARD_MODE;
1794 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1795 + String (SCIM_PATH_DELIM_STRING) + String ("IMEngine");
1796 ime_db.module_name = ime_db.pkgid;
1797 ime_db.is_enabled = 1;
1798 ime_db.is_preinstalled = 1;
1799 ime_db.has_option = 0; // It doesn't matter. No option for IMEngine...
1802 ime_db.mode = TOOLBAR_HELPER_MODE;
1803 if (ime_db.pkgtype.compare ("rpm") == 0 && path) //1 Inhouse Helper ISE(IME)
1806 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1808 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART;
1810 ime_db.module_name = ime_db.pkgid;
1812 String module_path = String (path) + String ("/lib");
1813 String fullpath = module_path + String (SCIM_PATH_DELIM_STRING) + ime_db.module_name + String (".so");
1815 if (stat (fullpath.c_str (), &st) < 0) {
1816 /* Not found in lib directory of package's root path */
1817 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1818 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1821 ime_db.module_path = module_path;
1824 ime_db.is_enabled = 1;
1825 ime_db.is_preinstalled = 1;
1826 ime_db.has_option = 1; // Let's assume the inhouse IME always has an option menu.
1828 else if (ime_db.pkgtype.compare ("wgt") == 0) //1 Download Web IME
1830 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1831 | SCIM_HELPER_NEED_SPOT_LOCATION_INFO | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1832 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1833 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1834 ime_db.module_name = String ("ise-web-helper-agent");
1835 if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1836 ime_db.is_enabled = 1;
1837 ime_db.is_preinstalled = 1;
1840 if (_MOBILE || _COMMON)
1841 ime_db.is_enabled = 0;
1843 ime_db.is_enabled = 1;
1845 ime_db.is_preinstalled = 0;
1847 ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1849 else if (ime_db.pkgtype.compare ("tpk") == 0) //1 Download Native IME
1851 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1852 | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1854 ime_db.module_path = String (path) + String ("/lib");
1856 ime_db.module_path = String (tzplatform_getenv(TZ_SYS_RW_APP)) + ime_db.pkgid + String ("/lib");
1857 ime_db.module_name = String ("lib") + ime_db.exec.substr (ime_db.exec.find_last_of (SCIM_PATH_DELIM) + 1);
1858 if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1859 ime_db.is_enabled = 1;
1860 ime_db.is_preinstalled = 1;
1863 if (_MOBILE || _COMMON)
1864 ime_db.is_enabled = 0;
1866 ime_db.is_enabled = 1;
1868 ime_db.is_preinstalled = 0;
1870 ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1873 LOGE ("Unsupported pkgtype(%s)", ime_db.pkgtype.c_str ());
1874 if (pkginfo_handle) {
1875 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1876 pkginfo_handle = NULL;
1882 _ime_info.push_back(ime_db);
1884 if (pkginfo_handle) {
1885 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1886 pkginfo_handle = NULL;
1894 * @brief Set active ISE.
1896 * @param uuid The ISE's uuid.
1897 * @param launch_ise The flag for launching helper ISE.
1899 * @return false if ISE change is failed, otherwise return true.
1901 static bool set_active_ise (const String &uuid, bool launch_ise)
1903 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1904 LOGD ("set ISE (%s) %d", uuid.c_str(), launch_ise);
1906 if (uuid.length () <= 0)
1909 bool ise_changed = false, valid = false;
1911 int ime_num = -1; /* If we failed retrieving the number of IMEs installed, assume we need to clear IME related settings */
1912 pkgmgrinfo_appinfo_filter_h handle;
1913 int ret = pkgmgrinfo_appinfo_filter_create(&handle);
1914 if (ret == PMINFO_R_OK) {
1915 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
1916 if (ret == PMINFO_R_OK) {
1917 ret = pkgmgrinfo_appinfo_filter_count(handle, &ime_num);
1918 if (ret != PMINFO_R_OK) {
1919 LOGW("pkgmgrinfo_appinfo_filter_count failed(%d)", ret);
1922 pkgmgrinfo_appinfo_filter_destroy (handle);
1925 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
1928 /* If the ime_num and _ime_info.size() are different, it is likely that the isf-panel-efl was
1929 terminated abnormally while processing package manager's install / uninstall events */
1930 LOGD("Checking whether db file needs to be re-created : %d %zu", ime_num, _ime_info.size());
1931 if (ime_num != (int)_ime_info.size()) {
1933 isf_db_delete_ime_info();
1934 isf_pkg_reload_ime_info_db();
1935 isf_pkg_select_all_ime_info_db(_ime_info);
1938 if (_ime_info.size () == 0) {
1939 #ifdef HAVE_PKGMGR_INFO
1940 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
1941 if (ret == PMINFO_R_OK) {
1942 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
1943 if (ret == PMINFO_R_OK)
1944 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
1946 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
1948 pkgmgrinfo_appinfo_filter_destroy (handle);
1951 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
1956 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1957 if (!uuid.compare (_ime_info[i].appid)) {
1958 if (TOOLBAR_KEYBOARD_MODE == _ime_info[i].mode)
1959 ise_changed = set_keyboard_ise (_ime_info[i].appid);
1960 else if (TOOLBAR_HELPER_MODE == _ime_info[i].mode) {
1961 if (_ime_info[i].is_enabled) {
1962 if (_ime_info[i].exec == String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
1963 /* If IME so is deleted somehow, main() in scim_helper_launcher.cpp will return -1.
1964 Checking HelperModule validity seems necessary here. */
1965 HelperModule helper_module (_ime_info[i].module_name);
1966 if (helper_module.valid ())
1968 helper_module.unload ();
1971 /* executable type */
1976 ise_changed = set_helper_ise (_ime_info[i].appid, launch_ise);
1978 LOGW ("Helper ISE(appid=\"%s\",module_name=\"%s\") is not valid.", _ime_info[i].appid.c_str (), _ime_info[i].module_name.c_str ());
1981 LOGW ("Helper ISE(appid=\"%s\") is not enabled.", _ime_info[i].appid.c_str ());
1984 _info_manager->set_current_toolbar_mode (_ime_info[i].mode);
1986 /* From Tizen 4.0 all the ISEs need to handle H/W keyboard events */
1987 _ime_info[i].options |= ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1988 _info_manager->set_current_helper_option (_ime_info[i].options);
1989 _info_manager->set_current_ise_name (_ime_info[i].label);
1990 _ise_state = WINDOW_STATE_HIDE;
1991 _candidate_mode = SOFT_CANDIDATE_WINDOW;
1992 _candidate_port_line = ONE_LINE_CANDIDATE;
1993 #if ISF_BUILD_CANDIDATE_UI
1996 _soft_candidate_width = 0;
1997 _soft_candidate_height = 0;
1999 if (_candidate_window)
2000 ui_create_candidate_window ();
2003 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _ime_info[i].appid);
2004 scim_global_config_flush ();
2010 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2014 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2021 LOGW ("Failed to launch IME (%s), %zu", uuid.c_str (), _ime_info.size());
2027 * @brief Set temporary ISE.
2029 * @param uuid The ISE's uuid.
2031 * @return false if ISE change is failed, otherwise return true.
2033 static bool set_temporary_ise (const String &uuid)
2035 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2036 LOGD ("set temporary ISE (%s)", uuid.c_str ());
2038 if (uuid.length () <= 0)
2041 if (_ime_info.size () == 0) {
2042 #ifdef HAVE_PKGMGR_INFO
2043 pkgmgrinfo_appinfo_filter_h handle;
2044 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
2045 if (ret == PMINFO_R_OK) {
2046 /* Add the package info for the IME that matches with our uuid only */
2047 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_ID, uuid.c_str ());
2048 if (ret == PMINFO_R_OK)
2049 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
2051 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
2053 pkgmgrinfo_appinfo_filter_destroy (handle);
2055 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
2060 #ifdef HAVE_PKGMGR_INFO
2061 bool ise_changed = false;
2063 pkgmgrinfo_appinfo_h handle = NULL;
2064 int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
2065 if (ret != PMINFO_R_OK) {
2066 LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
2072 ret = pkgmgrinfo_appinfo_get_label (handle, &label);
2073 if (ret != PMINFO_R_OK) {
2074 LOGW ("Could not get label for appid '%s'", uuid.c_str ());
2075 pkgmgrinfo_appinfo_destroy_appinfo (handle);
2079 ise_changed = set_helper_ise (uuid, true);
2082 _info_manager->set_current_toolbar_mode (TOOLBAR_HELPER_MODE);
2084 _info_manager->set_current_helper_option (SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO |
2085 SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT);
2087 _info_manager->set_current_helper_option (SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO |
2088 SCIM_HELPER_AUTO_RESTART);
2089 String label_string = label;
2090 _info_manager->set_current_ise_name (label_string);
2093 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2096 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2099 pkgmgrinfo_appinfo_destroy_appinfo (handle);
2109 * @brief Load ISF configuration and ISEs information.
2111 static void load_config (void)
2113 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2115 /* Read configurations. */
2116 if (!_config.null ()) {
2117 bool shared_ise = _config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), false);
2118 _info_manager->set_should_shared_ise (shared_ise);
2120 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
2121 _auto_destroy_ise = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_ENABLE_AUTO_DESTROY_ISE), _auto_destroy_ise);
2122 _enable_auto_restart = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_ENABLE_AUTO_RESTART_ISE), _enable_auto_restart);
2124 isf_load_ise_information (ALL_ISE, _config);
2128 * @brief Reload config callback function for ISF panel.
2130 * @param config The config pointer.
2132 static void config_reload_cb (const ConfigPointer &config)
2134 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2135 /* load_config (); */
2136 _info_manager->reload_config ();
2139 #if ISF_BUILD_CANDIDATE_UI
2140 //////////////////////////////////////////////////////////////////////
2141 // Start of Candidate Functions
2142 //////////////////////////////////////////////////////////////////////
2144 * @brief Get candidate window valid height for autoscroll.
2146 * @return The valid height.
2148 static int ui_candidate_get_valid_height (void)
2150 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2155 if (_candidate_window) {
2156 if (_candidate_state == WINDOW_STATE_SHOW)
2157 angle = _candidate_angle;
2159 angle = efl_get_app_window_angle ();
2161 if (_aux_area_visible && _candidate_area_1_visible) {
2162 if (angle == 90 || angle == 270)
2163 height = _candidate_land_height_min_2;
2165 height = _candidate_port_height_min_2;
2167 if (angle == 90 || angle == 270)
2168 height = _candidate_land_height_min;
2170 height = _candidate_port_height_min;
2177 * @brief Resize candidate window size.
2179 * @param new_width New width for candidate window.
2180 * @param new_height New height for candidate window.
2182 static void ui_candidate_window_resize (int new_width, int new_height)
2184 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " width:" << new_width << " height:" << new_height << "\n";
2186 if (!_candidate_window)
2191 LOGD ("%s (w: %d, h: %d)", __func__, new_width, new_height);
2192 evas_object_resize (_aux_line, new_width, 2);
2193 _candidate_width = new_width;
2194 _candidate_height = new_height;
2195 if (_candidate_state == WINDOW_STATE_SHOW)
2196 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2198 if (_candidate_state == WINDOW_STATE_SHOW && _candidate_mode == FIXED_CANDIDATE_WINDOW) {
2199 height = ui_candidate_get_valid_height ();
2200 if ((_ise_width == 0 && _ise_height == 0) ||
2201 (_ise_height > 0 && _candidate_valid_height != height) ||
2202 (_ise_height > 0 && (_candidate_height - height) > _ise_height) ||
2203 ((_candidate_angle == 90 || _candidate_angle == 270) && (_ise_width < _screen_height)) ||
2204 ((_candidate_angle == 0 || _candidate_angle == 180) && (_ise_width > _screen_width ))) {
2206 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2208 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2212 /* Get height for portrait and landscape */
2213 int port_width = _candidate_port_width;
2214 int port_height = _candidate_port_height_min;
2215 int land_width = _candidate_land_width;
2216 int land_height = _candidate_land_height_min;
2217 if (_candidate_angle == 90 || _candidate_angle == 270) {
2218 land_height = new_height;
2219 if (land_height == _candidate_land_height_min_2) {
2220 port_height = _candidate_port_height_min_2;
2221 } else if (land_height == _candidate_land_height_max) {
2222 port_height = _candidate_port_height_max;
2223 } else if (land_height == _candidate_land_height_max_2) {
2224 port_height = _candidate_port_height_max_2;
2227 port_height = new_height;
2228 if (port_height == _candidate_port_height_min_2) {
2229 land_height = _candidate_land_height_min_2;
2230 } else if (port_height == _candidate_port_height_max) {
2231 land_height = _candidate_land_height_max;
2232 } else if (port_height == _candidate_port_height_max_2) {
2233 land_height = _candidate_land_height_max_2;
2237 LOGD ("window_rotation_geometry_set (_candidate_window), port (%d, %d), land (%d, %d)",
2238 port_width, port_height, land_width, land_height);
2242 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2243 0, 0, 0, port_width, port_height);
2244 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2245 90, 0, 0, land_height, land_width);
2246 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2247 180, 0, 0, port_width, port_height);
2248 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2249 270, 0, 0, land_height, land_width);
2252 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2253 0, 0, 0, port_width, port_height);
2254 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2255 90, 0, 0, land_height, land_width);
2256 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2257 180, 0, 0, port_width, port_height);
2258 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2259 270, 0, 0, land_height, land_width);
2264 * @brief This function will show/hide widgets of candidate window,
2265 * and resize candidate window size according to aux_area/candidate_area.
2267 static void ui_candidate_window_adjust (void)
2269 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2270 if (!_candidate_window)
2273 int x = 0, y = 0, width = 0, height = 0;
2275 /* Get candidate window size */
2278 if (_candidate_angle == 90 || _candidate_angle == 270) {
2279 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2280 &x, &y, &height, &width);
2282 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2283 &x, &y, &width, &height);
2287 if (_candidate_angle == 90 || _candidate_angle == 270)
2288 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &height, &width);
2290 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
2293 if (_aux_area_visible && _candidate_area_2_visible) {
2294 evas_object_show (_aux_line);
2295 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);
2296 if (_candidate_angle == 90 || _candidate_angle == 270) {
2297 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2298 _ise_height > _candidate_land_height_max_2 - _candidate_land_height_min_2)
2299 ui_candidate_window_resize (width, _candidate_land_height_min_2 + _ise_height);
2301 ui_candidate_window_resize (width, _candidate_land_height_max_2);
2302 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2303 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min_2);
2304 evas_object_move (_scroller_bg, 0, _candidate_land_height_min_2);
2305 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2307 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2308 _ise_height > _candidate_port_height_max_2 - _candidate_port_height_min_2)
2309 ui_candidate_window_resize (width, _candidate_port_height_min_2 + _ise_height);
2311 ui_candidate_window_resize (width, _candidate_port_height_max_2);
2312 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2313 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min_2);
2314 evas_object_move (_scroller_bg, 0, _candidate_port_height_min_2);
2315 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2317 } else if (_aux_area_visible && _candidate_area_1_visible) {
2318 evas_object_show (_aux_line);
2319 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);
2320 if (_candidate_angle == 90 || _candidate_angle == 270) {
2321 ui_candidate_window_resize (width, _candidate_land_height_min_2);
2322 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2323 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2325 ui_candidate_window_resize (width, _candidate_port_height_min_2);
2326 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2327 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2329 } else if (_aux_area_visible) {
2330 evas_object_hide (_aux_line);
2331 ui_candidate_window_resize (width, _aux_height + 2);
2332 evas_object_resize (_candidate_bg, width, _aux_height + 2);
2333 } else if (_candidate_area_2_visible) {
2334 evas_object_hide (_aux_line);
2335 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2336 if (_candidate_angle == 90 || _candidate_angle == 270) {
2337 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2338 _ise_height > _candidate_land_height_max - _candidate_land_height_min)
2339 ui_candidate_window_resize (width, _candidate_land_height_min + _ise_height);
2341 ui_candidate_window_resize (width, _candidate_land_height_max);
2342 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3]);
2343 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min);
2344 evas_object_move (_scroller_bg, 0, _candidate_land_height_min);
2345 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2347 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2348 _ise_height > _candidate_port_height_max - _candidate_port_height_min)
2349 ui_candidate_window_resize (width, _candidate_port_height_min + _ise_height);
2351 ui_candidate_window_resize (width, _candidate_port_height_max);
2352 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
2353 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min);
2354 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
2355 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2358 evas_object_hide (_aux_line);
2359 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2360 if (_candidate_angle == 90 || _candidate_angle == 270) {
2361 ui_candidate_window_resize (width, _candidate_land_height_min);
2362 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3]);
2363 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2365 ui_candidate_window_resize (width, _candidate_port_height_min);
2366 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
2367 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2373 * @brief Rotate candidate window.
2375 * @param angle The angle of candidate window.
2377 static void ui_candidate_window_rotate (int angle)
2379 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2380 if (!_candidate_window)
2383 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
2385 if (angle == 90 || angle == 270) {
2386 _candidate_scroll_width = _candidate_scroll_width_max;
2387 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
2388 evas_object_resize (_aux_area, _aux_land_width, _aux_height);
2389 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_max, _item_min_height);
2390 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_min);
2391 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_min + 6);
2393 _candidate_scroll_width = _candidate_scroll_width_min;
2394 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
2395 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
2396 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
2397 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_max);
2398 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
2401 evas_object_hide (_candidate_area_2);
2402 _candidate_area_2_visible = false;
2403 ui_candidate_window_adjust ();
2404 if (_candidate_area_1_visible) {
2405 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2406 ui_tts_focus_rect_hide ();
2412 * @brief This function is used to judge whether candidate window should be hidden.
2414 * @return true if candidate window should be hidden, otherwise return false.
2416 static bool ui_candidate_can_be_hide (void)
2418 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2420 if (_aux_area_visible || _candidate_area_1_visible || _candidate_area_2_visible)
2427 * @brief Delete check candidate window size timer.
2431 static void ui_candidate_delete_check_size_timer (void)
2433 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2435 if (_check_size_timer != NULL) {
2436 ecore_timer_del (_check_size_timer);
2437 _check_size_timer = NULL;
2442 * @brief Callback function for check candidate window size timer.
2444 * @param data Data to pass when it is called.
2446 * @return ECORE_CALLBACK_CANCEL
2448 static Eina_Bool ui_candidate_check_size_timeout (void *data)
2450 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2452 ui_candidate_delete_check_size_timer ();
2453 ui_candidate_window_resize (_candidate_width, _candidate_height);
2454 ui_settle_candidate_window ();
2455 return ECORE_CALLBACK_CANCEL;
2459 * @brief Delete longpress timer.
2463 static void ui_candidate_delete_longpress_timer (void)
2465 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2467 if (_longpress_timer != NULL) {
2468 ecore_timer_del (_longpress_timer);
2469 _longpress_timer = NULL;
2474 * @brief Callback function for candidate longpress timer.
2476 * @param data Data to pass when it is called.
2478 * @return ECORE_CALLBACK_CANCEL
2480 static Eina_Bool ui_candidate_longpress_timeout (void *data)
2482 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2484 int index = (int)GPOINTER_TO_INT (data);
2485 ui_candidate_delete_longpress_timer ();
2487 _info_manager->send_longpress_event (_click_object, index);
2488 return ECORE_CALLBACK_CANCEL;
2492 * @brief Delete destroy timer.
2496 static void ui_candidate_delete_destroy_timer (void)
2498 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2500 if (_destroy_timer != NULL) {
2501 ecore_timer_del (_destroy_timer);
2502 _destroy_timer = NULL;
2507 * @brief Callback function for destroy timer.
2509 * @param data Data to pass when it is called.
2511 * @return ECORE_CALLBACK_CANCEL
2513 static Eina_Bool ui_candidate_destroy_timeout (void *data)
2515 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2517 ui_candidate_delete_destroy_timer ();
2518 ui_destroy_candidate_window ();
2519 return ECORE_CALLBACK_CANCEL;
2521 #endif /* CANDIDATE */
2525 * @brief Callback function for off_prepare_done.
2527 * @param data Data to pass when it is called.
2529 * @return ECORE_CALLBACK_CANCEL
2531 static Eina_Bool off_prepare_done_timeout (void *data)
2533 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2535 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
2536 // WILL_HIDE_REQUEST_DONE Ack to WM
2537 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
2538 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
2539 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
2540 root_window, _control_window);
2541 _off_prepare_done_timer = NULL;
2543 return ECORE_CALLBACK_CANCEL;
2545 #endif /* HAVE_ECOREX */
2547 #if ISF_BUILD_CANDIDATE_UI
2549 * @brief Delete candidate hide timer.
2553 static void delete_candidate_hide_timer (void)
2555 LOGD ("deleting candidate_hide_timer");
2556 if (_candidate_hide_timer) {
2557 ecore_timer_del (_candidate_hide_timer);
2558 _candidate_hide_timer = NULL;
2562 static void candidate_window_hide (void)
2564 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2566 delete_candidate_hide_timer ();
2567 _candidate_state = WINDOW_STATE_HIDE;
2569 LOGD ("evas_object_hide (_candidate_window, %p)", elm_win_xwindow_get (_candidate_window));
2571 if (_candidate_window) {
2572 /* There are cases that when there are rapid ISE_HIDE and ISE_SHOW requests,
2573 candidate window should be displayed but STATE_OFF for the first ISE_HIDE
2574 calls this function, so when the candidate window is shown by the following
2575 STATE_ON message, a blank area is displayed in candidate window -
2576 so we let the _candidate_area_1 as the default area that would be displayed */
2577 //evas_object_hide (_candidate_area_1);
2578 //evas_object_hide (_more_btn);
2579 _candidate_area_1_visible = false;
2581 evas_object_hide (_candidate_window);
2582 SCIM_DEBUG_MAIN (3) << " Hide candidate window\n";
2587 * @brief Callback function for candidate hide timer
2589 * @param data Data to pass when it is called.
2591 * @return ECORE_CALLBACK_CANCEL
2593 static Eina_Bool candidate_hide_timer (void *data)
2595 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2597 LOGD ("calling candidate_window_hide ()");
2598 candidate_window_hide ();
2600 return ECORE_CALLBACK_CANCEL;
2605 * @brief Delete candidate show handler.
2609 static void delete_candidate_show_handler (void)
2611 if (_candidate_show_handler) {
2612 ecore_event_handler_del (_candidate_show_handler);
2613 _candidate_show_handler = NULL;
2618 * @brief Callback function for window show completion event
2620 * @param data Data to pass when it is called.
2622 * @return ECORE_CALLBACK_CANCEL
2625 static Eina_Bool x_event_window_show_cb (void *data, int ev_type, void *event)
2627 delete_candidate_show_handler ();
2629 Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
2630 if (_candidate_state == WINDOW_STATE_WILL_SHOW) {
2631 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2632 LOGD ("Candidate window show callback");
2634 /* If our candidate window is in WILL_SHOW state and this show callback was called,
2635 now we are finally displayed on to the screen */
2636 _candidate_state = WINDOW_STATE_SHOW;
2638 /* Update the geometry information for auto scrolling */
2639 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2640 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2641 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2643 /* And the state event */
2644 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2646 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2647 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2648 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2649 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2654 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2655 LOGD ("Candidate window show callback, but _candidate_state is %d", _candidate_state);
2659 return ECORE_CALLBACK_CANCEL;
2661 #endif /* HAVE_ECOREX */
2664 * @brief Show candidate window.
2666 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2668 static void ui_candidate_show (bool bSetVirtualKbd)
2670 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2672 delete_candidate_hide_timer ();
2674 if (!_candidate_window) return;
2675 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
2678 /* FIXME : SHOULD UNIFY THE METHOD FOR CHECKING THE HW KEYBOARD EXISTENCE */
2679 /* If the ISE is not visible currently, wait for the ISE to be opened and then show our candidate window */
2680 _candidate_show_requested = true;
2681 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) && (_ise_state != WINDOW_STATE_SHOW)) {
2682 LOGD ("setting _show_candidate_requested to TRUE");
2686 /* If the ISE angle is valid, respect the value to make sure
2687 the candidate window always have the same angle with ISE */
2688 if (_ise_angle != -1) {
2689 _candidate_angle = _ise_angle;
2691 ui_candidate_window_rotate (_candidate_angle);
2693 /* If the candidate window was about to hide, turn it back to SHOW state now */
2694 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
2695 _candidate_state = WINDOW_STATE_SHOW;
2698 /* Change to WILL_SHOW state only when we are not currently in SHOW state */
2699 if (_candidate_state != WINDOW_STATE_SHOW) {
2700 _candidate_state = WINDOW_STATE_WILL_SHOW;
2704 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2705 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
2706 // Unset conformant area
2707 Ecore_X_Window current_app_window = efl_get_app_window ();
2708 if (_app_window != current_app_window) {
2709 struct rectinfo info = {0, 0, 0, 0};
2710 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
2711 set_keyboard_geometry_atom_info (_app_window, info);
2712 LOGD ("Conformant reset for window %x", _app_window);
2713 _app_window = current_app_window;
2717 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2718 if (bSetVirtualKbd) {
2719 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2722 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
2725 ui_candidate_delete_check_size_timer ();
2726 _check_size_timer = ecore_timer_add (0.02, ui_candidate_check_size_timeout, NULL);
2728 SCIM_DEBUG_MAIN (3) << " Show candidate window\n";
2730 if (_ise_state == WINDOW_STATE_SHOW) {
2731 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
2732 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
2734 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
2735 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
2738 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2739 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2740 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2741 LOGD ("sending ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW");
2742 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
2746 if (_candidate_state != WINDOW_STATE_SHOW) {
2748 if (_candidate_show_handler) {
2749 LOGD ("Was still waiting for CANDIDATE_WINDOW_SHOW....");
2751 delete_candidate_show_handler ();
2752 LOGD ("Registering ECORE_X_EVENT_WINDOW_SHOW event, %d", _candidate_state);
2753 _candidate_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_window_show_cb, NULL);
2757 LOGD ("The candidate window was already in SHOW state, update geometry information");
2758 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2759 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2761 /* And the state event */
2762 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2764 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2765 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2766 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2767 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2772 evas_object_show (_candidate_window);
2776 * @brief Hide candidate window.
2778 * @param bForce The flag to hide candidate window by force.
2779 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2781 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd, bool will_hide)
2783 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " bForce:" << bForce << " bSetVirtualKbd:" << bSetVirtualKbd << " will_hide:" << will_hide << "...\n";
2785 if (!_candidate_window)
2789 if (_candidate_area_2 && _candidate_area_2_visible) {
2790 evas_object_hide (_candidate_area_2);
2791 _candidate_area_2_visible = false;
2792 evas_object_hide (_scroller_bg);
2793 evas_object_hide (_close_btn);
2794 _info_manager->candidate_more_window_hide ();
2795 ui_candidate_window_adjust ();
2799 if (bForce || ui_candidate_can_be_hide ()) {
2801 LOGD ("candidate_state = WILL_HIDE");
2802 _candidate_state = WINDOW_STATE_WILL_HIDE;
2804 delete_candidate_hide_timer ();
2805 _candidate_hide_timer = ecore_timer_add (2.0, candidate_hide_timer, NULL);
2808 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2809 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2810 /* FIXME : should check if bSetVirtualKbd flag is really needed in this case */
2812 if (_ise_state == WINDOW_STATE_SHOW) {
2813 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2815 if (bSetVirtualKbd) {
2816 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2820 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2821 _info_manager->update_input_panel_event
2822 ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_HIDE);
2826 /* Update the new keyboard geometry first, and then send the candidate hide event */
2827 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_HIDE);
2830 /* If we are not in will_hide state, hide the candidate window immediately */
2831 candidate_window_hide ();
2833 if (_preedit_window)
2834 evas_object_hide (_preedit_window);
2840 * @brief Callback function for more button.
2842 * @param data Data to pass when it is called.
2843 * @param e The evas for current event.
2844 * @param button The evas object for current event.
2845 * @param event_info The information for current event.
2847 static void ui_candidate_window_more_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2849 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2851 _info_manager->candidate_more_window_show ();
2853 if (candidate_expanded == false) {
2854 candidate_expanded = true;
2855 int number = SCIM_LOOKUP_TABLE_MAX_PAGESIZE;
2856 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
2857 if (_candidate_0 [i] == NULL) {
2862 if (g_isf_candidate_table.get_current_page_size () != number)
2863 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2866 if (_candidate_angle == 180) {
2867 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2868 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2869 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2870 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2872 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2873 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2874 * for avoiding this situation.
2876 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2877 ecore_evas_move_resize (ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2878 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2879 ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2882 evas_object_show (_candidate_area_2);
2883 _candidate_area_2_visible = true;
2884 evas_object_show (_scroller_bg);
2885 evas_object_hide (_more_btn);
2886 evas_object_show (_close_btn);
2888 ui_candidate_window_adjust ();
2889 ui_settle_candidate_window ();
2894 * @brief Callback function for close button.
2896 * @param data Data to pass when it is called.
2897 * @param e The evas for current event.
2898 * @param button The evas object for current event.
2899 * @param event_info The information for current event.
2901 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2903 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2905 if (_candidate_area_2 == NULL || !_candidate_area_2_visible)
2908 _info_manager->candidate_more_window_hide ();
2910 evas_object_hide (_candidate_area_2);
2911 _candidate_area_2_visible = false;
2912 evas_object_hide (_scroller_bg);
2913 evas_object_hide (_close_btn);
2915 candidate_expanded = false;
2916 evas_object_show (_candidate_area_1);
2917 _candidate_area_1_visible = true;
2918 evas_object_show (_more_btn);
2920 elm_scroller_region_show (_candidate_area_2, 0, 0, _candidate_scroll_width, 100);
2921 if (_candidate_angle == 180) {
2922 Ecore_Evas *ee= ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2923 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2924 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2925 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2927 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2928 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2929 * for avoiding this situation.
2931 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2932 ecore_evas_move_resize (ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2933 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2934 ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2937 ui_candidate_window_adjust ();
2938 ui_settle_candidate_window ();
2943 * @brief Callback function for mouse button press.
2945 * @param data Data to pass when it is called.
2946 * @param e The evas for current event.
2947 * @param button The evas object for current event.
2948 * @param event_info The information for current event.
2950 static void ui_mouse_button_pressed_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2952 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2954 _click_object = GPOINTER_TO_INT (data) & 0xFF;
2957 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
2960 _click_down_pos [0] = ev->canvas.x;
2961 _click_down_pos [1] = ev->canvas.y;
2963 if (_click_object == ISF_EFL_CANDIDATE_0 || _click_object == ISF_EFL_CANDIDATE_ITEMS) {
2964 int index = (int)GPOINTER_TO_INT (data) >> 8;
2966 #ifdef HAVE_FEEDBACK
2967 if (feedback_initialized) {
2968 int feedback_result = 0;
2969 bool sound_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_SOUND_FEEDBACK, false);
2971 if (sound_feedback) {
2972 feedback_result = feedback_play_type (FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_SIP);
2974 if (FEEDBACK_ERROR_NONE == feedback_result)
2975 LOGD ("Sound play successful");
2977 LOGW ("Cannot play feedback sound : %d", feedback_result);
2980 bool vibrate_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_VIBRATION_FEEDBACK, false);
2982 if (vibrate_feedback) {
2983 feedback_result = feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
2985 if (FEEDBACK_ERROR_NONE == feedback_result)
2986 LOGD ("Vibration play successful");
2988 LOGW ("Cannot play feedback vibration : %d", feedback_result);
2993 ui_candidate_delete_longpress_timer ();
2994 _longpress_timer = ecore_timer_add (1.0, ui_candidate_longpress_timeout, (void *)index);
2999 * @brief Callback function for mouse button release.
3001 * @param data Data to pass when it is called.
3002 * @param e The evas for current event.
3003 * @param button The evas object for current event.
3004 * @param event_info The information for current event.
3006 static void ui_mouse_button_released_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3008 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " index:" << GPOINTER_TO_INT (data) << "...\n";
3010 ui_candidate_delete_longpress_timer ();
3012 int index = GPOINTER_TO_INT (data);
3013 if (_click_object == ISF_EFL_AUX && _is_click) {
3015 const char *buf = edje_object_part_state_get (button, "aux", &ret);
3016 if (strcmp ("selected", buf)) {
3017 for (unsigned int i = 0; i < _aux_items.size (); i++) {
3018 buf = edje_object_part_state_get (_aux_items [i], "aux", &ret);
3019 if (!strcmp ("selected", buf))
3020 edje_object_signal_emit (_aux_items [i], "aux,state,unselected", "aux");
3022 edje_object_signal_emit (button, "aux,state,selected", "aux");
3023 _info_manager->select_aux (index);
3025 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
3026 edje_object_color_class_get (_aux_items [index], "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
3027 // Normal item is clicked
3028 if (!(r == 62 && g == 207 && b == 255)) {
3029 for (unsigned int i = 0; i < _aux_items.size (); i++) {
3030 edje_object_color_class_set (_aux_items [i], "text_color", 249, 249, 249, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3032 edje_object_color_class_set (_aux_items [index], "text_color", 62, 207, 255, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3033 _info_manager->select_aux (index);
3035 } else if (_click_object == ISF_EFL_CANDIDATE_0 && _is_click) {
3036 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3037 _info_manager->select_candidate (index);
3038 } else if (_click_object == ISF_EFL_CANDIDATE_ITEMS && _is_click) {
3039 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3040 _info_manager->select_candidate (index);
3045 * @brief Callback function for mouse move.
3047 * @param data Data to pass when it is called.
3048 * @param e The evas for current event.
3049 * @param button The evas object for current event.
3050 * @param event_info The information for current event.
3052 static void ui_mouse_moved_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3054 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3056 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
3059 _click_up_pos [0] = ev->canvas.x;
3060 _click_up_pos [1] = ev->canvas.y;
3062 if (abs (_click_up_pos [0] - _click_down_pos [0]) >= (int)(15 * _height_rate) ||
3063 abs (_click_up_pos [1] - _click_down_pos [1]) >= (int)(15 * _height_rate)) {
3065 ui_candidate_delete_longpress_timer ();
3070 * @brief Show rect for candidate focus object when screen reader is enabled.
3072 * @param x Rect X position.
3073 * @param y Rect Y position.
3074 * @param w Rect width.
3075 * @param h Rect height.
3077 static void ui_tts_focus_rect_show (int x, int y, int w, int h)
3079 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3080 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
3083 if (_tts_focus_rect == NULL) {
3084 _tts_focus_rect = evas_object_rectangle_add (evas_object_evas_get ((Evas_Object*)_candidate_window));
3085 evas_object_color_set (_tts_focus_rect, 0, 0, 0, 0);
3086 elm_access_highlight_set (elm_access_object_register (_tts_focus_rect, (Evas_Object*)_candidate_window));
3088 evas_object_move (_tts_focus_rect, x, y);
3089 evas_object_resize (_tts_focus_rect, w, h);
3090 evas_object_raise (_tts_focus_rect);
3091 evas_object_show (_tts_focus_rect);
3095 * @brief Hide rect for candidate focus object when screen reader is enabled.
3097 static void ui_tts_focus_rect_hide (void)
3099 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3101 if (_tts_focus_rect) {
3102 //evas_object_hide (_tts_focus_rect);
3103 evas_object_move (_tts_focus_rect, -1000, -1000);
3108 * @brief Callback function for candidate scroller stop event.
3110 * @param data Data to pass when it is called.
3111 * @param obj The evas object for current event.
3112 * @param event_info The information for current event.
3114 static void ui_candidate_scroller_stop_cb (void *data, Evas_Object *obj, void *event_info)
3116 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3117 if (!_wait_stop_event)
3120 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
3121 if (_candidate_0 [_candidate_tts_focus_index]) {
3123 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
3124 ui_tts_focus_rect_show (x, y, w, h);
3127 _wait_stop_event = false;
3131 * @brief Create preedit window.
3133 static void ui_create_preedit_window (void)
3135 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3137 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3140 _preedit_width = 100;
3141 _preedit_height = _preedit_height * _height_rate;
3142 if (_preedit_window == NULL) {
3143 _preedit_window = efl_create_window ("ISF Popup", "Preedit Window");
3144 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
3145 int rots [4] = {0, 90, 180, 270};
3146 elm_win_wm_rotation_available_rotations_set (_preedit_window, rots, 4);
3147 int preedit_font_size = (int)(32 * _width_rate);
3149 _preedit_text = edje_object_add (evas_object_evas_get (_preedit_window));
3150 edje_object_file_set (_preedit_text, _candidate_edje_file.c_str (), "preedit_text");
3151 evas_object_size_hint_fill_set (_preedit_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
3152 evas_object_size_hint_weight_set (_preedit_text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3153 elm_win_resize_object_add (_preedit_window, _preedit_text);
3154 evas_object_show (_preedit_text);
3156 _tmp_preedit_text = evas_object_text_add (evas_object_evas_get (_preedit_window));
3157 evas_object_text_font_set (_tmp_preedit_text, _candidate_font_name.c_str (), preedit_font_size);
3162 * @brief Create native style candidate window.
3164 static void ui_create_native_candidate_window (void)
3166 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3167 _more_btn_width = 80 * (_width_rate > 1 ? 1 : _width_rate);
3168 _more_btn_height = 64 * _height_rate;
3170 _candidate_port_width = _screen_width;
3171 _candidate_port_height_min = 84 * _height_rate * _candidate_port_line;
3172 _candidate_port_height_min_2 = 84 * _height_rate + _candidate_port_height_min;
3173 _candidate_port_height_max = 426 * _height_rate + _candidate_port_height_min;
3174 _candidate_port_height_max_2 = 84 * _height_rate + _candidate_port_height_max;
3175 _candidate_land_width = _screen_height;
3176 _candidate_land_height_min = 84 * _width_rate;
3177 _candidate_land_height_min_2 = 168 * _width_rate;
3178 _candidate_land_height_max = 342 * _width_rate;
3179 _candidate_land_height_max_2 = 426 * _width_rate;
3181 _candidate_scroll_0_width_min= _screen_width;
3182 _candidate_scroll_0_width_max= _screen_height;
3183 _candidate_scroll_width_min = _screen_width;
3184 _candidate_scroll_width_max = _screen_height;
3185 _candidate_scroll_height_min = 252 * _width_rate;
3186 _candidate_scroll_height_max = 420 * _height_rate;
3188 _candidate_area_1_pos [0] = 0 * _width_rate;
3189 _candidate_area_1_pos [1] = 2 * _height_rate;
3190 _more_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3191 _more_btn_pos [1] = 12 * _height_rate;
3192 _more_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3193 _more_btn_pos [3] = 12 * _width_rate;
3194 _close_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3195 _close_btn_pos [1] = 12 * _height_rate;
3196 _close_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3197 _close_btn_pos [3] = 12 * _width_rate;
3199 _aux_height = 84 * _height_rate - 2;
3200 _aux_port_width = _screen_width;
3201 _aux_land_width = _screen_height;
3203 _item_min_height = 84 * _height_rate - 2;
3205 /* Create candidate window */
3206 if (_candidate_window == NULL) {
3207 _candidate_window = efl_create_window ("ISF Popup", "Prediction Window");
3208 int rots [4] = {0, 90, 180, 270};
3209 elm_win_wm_rotation_available_rotations_set (_candidate_window, rots, 4);
3210 if (_candidate_angle == 90 || _candidate_angle == 270) {
3211 _candidate_width = _candidate_land_width;
3212 _candidate_height = _candidate_land_height_min;
3214 _candidate_width = _candidate_port_width;
3215 _candidate_height = _candidate_port_height_min;
3219 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3220 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3221 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3222 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3223 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3224 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3225 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3226 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3229 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3230 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3231 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3232 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3233 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3234 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3235 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3236 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3238 /* Add dim background */
3239 Evas_Object *dim_bg = elm_bg_add (_candidate_window);
3240 evas_object_color_set (dim_bg, 0, 0, 0, 153);
3241 elm_win_resize_object_add (_candidate_window, dim_bg);
3242 evas_object_show (dim_bg);
3244 /* Add candidate background */
3245 _candidate_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3246 edje_object_file_set (_candidate_bg, _candidate_edje_file.c_str (), "candidate_bg");
3247 evas_object_size_hint_weight_set (_candidate_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3248 evas_object_resize (_candidate_bg, _candidate_port_width, _candidate_port_height_min);
3249 evas_object_move (_candidate_bg, 0, 0);
3250 evas_object_show (_candidate_bg);
3252 /* Create _candidate_0 scroller */
3253 _candidate_0_scroll = elm_scroller_add (_candidate_window);
3254 elm_scroller_bounce_set (_candidate_0_scroll, EINA_TRUE, EINA_FALSE);
3255 elm_scroller_policy_set (_candidate_0_scroll, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3256 evas_object_resize (_candidate_0_scroll, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
3257 evas_object_move (_candidate_0_scroll, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3259 /* Create candidate table */
3260 _candidate_0_table = elm_table_add (_candidate_window);
3261 evas_object_size_hint_weight_set (_candidate_0_table, 0.0, 0.0);
3262 evas_object_size_hint_align_set (_candidate_0_table, 0.0, 0.0);
3263 elm_table_padding_set (_candidate_0_table, 0, 0);
3264 elm_object_content_set (_candidate_0_scroll, _candidate_0_table);
3265 evas_object_show (_candidate_0_table);
3266 _candidate_area_1 = _candidate_0_scroll;
3268 /* Create more button */
3269 _more_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3270 if (_ise_width == 0 && _ise_height == 0)
3271 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
3273 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
3274 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
3275 evas_object_resize (_more_btn, _more_btn_width, _more_btn_height);
3276 evas_object_event_callback_add (_more_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_more_button_cb, NULL);
3278 /* Add scroller background */
3279 _candidate_scroll_width = _candidate_scroll_width_min;
3280 _scroller_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3281 edje_object_file_set (_scroller_bg, _candidate_edje_file.c_str (), "scroller_bg");
3282 evas_object_size_hint_weight_set (_scroller_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3283 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3284 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
3286 /* Create vertical scroller */
3287 _candidate_scroll = elm_scroller_add (_candidate_window);
3288 elm_scroller_bounce_set (_candidate_scroll, 0, 1);
3289 elm_scroller_policy_set (_candidate_scroll, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
3290 evas_object_resize (_candidate_scroll, _candidate_scroll_width, _candidate_scroll_height_max);
3291 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3292 elm_scroller_page_size_set (_candidate_scroll, 0, _item_min_height+_v_padding);
3293 evas_object_move (_candidate_scroll, 0, _candidate_port_height_min);
3295 /* Create candidate table */
3296 _candidate_table = elm_table_add (_candidate_window);
3297 evas_object_size_hint_weight_set (_candidate_table, 0.0, 0.0);
3298 evas_object_size_hint_align_set (_candidate_table, 0.0, 0.0);
3299 elm_table_padding_set (_candidate_table, 0, 0);
3300 elm_object_content_set (_candidate_scroll, _candidate_table);
3301 evas_object_show (_candidate_table);
3302 _candidate_area_2 = _candidate_scroll;
3303 evas_object_smart_callback_add (_candidate_scroll, "scroll,anim,stop", ui_candidate_scroller_stop_cb, NULL);
3305 /* Create close button */
3306 _close_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3307 if (_ise_width == 0 && _ise_height == 0)
3308 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
3310 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
3311 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
3312 evas_object_resize (_close_btn, _more_btn_width, _more_btn_height);
3313 evas_object_event_callback_add (_close_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_close_button_cb, NULL);
3315 _tmp_candidate_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3316 evas_object_text_font_set (_tmp_candidate_text, _candidate_font_name.c_str (), _candidate_font_size);
3319 _aux_area = elm_scroller_add (_candidate_window);
3320 elm_scroller_bounce_set (_aux_area, 1, 0);
3321 elm_scroller_policy_set (_aux_area, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3322 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
3323 evas_object_move (_aux_area, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3325 _aux_table = elm_table_add (_candidate_window);
3326 elm_object_content_set (_aux_area, _aux_table);
3327 elm_table_padding_set (_aux_table, 0, 0);
3328 evas_object_size_hint_weight_set (_aux_table, 0.0, 0.0);
3329 evas_object_size_hint_align_set (_aux_table, 0.0, 0.0);
3330 evas_object_show (_aux_table);
3332 _aux_line = edje_object_add (evas_object_evas_get (_candidate_window));
3333 edje_object_file_set (_aux_line, _candidate_edje_file.c_str (), "popup_line");
3334 evas_object_resize (_aux_line, _candidate_port_width, 2);
3335 evas_object_move (_aux_line, 0, _aux_height + 2);
3337 _tmp_aux_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3338 evas_object_text_font_set (_tmp_aux_text, _candidate_font_name.c_str (), _aux_font_size);
3340 evas_object_hide (_candidate_window);
3347 * @brief Create candidate window.
3351 static void ui_create_candidate_window (void)
3353 check_time ("\nEnter ui_create_candidate_window");
3354 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3355 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3360 _candidate_angle = 0;
3362 ui_create_native_candidate_window ();
3365 unsigned int set = 1;
3367 ecore_x_window_prop_card32_set (elm_win_xwindow_get (_candidate_window),
3368 ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
3371 int angle = efl_get_app_window_angle ();
3372 if (_candidate_angle != angle) {
3373 _candidate_angle = angle;
3374 ui_candidate_window_rotate (angle);
3376 ui_settle_candidate_window ();
3379 candidate_expanded = false;
3381 check_time ("Exit ui_create_candidate_window");
3385 * @brief Destroy candidate window.
3389 static void ui_destroy_candidate_window (void)
3391 check_time ("Enter ui_destroy_candidate_window");
3392 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3394 /* Delete candidate items, popup lines and seperator items */
3395 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3396 if (_candidate_0 [i]) {
3397 evas_object_del (_candidate_0 [i]);
3398 _candidate_0 [i] = NULL;
3400 if (_seperate_0 [i]) {
3401 evas_object_del (_seperate_0 [i]);
3402 _seperate_0 [i] = NULL;
3404 if (_seperate_items [i]) {
3405 evas_object_del (_seperate_items [i]);
3406 _seperate_items [i] = NULL;
3409 evas_object_del (_line_0 [i]);
3412 if (_line_items [i]) {
3413 evas_object_del (_line_items [i]);
3414 _line_items [i] = NULL;
3418 _aux_items.clear ();
3419 _aux_seperates.clear ();
3420 /* Delete candidate window */
3421 if (_candidate_window) {
3422 LOGD ("calling ui_candidate_hide (true)");
3423 ui_candidate_hide (true);
3425 evas_object_del (_candidate_window);
3426 _candidate_window = NULL;
3428 _candidate_area_1 = NULL;
3429 _candidate_area_2 = NULL;
3432 if (_tts_focus_rect) {
3433 evas_object_del (_tts_focus_rect);
3434 _tts_focus_rect = NULL;
3437 if (_candidate_bg) {
3438 evas_object_del (_candidate_bg);
3439 _candidate_bg = NULL;
3443 evas_object_del (_more_btn);
3448 evas_object_del (_scroller_bg);
3449 _scroller_bg = NULL;
3453 evas_object_del (_close_btn);
3458 evas_object_del (_aux_line);
3462 if (_tmp_candidate_text) {
3463 evas_object_del (_tmp_candidate_text);
3464 _tmp_candidate_text = NULL;
3467 if (_tmp_preedit_text) {
3468 evas_object_del (_tmp_preedit_text);
3469 _tmp_preedit_text = NULL;
3472 if (_tmp_aux_text) {
3473 evas_object_del (_tmp_aux_text);
3474 _tmp_aux_text = NULL;
3477 if (_preedit_text) {
3478 evas_object_del (_preedit_text);
3479 _preedit_text = NULL;
3482 if (_preedit_window) {
3483 evas_object_hide (_preedit_window);
3484 evas_object_del (_preedit_window);
3485 _preedit_window = NULL;
3489 check_time ("Exit ui_destroy_candidate_window");
3493 * @brief Settle candidate window position.
3495 static void ui_settle_candidate_window (void)
3497 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3499 if (!_candidate_window)
3502 /* If both ISE and candidate window are going to be hidden,
3503 let's just not move our candidate window */
3504 if (_ise_state == WINDOW_STATE_WILL_HIDE && _candidate_state == WINDOW_STATE_WILL_HIDE)
3508 int x, y, width, height;
3509 int ise_width = 0, ise_height = 0;
3510 bool get_geometry_result = false;
3512 /* Get candidate window position */
3513 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
3517 int pos_x = 0, pos_y = 0;
3518 if (_candidate_angle == 90 || _candidate_angle == 270)
3519 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_height, &ise_width);
3521 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_width, &ise_height);
3526 ise_width = _ise_width;
3527 ise_height = _ise_height;
3528 get_geometry_result = true;
3530 if ((_ise_state != WINDOW_STATE_SHOW && _ise_state != WINDOW_STATE_WILL_HIDE) ||
3531 (get_geometry_result == false) || (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
3536 int height2 = ui_candidate_get_valid_height ();
3538 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
3539 if (_candidate_angle == 90) {
3540 spot_x = _screen_width - ise_height - height2;
3542 } else if (_candidate_angle == 270) {
3543 spot_x = ise_height - (_candidate_height - height2);
3545 } else if (_candidate_angle == 180) {
3547 spot_y = ise_height - (_candidate_height - height2);
3550 spot_y = _screen_height - ise_height - height2;
3553 spot_x = _spot_location_x;
3554 spot_y = _spot_location_y;
3556 rectinfo ise_rect = {0, 0, (uint32)ise_width, (uint32)ise_height};
3557 if (_candidate_angle == 90 || _candidate_angle == 270) {
3558 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32)_screen_width)
3559 ise_rect.height = ISE_DEFAULT_HEIGHT_LANDSCAPE * _width_rate;
3561 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32) _screen_height)
3562 ise_rect.height = ISE_DEFAULT_HEIGHT_PORTRAIT * _height_rate;
3565 int nOffset = _candidate_port_height_min / 3;
3566 if (_candidate_angle == 270) {
3567 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3568 spot_x = _screen_width - _spot_location_top_y - (_candidate_height - height2);
3570 spot_x = _screen_width - _spot_location_y - _candidate_height;
3572 } else if (_candidate_angle == 90) {
3573 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3574 spot_x = _spot_location_top_y - height2;
3578 } else if (_candidate_angle == 180) {
3579 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3580 spot_y = _screen_height - _spot_location_top_y - (_candidate_height - height2);
3582 spot_y = _screen_height - _spot_location_y - _candidate_height;
3585 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3586 spot_y = _spot_location_top_y - height2;
3591 if (_candidate_angle == 90) {
3592 spot_y = (_screen_height - _candidate_width) / 2;
3593 spot_x = spot_x < _indicator_height ? _indicator_height : spot_x;
3594 if (spot_x > _screen_width - _candidate_height)
3595 spot_x = _screen_width - _candidate_height;
3596 } else if (_candidate_angle == 270) {
3597 spot_y = (_screen_height - _candidate_width) / 2;
3598 spot_x = spot_x < 0 ? 0 : spot_x;
3599 if (spot_x > _screen_width - (_indicator_height+_candidate_height))
3600 spot_x = _screen_width - (_indicator_height+_candidate_height);
3601 } else if (_candidate_angle == 180) {
3602 spot_x = (_screen_width - _candidate_width) / 2;
3603 spot_y = spot_y < 0 ? 0 : spot_y;
3604 if (spot_y > _screen_height - (_indicator_height+_candidate_height))
3605 spot_y = _screen_height - (_indicator_height+_candidate_height);
3607 spot_x = (_screen_width - _candidate_width) / 2;
3608 spot_y = spot_y < _indicator_height ? _indicator_height : spot_y;
3609 if (spot_y > _screen_height - _candidate_height)
3610 spot_y = _screen_height - _candidate_height;
3613 if (spot_x != x || spot_y != y) {
3614 _candidate_x = spot_x;
3615 _candidate_y = spot_y;
3616 evas_object_move (_candidate_window, spot_x, spot_y);
3617 LOGD ("Moving candidate window to : %d %d", spot_x, spot_y);
3618 if (_preedit_window) {
3619 if (_candidate_angle == 90) {
3620 spot_x -= _preedit_height;
3621 spot_y = _screen_height - _preedit_width;
3622 } else if (_candidate_angle == 270) {
3624 } else if (_candidate_angle == 180) {
3625 spot_x = _screen_width - _preedit_width;
3628 spot_y -= _preedit_height;
3630 evas_object_move (_preedit_window, spot_x, spot_y);
3632 if (_candidate_state == WINDOW_STATE_SHOW) {
3633 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
3637 #endif /* CANDIDATE */
3640 * @brief Set soft candidate geometry.
3642 * @param x The x position in screen.
3643 * @param y The y position in screen.
3644 * @param width The candidate window width.
3645 * @param height The candidate window height.
3647 static void set_soft_candidate_geometry (int x, int y, int width, int height)
3649 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
3651 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);
3653 if ((_candidate_mode != SOFT_CANDIDATE_WINDOW) || (_info_manager->get_current_toolbar_mode () != TOOLBAR_KEYBOARD_MODE))
3657 _soft_candidate_width = width;
3658 _soft_candidate_height = height;
3659 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry());
3661 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
3664 #if ISF_BUILD_CANDIDATE_UI
3665 //////////////////////////////////////////////////////////////////////
3666 // End of Candidate Functions
3667 //////////////////////////////////////////////////////////////////////
3670 * @brief Set transient for app window.
3672 * @param window The Ecore_X_Window handler of app window.
3674 static void efl_set_transient_for_app_window (Ecore_X_Window window)
3676 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3678 /* Set a transient window for window stack */
3679 Ecore_X_Window xAppWindow = efl_get_app_window ();
3680 ecore_x_icccm_transient_for_set (window, xAppWindow);
3682 LOGD ("win : %x, forwin : %x", window, xAppWindow);
3685 static int efl_get_window_rotate_angle (Ecore_X_Window win)
3687 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3692 unsigned char *prop_data = NULL;
3694 ret = ecore_x_window_prop_property_get (win,
3695 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
3696 if (ret && prop_data) {
3697 memcpy (&angle, prop_data, sizeof (int));
3698 LOGD ("WINDOW angle of %p is %d", win, angle);
3700 std::cerr << "ecore_x_window_prop_property_get () is failed!!!\n";
3701 LOGW ("WINDOW angle of %p FAILED!", win);
3708 #endif /* HAVE_ECOREX */
3711 * @brief Get angle for app window.
3713 * @param win_obj The Evas_Object handler of application window.
3715 * @return The angle of app window.
3717 static int efl_get_app_window_angle ()
3719 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3721 return efl_get_window_rotate_angle (efl_get_app_window ());
3727 #endif /* CANDIDATE */
3730 * @brief Get angle for ise window.
3732 * @param win_obj The Evas_Object handler of ise window.
3734 * @return The angle of ise window.
3736 static int efl_get_ise_window_angle ()
3738 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3740 return efl_get_window_rotate_angle (_ise_window);
3747 #if ISF_BUILD_CANDIDATE_UI
3750 * @brief Get angle of quickpanel window.
3752 * @return The angle of quickpanel window.
3754 static int efl_get_quickpanel_window_angle ()
3756 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3757 return efl_get_window_rotate_angle (efl_get_quickpanel_window ());
3762 * @brief Set showing effect for application window.
3764 * @param win The Evas_Object handler of application window.
3765 * @param strEffect The pointer of effect string.
3767 static void efl_set_showing_effect_for_app_window (Evas_Object *win, const char* strEffect)
3769 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3771 ecore_x_icccm_name_class_set (elm_win_xwindow_get (static_cast<Evas_Object*>(win)), strEffect, "ISF");
3776 * @brief Create elementary window.
3778 * @param strWinName The window name.
3779 * @param strEffect The window effect string.
3781 * @return The window pointer
3783 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect)
3785 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3787 Evas_Object *win = elm_win_add (NULL, strWinName, ELM_WIN_UTILITY);
3788 elm_win_title_set (win, strWinName);
3790 /* set window properties */
3791 elm_win_autodel_set (win, EINA_TRUE);
3792 elm_object_focus_allow_set (win, EINA_FALSE);
3793 elm_win_borderless_set (win, EINA_TRUE);
3794 elm_win_alpha_set (win, EINA_TRUE);
3795 elm_win_prop_focus_skip_set (win, EINA_TRUE);
3796 efl_set_showing_effect_for_app_window (win, strEffect);
3800 #endif /* CANDIDATE */
3804 * @brief Create elementary control window.
3806 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3808 static Eina_Bool efl_create_control_window (void)
3810 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3812 /* WMSYNC, #1 Creating and registering control window */
3813 if (ecore_x_display_get () == NULL)
3816 Ecore_X_Window root = ecore_x_window_root_first_get ();
3817 _control_window = ecore_x_window_input_new (root, -100, -100, 1, 1);
3818 //ecore_x_e_virtual_keyboard_control_window_set (root, _control_window, 0, EINA_TRUE);
3820 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_CONTROL_WINDOW");
3821 ecore_x_window_prop_xid_set (root, atom, ECORE_X_ATOM_WINDOW, &_control_window, 1);
3827 * @brief Get an window's x window id.
3829 * @param name the property name.
3830 * @return X window id.
3832 static Ecore_X_Window efl_get_window (const char *name)
3834 /* Gets the XID of the window from the root window property */
3838 unsigned long nitems_return;
3839 unsigned long bytes_after_return;
3840 unsigned char *data = NULL;
3841 Ecore_X_Window window = 0;
3843 ret = XGetWindowProperty ((Display *)ecore_x_display_get (),
3844 ecore_x_window_root_get (_control_window),
3845 ecore_x_atom_get (name),
3846 0, G_MAXLONG, False, XA_WINDOW, &type_return,
3847 &format_return, &nitems_return, &bytes_after_return,
3850 if (ret == Success) {
3851 if ((type_return == XA_WINDOW) && (format_return == 32) && (data)) {
3852 window = *(Window *)data;
3855 std::cerr << "XGetWindowProperty () is failed!!!\n";
3865 * @brief Get app window's x window id.
3867 * @return the X window id of application to have focus or to request to show IME.
3869 static Ecore_X_Window efl_get_app_window (void)
3871 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3873 return efl_get_window ("_ISF_ACTIVE_WINDOW");
3877 * @brief Get clipboard window's x window id.
3879 * @return the X window id of clipboard.
3881 static Ecore_X_Window efl_get_clipboard_window (void)
3883 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3885 return efl_get_window ("CBHM_ELM_WIN");
3889 * @brief Get global navigation window's x window id.
3891 * @return the X window id of global navigation.
3893 static Ecore_X_Window efl_get_global_navigation_window (void)
3895 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3897 return efl_get_window ("GNB_WIN");
3901 * @brief Get app window's x window id.
3903 * @return the X window id of quick panel.
3905 static Ecore_X_Window efl_get_quickpanel_window (void)
3907 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3909 Ecore_X_Window rootWin = ecore_x_window_root_first_get ();
3910 Ecore_X_Window qpwin;
3911 ecore_x_window_prop_xid_get (rootWin, ecore_x_atom_get ("_E_ILLUME_QUICKPANEL_WINDOW_LIST"), ECORE_X_ATOM_WINDOW, &qpwin, 1);
3917 * @brief Get default zone geometry.
3919 * @param x The zone x position.
3920 * @param y The zone y position.
3921 * @param w The zone width.
3922 * @param h The zone height.
3924 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3926 static Eina_Bool efl_get_default_zone_geometry_info (Ecore_X_Window root, uint *x, uint *y, uint *w, uint *h)
3928 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3930 Ecore_X_Atom zone_geometry_atom;
3931 Ecore_X_Window *zone_lists;
3936 zone_geometry_atom = ecore_x_atom_get ("_E_ILLUME_ZONE_GEOMETRY");
3937 if (!zone_geometry_atom) {
3943 num_zone_lists = ecore_x_window_prop_window_list_get (root, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, &zone_lists);
3944 if (num_zone_lists > 0) {
3945 num_ret = ecore_x_window_prop_card32_get (zone_lists[0], zone_geometry_atom, geom, 4);
3947 if (x) *x = geom[0];
3948 if (y) *y = geom[1];
3949 if (w) *w = geom[2];
3950 if (h) *h = geom[3];
3956 /* if there is no zone available */
3961 /* We must free zone_lists */
3967 #endif /* HAVE_ECOREX */
3969 #if ISF_BUILD_CANDIDATE_UI
3971 * @brief Get screen resolution.
3973 * @param width The screen width.
3974 * @param height The screen height.
3976 static void efl_get_screen_resolution (int &width, int &height)
3978 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3980 static Evas_Coord scr_w = 0, scr_h = 0;
3981 if (scr_w == 0 || scr_h == 0) {
3984 if (efl_get_default_zone_geometry_info (ecore_x_window_root_first_get (), NULL, NULL, &w, &h)) {
3988 ecore_x_window_size_get (ecore_x_window_root_first_get (), &scr_w, &scr_h);
3991 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
3993 ecore_wl2_display_screen_size_get(wl2_display, &scr_w, &scr_h);
4000 #endif /* CANDIDATE */
4002 //////////////////////////////////////////////////////////////////////
4003 // Start of PanelAgent Functions
4004 //////////////////////////////////////////////////////////////////////
4007 * @brief Initialize panel agent.
4009 * @param config The config string for PanelAgent.
4010 * @param display The current display.
4011 * @param resident The variable indicates whether panel will be resident.
4013 * @return true if initialize is successful, otherwise return false.
4015 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident)
4017 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4019 LOGD ("initializing panel agent");
4021 _info_manager = new InfoManager ();
4023 if (!_info_manager || !_info_manager->initialize (_info_manager, config, display, resident)) {
4024 ISF_SAVE_LOG ("panel_agent initialize fail!");
4028 _info_manager->signal_connect_focus_in (slot (slot_focus_in));
4029 _info_manager->signal_connect_focus_out (slot (slot_focus_out));
4030 _info_manager->signal_connect_expand_candidate (slot (slot_expand_candidate));
4031 _info_manager->signal_connect_contract_candidate (slot (slot_contract_candidate));
4032 _info_manager->signal_connect_set_candidate_ui (slot (slot_set_candidate_style));
4033 _info_manager->signal_connect_update_factory_info (slot (slot_update_factory_info));
4034 _info_manager->signal_connect_update_spot_location (slot (slot_update_spot_location));
4035 _info_manager->signal_connect_update_input_context (slot (slot_update_input_context));
4036 _info_manager->signal_connect_update_ise_geometry (slot (slot_update_ise_geometry));
4037 #if ISF_BUILD_CANDIDATE_UI
4038 _info_manager->signal_connect_show_preedit_string (slot (slot_show_preedit_string));
4039 _info_manager->signal_connect_show_aux_string (slot (slot_show_aux_string));
4041 _info_manager->signal_connect_show_lookup_table (slot (slot_show_candidate_table));
4042 _info_manager->signal_connect_hide_preedit_string (slot (slot_hide_preedit_string));
4043 _info_manager->signal_connect_hide_aux_string (slot (slot_hide_aux_string));
4044 _info_manager->signal_connect_hide_lookup_table (slot (slot_hide_candidate_table));
4045 _info_manager->signal_connect_update_preedit_string (slot (slot_update_preedit_string));
4046 _info_manager->signal_connect_update_preedit_caret (slot (slot_update_preedit_caret));
4047 _info_manager->signal_connect_update_aux_string (slot (slot_update_aux_string));
4048 _info_manager->signal_connect_update_lookup_table (slot (slot_update_candidate_table));
4049 _info_manager->signal_connect_select_candidate (slot (slot_select_candidate));
4050 _info_manager->signal_connect_get_candidate_geometry (slot (slot_get_candidate_geometry));
4051 _info_manager->signal_connect_get_input_panel_geometry (slot (slot_get_input_panel_geometry));
4052 _info_manager->signal_connect_set_active_ise_by_uuid (slot (slot_set_active_ise));
4053 _info_manager->signal_connect_get_ise_list (slot (slot_get_ise_list));
4054 _info_manager->signal_connect_get_all_helper_ise_info (slot (slot_get_all_helper_ise_info));
4055 _info_manager->signal_connect_set_has_option_helper_ise_info(slot (slot_set_has_option_helper_ise_info));
4056 _info_manager->signal_connect_set_enable_helper_ise_info (slot (slot_set_enable_helper_ise_info));
4057 _info_manager->signal_connect_show_helper_ise_list (slot (slot_show_helper_ise_list));
4058 _info_manager->signal_connect_show_helper_ise_selector (slot (slot_show_helper_ise_selector));
4059 _info_manager->signal_connect_is_helper_ise_enabled (slot (slot_is_helper_ise_enabled));
4060 _info_manager->signal_connect_get_ise_information (slot (slot_get_ise_information));
4061 _info_manager->signal_connect_get_keyboard_ise_list (slot (slot_get_keyboard_ise_list));
4062 _info_manager->signal_connect_get_language_list (slot (slot_get_language_list));
4063 _info_manager->signal_connect_get_all_language (slot (slot_get_all_language));
4064 _info_manager->signal_connect_get_ise_language (slot (slot_get_ise_language));
4065 _info_manager->signal_connect_get_ise_info_by_uuid (slot (slot_get_ise_info));
4066 _info_manager->signal_connect_set_keyboard_ise (slot (slot_set_keyboard_ise));
4067 _info_manager->signal_connect_get_keyboard_ise (slot (slot_get_keyboard_ise));
4068 _info_manager->signal_connect_accept_connection (slot (slot_accept_connection));
4069 _info_manager->signal_connect_close_connection (slot (slot_close_connection));
4070 _info_manager->signal_connect_exit (slot (slot_exit));
4072 _info_manager->signal_connect_register_helper (slot(slot_register_helper));
4073 _info_manager->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
4074 _info_manager->signal_connect_show_ise (slot (slot_show_ise));
4075 _info_manager->signal_connect_hide_ise (slot (slot_hide_ise));
4077 _info_manager->signal_connect_will_hide_ack (slot (slot_will_hide_ack));
4079 _info_manager->signal_connect_set_keyboard_mode (slot (slot_set_keyboard_mode));
4081 _info_manager->signal_connect_candidate_will_hide_ack (slot (slot_candidate_will_hide_ack));
4082 _info_manager->signal_connect_get_ise_state (slot (slot_get_ise_state));
4083 _info_manager->signal_connect_start_default_ise (slot (slot_start_default_ise));
4084 _info_manager->signal_connect_stop_default_ise (slot (slot_stop_default_ise));
4085 _info_manager->signal_connect_show_panel (slot (slot_show_helper_ise_selector));
4086 #if ENABLE_REMOTE_INPUT
4087 _info_manager->signal_connect_remoteinput_send_input_message(slot (slot_send_remote_input_message));
4088 _info_manager->signal_connect_remoteinput_send_surrounding_text(slot (slot_recv_remote_surrounding_text));
4090 _info_manager->signal_connect_get_recent_ise_geometry (slot (slot_get_recent_ise_geometry));
4091 _info_manager->signal_connect_check_privilege_by_sockfd (slot (slot_check_privilege_by_sockfd));
4093 _info_manager->signal_connect_run_helper (slot (slot_run_helper));
4094 _info_manager->signal_connect_launch_option_application (slot (slot_launch_option_application));
4095 _info_manager->signal_connect_get_ise_setting_appid (slot (slot_get_ise_setting_appid));
4097 LOGD ("initializing panel agent succeeded");
4102 static void delete_ise_hide_timer (void)
4104 LOGD ("deleting ise_hide_timer");
4105 if (_ise_hide_timer) {
4106 ecore_timer_del (_ise_hide_timer);
4107 _ise_hide_timer = NULL;
4111 static void hide_ise ()
4113 LOGD ("send request to hide helper");
4114 String uuid = _info_manager->get_current_helper_uuid ();
4115 _info_manager->hide_helper (uuid);
4117 /* Only if we are not already in HIDE state */
4118 if (_ise_state != WINDOW_STATE_HIDE) {
4119 /* From this point, slot_get_input_panel_geometry should return hidden state geometry */
4120 _ise_state = WINDOW_STATE_WILL_HIDE;
4122 _updated_hide_state_geometry = false;
4126 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
4128 #if ISF_BUILD_CANDIDATE_UI
4129 if (_candidate_window) {
4130 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)
4131 ui_candidate_hide (true, true, true);
4133 ui_candidate_hide (true, false, true);
4135 #endif /* CANDIDATE */
4138 #ifdef HAVE_NOTIFICATION
4139 delete_notification (&ise_selector_module_noti);
4144 #if ENABLE_MULTIWINDOW_SUPPORT
4145 static Eina_Bool ise_hide_timeout (void *data)
4147 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4149 delete_ise_hide_timer ();
4152 return ECORE_CALLBACK_CANCEL;
4157 * @brief Insert data to ime_info table.
4159 * @param list The list to store uuid
4161 * @return true if it is successful, otherwise return false.
4163 static bool update_ise_list (std::vector<String> &list)
4165 std::vector<String> uuids;
4166 std::vector<TOOLBAR_MODE_T> modes;
4167 std::vector<ImeInfoDB>::iterator iter;
4170 if (_ime_info.size() == 0) {
4171 if (isf_pkg_select_all_ime_info_db(_ime_info) == 0)
4175 /* Update _groups */
4177 std::vector<String> ise_langs;
4178 for (size_t i = 0; i < _ime_info.size (); ++i) {
4179 scim_split_string_list(ise_langs, _ime_info[i].languages);
4180 for (size_t j = 0; j < ise_langs.size (); j++) {
4181 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
4182 _groups[ise_langs[j]].push_back (i);
4187 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
4188 uuids.push_back(iter->appid);
4189 modes.push_back(iter->mode);
4192 if (uuids.size() > 0) {
4196 _info_manager->update_ise_list (list);
4198 if (_initial_ise_uuid.length () > 0) {
4199 String active_uuid = _initial_ise_uuid;
4200 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
4201 if (std::find (uuids.begin (), uuids.end (), default_uuid) == uuids.end ()) {
4202 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (modes[get_ise_index (_initial_ise_uuid)] != TOOLBAR_KEYBOARD_MODE)) {
4203 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4206 if (set_active_ise (active_uuid, _soft_keyboard_launched) == false) {
4207 if (_initial_ise_uuid.compare (active_uuid)) {
4208 LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
4209 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
4212 } else if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) { // Check whether keyboard engine is installed
4213 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
4214 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
4215 if (std::find (uuids.begin (), uuids.end (), keyboard_uuid) == uuids.end ()) {
4216 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4217 _info_manager->change_factory (active_uuid);
4218 _config->write (IMENGINE_KEY, active_uuid);
4225 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
4227 if (_ime_info.size () > 0 && _ime_info[0].display_lang.compare(lang_str) == 0)
4228 _locale_string = String (lang_str);
4234 LOGW ("No IME list");
4236 #ifdef HAVE_PKGMGR_INFO
4238 int ret = package_manager_create (&pkgmgr);
4239 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4240 ret = package_manager_set_event_cb (pkgmgr, _package_manager_event_cb, NULL);
4241 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4242 LOGD ("package_manager_set_event_cb succeeded.");
4245 LOGE ("package_manager_set_event_cb failed(%d)", ret);
4249 LOGE ("package_manager_create failed(%d)", ret);
4258 * @brief Focus in slot function for PanelAgent.
4260 static void slot_focus_in (void)
4262 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4265 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
4266 if (_launch_ise_on_request && !_soft_keyboard_launched) {
4267 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
4268 if (uuid.length () > 0 && (_ime_info[get_ise_index(uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
4269 LOGD ("Start helper (%s)", uuid.c_str ());
4271 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
4272 if (_info_manager->start_helper (uuid))
4273 _soft_keyboard_launched = true;
4278 #if ISF_BUILD_CANDIDATE_UI
4279 ui_candidate_delete_destroy_timer ();
4280 #endif /* CANDIDATE */
4284 * @brief Focus out slot function for PanelAgent.
4286 static void slot_focus_out (void)
4288 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4292 #if ISF_BUILD_CANDIDATE_UI
4293 ui_candidate_delete_destroy_timer ();
4294 _destroy_timer = ecore_timer_add (ISF_CANDIDATE_DESTROY_DELAY, ui_candidate_destroy_timeout, NULL);
4295 #endif /* CANDIDATE */
4299 * @brief Expand candidate slot function for PanelAgent.
4301 static void slot_expand_candidate (void)
4303 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4304 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4307 #if ISF_BUILD_CANDIDATE_UI
4308 if (_candidate_area_2 && !_candidate_area_2_visible)
4309 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
4310 #endif /* CANDIDATE */
4314 * @brief Contract candidate slot function for PanelAgent.
4316 static void slot_contract_candidate (void)
4318 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4320 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4323 #if ISF_BUILD_CANDIDATE_UI
4324 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
4325 #endif /* CANDIDATE */
4329 * @brief Set candidate style slot function for PanelAgent.
4331 * @param portrait_line The displayed line number for portrait.
4332 * @param mode The candidate mode.
4334 static void slot_set_candidate_style (int portrait_line, int mode)
4336 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " display_line:" << portrait_line << " mode:" << mode << "\n";
4337 #if ISF_BUILD_CANDIDATE_UI
4338 if ((portrait_line != _candidate_port_line) || (mode != _candidate_mode)) {
4339 _candidate_mode = (ISF_CANDIDATE_MODE_T)mode;
4340 _candidate_port_line = (ISF_CANDIDATE_PORTRAIT_LINE_T)portrait_line;
4341 _soft_candidate_width = 0;
4342 _soft_candidate_height = 0;
4344 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4345 if (_candidate_window)
4346 ui_destroy_candidate_window ();
4351 if (_candidate_window)
4352 ui_create_candidate_window ();
4354 #endif /* CANDIDATE */
4357 #if defined(HAVE_NOTIFICATION) || defined(HAVE_ECOREX)
4358 static unsigned int get_ise_count (TOOLBAR_MODE_T mode, bool valid_helper)
4360 unsigned int ise_count = 0;
4361 for (unsigned int i = 0; i < _ime_info.size (); i++) {
4362 if (mode == _ime_info[i].mode) {
4363 if (mode == TOOLBAR_KEYBOARD_MODE || !valid_helper)
4365 else if (_ime_info[i].is_enabled)
4375 * @brief Update keyboard ISE information slot function for PanelAgent.
4377 * @param info The information of current Keyboard ISE.
4379 static void slot_update_factory_info (const PanelFactoryInfo &info)
4381 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4383 String ise_name = info.name;
4385 String old_ise = _info_manager->get_current_ise_name ();
4386 #if ISF_BUILD_CANDIDATE_UI
4387 if (old_ise != ise_name) {
4388 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && _candidate_window) {
4389 ui_destroy_candidate_window ();
4392 #endif /* CANDIDATE */
4394 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
4396 if (TOOLBAR_HELPER_MODE == mode)
4397 ise_name = _ime_info[get_ise_index (_info_manager->get_current_helper_uuid())].label;
4399 if (ise_name.length () > 0)
4400 _info_manager->set_current_ise_name (ise_name);
4402 #ifdef HAVE_NOTIFICATION
4403 if (_MOBILE || _COMMON) {
4404 if (old_ise != ise_name) {
4405 if (TOOLBAR_KEYBOARD_MODE == mode) {
4406 char noti_msg[256] = {0};
4407 unsigned int keyboard_ise_count = get_ise_count (TOOLBAR_KEYBOARD_MODE, false);
4408 if (keyboard_ise_count == 0) {
4409 LOGD ("the number of keyboard ise is %d", keyboard_ise_count);
4412 else if (keyboard_ise_count >= 2) {
4413 snprintf (noti_msg, sizeof (noti_msg), _("%s selected"), ise_name.c_str ());
4415 else if (keyboard_ise_count == 1) {
4416 snprintf (noti_msg, sizeof (noti_msg), _("Only %s available"), ise_name.c_str ());
4419 notification_status_message_post (noti_msg);
4420 LOGD ("%s", noti_msg);
4428 * @brief Update cursor position slot function for PanelAgent.
4430 * @param x The x position of current cursor.
4431 * @param y The bottom y position of current cursor.
4432 * @param top_y The top y position of current cursor.
4434 static void slot_update_spot_location (int x, int y, int top_y)
4436 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4438 #if ISF_BUILD_CANDIDATE_UI
4439 if (x >= 0 && x < _screen_height && y >= 0 && y < _screen_height) {
4440 _spot_location_x = x;
4441 _spot_location_y = y;
4442 _spot_location_top_y = top_y;
4444 ui_settle_candidate_window ();
4446 #endif /* CANDIDATE */
4450 * @brief The input context of ISE is changed.
4452 * @param type The event type.
4453 * @param value The event value.
4455 static void slot_update_input_context (int type, int value)
4460 * @brief Update ise geometry.
4462 * @param x The x position in screen.
4463 * @param y The y position in screen.
4464 * @param width The ISE window width.
4465 * @param height The ISE window height.
4467 static void slot_update_ise_geometry (int x, int y, int width, int height)
4469 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
4471 LOGD ("x : %d , y : %d , width : %d , height : %d, _ise_state : %d", x, y, width, height, _ise_state);
4473 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
4474 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4475 /*IF ISE sent the ise_geometry information when the current_keyboard_mode is H/W mode and candidate_mode is SOFT_CANDIDATE,
4476 It means that given geometry information is for the candidate window */
4477 set_soft_candidate_geometry (x, y, width, height);
4485 #if ISF_BUILD_CANDIDATE_UI
4487 _ise_height = height;
4489 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
4490 ui_settle_candidate_window ();
4492 #endif /* CANDIDATE */
4494 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
4495 _ise_reported_geometry.valid = true;
4496 _ise_reported_geometry.angle = efl_get_ise_window_angle ();
4497 _ise_reported_geometry.geometry.pos_x = x;
4498 _ise_reported_geometry.geometry.pos_y = y;
4499 _ise_reported_geometry.geometry.width = width;
4500 _ise_reported_geometry.geometry.height = height;
4501 if (_ise_state == WINDOW_STATE_SHOW) {
4503 set_keyboard_geometry_atom_info (_app_window, _ise_reported_geometry.geometry);
4505 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
4510 #if ISF_BUILD_CANDIDATE_UI
4512 * @brief Show preedit slot function for PanelAgent.
4514 static void slot_show_preedit_string (void)
4516 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4518 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4521 if (_preedit_window == NULL) {
4522 ui_create_preedit_window ();
4524 /* Move preedit window according to candidate window position */
4525 if (_candidate_window) {
4526 /* Get candidate window position */
4527 int x, y, width, height;
4528 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
4530 int height2 = ui_candidate_get_valid_height ();
4531 int angle = efl_get_app_window_angle ();
4534 x -= _preedit_height;
4535 y = _screen_height - _preedit_width;
4536 } else if (_candidate_angle == 270) {
4538 } else if (_candidate_angle == 180) {
4539 x = _screen_width - _preedit_width;
4542 y -= _preedit_height;
4545 if (_preedit_window)
4546 evas_object_move (_preedit_window, x, y);
4550 if (_preedit_window && evas_object_visible_get (_preedit_window))
4553 slot_show_candidate_table ();
4555 if (_preedit_window)
4556 evas_object_show (_preedit_window);
4560 * @brief Show aux slot function for PanelAgent.
4562 static void slot_show_aux_string (void)
4564 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4566 if (_candidate_window == NULL)
4567 ui_create_candidate_window ();
4569 if (_aux_area == NULL || _aux_area_visible)
4572 evas_object_show (_aux_area);
4573 _aux_area_visible = true;
4574 ui_candidate_window_adjust ();
4576 LOGD ("calling ui_candidate_show ()");
4577 ui_candidate_show ();
4578 ui_settle_candidate_window ();
4579 ui_candidate_delete_destroy_timer ();
4582 #endif /* CANDIDATE */
4585 * @brief Show candidate table slot function for PanelAgent.
4587 static void slot_show_candidate_table (void)
4589 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4590 _info_manager->helper_candidate_show ();
4594 #if ISF_BUILD_CANDIDATE_UI
4595 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4596 if (_candidate_window == NULL)
4597 ui_create_candidate_window ();
4600 if (_candidate_state == WINDOW_STATE_SHOW &&
4601 (_candidate_area_1_visible || _candidate_area_2_visible)) {
4602 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
4607 evas_object_show (_candidate_area_1);
4608 _candidate_area_1_visible = true;
4609 ui_candidate_window_adjust ();
4611 LOGD ("calling ui_candidate_show ()");
4612 ui_candidate_show ();
4613 ui_settle_candidate_window ();
4614 ui_candidate_delete_destroy_timer ();
4616 #ifdef HAVE_FEEDBACK
4617 int feedback_result = feedback_initialize ();
4619 if (FEEDBACK_ERROR_NONE == feedback_result) {
4620 LOGD ("Feedback initialize successful");
4621 feedback_initialized = true;
4623 LOGW ("Feedback initialize fail : %d", feedback_result);
4624 feedback_initialized = false;
4626 #endif /* HAVE_FEEDBACK */
4627 #endif /* CANDIDATE */
4631 * @brief Hide preedit slot function for PanelAgent.
4633 static void slot_hide_preedit_string (void)
4635 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4637 #if ISF_BUILD_CANDIDATE_UI
4638 if (!_preedit_window || !evas_object_visible_get (_preedit_window))
4641 evas_object_hide (_preedit_window);
4642 #endif /* CANDIDATE */
4646 * @brief Hide aux slot function for PanelAgent.
4648 static void slot_hide_aux_string (void)
4650 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4652 #if ISF_BUILD_CANDIDATE_UI
4653 if (!_aux_area || !_aux_area_visible)
4656 evas_object_hide (_aux_area);
4657 _aux_area_visible = false;
4658 elm_scroller_region_show (_aux_area, 0, 0, 10, 10);
4659 ui_candidate_window_adjust ();
4661 LOGD ("calling ui_candidate_hide (false, true, true)");
4662 ui_candidate_hide (false, true, true);
4663 ui_settle_candidate_window ();
4665 if (ui_candidate_can_be_hide ()) {
4666 _candidate_show_requested = false;
4667 LOGD ("setting _show_candidate_requested to FALSE");
4669 #endif /* CANDIDATE */
4673 * @brief Hide candidate table slot function for PanelAgent.
4675 static void slot_hide_candidate_table (void)
4677 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4679 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4680 _info_manager->helper_candidate_hide ();
4684 #if ISF_BUILD_CANDIDATE_UI
4685 if (!_candidate_area_1 || _candidate_state == WINDOW_STATE_WILL_HIDE)
4688 if (_candidate_area_1_visible || _candidate_area_2_visible) {
4689 bool bForce = false;
4690 if (_candidate_area_1_visible) {
4691 if (_aux_area_visible) {
4692 evas_object_hide (_candidate_area_1);
4693 _candidate_area_1_visible = false;
4694 evas_object_hide (_more_btn);
4696 /* Let's not actually hide the _candidate_area_1 object, for the case that
4697 even if the application replies CANDIDATE_WILL_HIDE_ACK a little late,
4698 it is better to display the previous candidates instead of blank screen */
4699 _candidate_area_1_visible = false;
4703 if (_candidate_area_2_visible) {
4704 evas_object_hide (_candidate_area_2);
4705 _candidate_area_2_visible = false;
4706 evas_object_hide (_scroller_bg);
4707 evas_object_hide (_close_btn);
4708 _info_manager->candidate_more_window_hide ();
4710 ui_candidate_window_adjust ();
4712 LOGD ("calling ui_candidate_hide (%d, true, true)", bForce);
4713 ui_candidate_hide (bForce, true, true);
4714 ui_settle_candidate_window ();
4717 #ifdef HAVE_FEEDBACK
4718 int feedback_result = feedback_deinitialize ();
4720 if (FEEDBACK_ERROR_NONE == feedback_result)
4721 LOGD ("Feedback deinitialize successful");
4723 LOGW ("Feedback deinitialize fail : %d", feedback_result);
4725 feedback_initialized = false;
4728 if (ui_candidate_can_be_hide ()) {
4729 _candidate_show_requested = false;
4730 LOGD ("setting _show_candidate_requested to FALSE");
4732 #endif /* CANDIDATE */
4736 * @brief Update preedit slot function for PanelAgent.
4738 * @param str The new preedit string.
4739 * @param attrs The attribute list of new preedit string.
4741 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret)
4743 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " string=" << str << "\n";
4745 #if ISF_BUILD_CANDIDATE_UI
4746 if (str.length () <= 0)
4749 if (_preedit_window == NULL || !evas_object_visible_get (_preedit_window)) {
4750 slot_show_preedit_string ();
4753 int x, y, width, height, candidate_width;
4754 evas_object_text_text_set (_tmp_preedit_text, str.c_str ());
4755 evas_object_geometry_get (_tmp_preedit_text, &x, &y, &width, &height);
4756 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &candidate_width, &height);
4757 _preedit_width = (width + ISF_PREEDIT_BORDER * 2) < candidate_width ? (width + ISF_PREEDIT_BORDER * 2) : candidate_width;
4759 /* Resize preedit window and avoid text blink */
4760 int old_width, old_height;
4761 evas_object_geometry_get (_preedit_window, &x, &y, &old_width, &old_height);
4762 if (old_width < _preedit_width) {
4763 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4764 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4766 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4767 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4770 /* Move preedit window */
4771 if (_candidate_angle == 90 || _candidate_angle == 180) {
4772 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_preedit_window)), &x, &y, &width, &height);
4773 if (_candidate_angle == 90) {
4774 y = _screen_height - _preedit_width;
4775 } else if (_candidate_angle == 180) {
4776 x = _screen_width - _preedit_width;
4778 evas_object_move (_preedit_window, x, y);
4780 #endif /* CANDIDATE */
4784 * @brief Update caret slot function for PanelAgent.
4786 * @param caret The caret position.
4788 static void slot_update_preedit_caret (int caret)
4790 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " caret=" << caret << "\n";
4793 #if ISF_BUILD_CANDIDATE_UI
4795 * @brief Set highlight text color and background color for edje object.
4797 * @param item The edje object pointer.
4798 * @param nForeGround The text color.
4799 * @param nBackGround The background color.
4800 * @param bSetBack The flag for background color.
4802 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack)
4804 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4806 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
4807 if (edje_object_color_class_get (item, "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4808 r = SCIM_RGB_COLOR_RED (nForeGround);
4809 g = SCIM_RGB_COLOR_GREEN (nForeGround);
4810 b = SCIM_RGB_COLOR_BLUE (nForeGround);
4811 edje_object_color_class_set (item, "text_color", r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
4813 if (bSetBack && edje_object_color_class_get (item, "rect_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4814 r = SCIM_RGB_COLOR_RED (nBackGround);
4815 g = SCIM_RGB_COLOR_GREEN (nBackGround);
4816 b = SCIM_RGB_COLOR_BLUE (nBackGround);
4817 edje_object_color_class_set (item, "rect_color", r, g, b, 255, r2, g2, b2, a2, r3, g3, b3, a3);
4820 #endif /* CANDIDATE */
4823 * @brief Update aux slot function for PanelAgent.
4825 * @param str The new aux string.
4826 * @param attrs The attribute list of new aux string.
4828 static void slot_update_aux_string (const String &str, const AttributeList &attrs)
4830 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4831 #if ISF_BUILD_CANDIDATE_UI
4832 if (_candidate_window == NULL)
4833 ui_create_candidate_window ();
4835 if (!_aux_area || (str.length () <= 0))
4838 if (!_aux_area_visible) {
4839 LOGD ("calling ui_candidate_show ()");
4840 ui_candidate_show ();
4841 slot_show_aux_string ();
4844 int x, y, width, height, item_width = 0;
4845 unsigned int window_width = 0, count = 0, i;
4847 Evas_Object *aux_edje = NULL;
4849 /* Get highlight item index */
4850 int aux_index = -1, aux_start = 0, aux_end = 0;
4851 String strAux = str;
4852 bool bSetBack = false;
4853 uint32 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
4854 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
4855 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4856 if (aux_index == -1 && ait->get_type () == SCIM_ATTR_DECORATE) {
4857 aux_index = ait->get_value ();
4858 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
4859 nForeGround = ait->get_value ();
4860 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
4861 nBackGround = ait->get_value ();
4866 std::vector<String> aux_list;
4867 scim_split_string_list (aux_list, strAux, '|');
4869 if (_aux_items.size () > 0) {
4870 for (i = 0; i < _aux_items.size (); i++)
4871 evas_object_del (_aux_items [i]);
4872 _aux_items.clear ();
4874 if (_aux_seperates.size () > 0) {
4875 for (i = 0; i < _aux_seperates.size (); i++)
4876 evas_object_del (_aux_seperates [i]);
4877 _aux_seperates.clear ();
4880 int seperate_width = 4;
4881 int seperate_height = 52 * _height_rate;
4882 Evas *evas = evas_object_evas_get (_candidate_window);
4883 for (i = 0; i < aux_list.size (); i++) {
4885 Evas_Object *seperate_item = edje_object_add (evas);
4886 edje_object_file_set (seperate_item, _candidate_edje_file.c_str (), "seperate_line");
4887 evas_object_size_hint_min_set (seperate_item, seperate_width, seperate_height);
4888 elm_table_pack (_aux_table, seperate_item, 2 * i - 1, 0, 1, 1);
4889 evas_object_show (seperate_item);
4890 _aux_seperates.push_back (seperate_item);
4894 aux_edje = edje_object_add (evas);
4895 edje_object_file_set (aux_edje, _candidate_edje_file.c_str (), "aux");
4896 edje_object_part_text_set (aux_edje, "aux", aux_list [i].c_str ());
4897 edje_object_text_class_set (aux_edje, "tizen", _candidate_font_name.c_str (), _aux_font_size);
4898 elm_table_pack (_aux_table, aux_edje, 2 * i, 0, 1, 1);
4899 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_AUX));
4900 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
4901 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_AUX));
4902 evas_object_show (aux_edje);
4903 _aux_items.push_back (aux_edje);
4904 /* if (i == (unsigned int)aux_index)
4905 edje_object_signal_emit (aux_edje, "aux,state,selected", "aux");
4907 edje_object_signal_emit (aux_edje, "aux,state,unselected", "aux");
4909 evas_object_text_text_set (_tmp_aux_text, aux_list [i].c_str ());
4910 evas_object_geometry_get (_tmp_aux_text, &x, &y, &width, &height);
4911 item_width = width + 2*_blank_width;
4912 item_width = item_width > _item_min_width ? item_width : _item_min_width;
4913 evas_object_size_hint_min_set (aux_edje, item_width, _aux_height);
4914 if (aux_index == (int)i || (aux_index == -1 && i == 0)) {
4915 aux_start = window_width;
4916 aux_end = window_width + item_width;
4918 window_width = window_width + item_width + 4;
4921 // Set highlight item
4922 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4923 if (ait->get_type () == SCIM_ATTR_DECORATE) {
4924 unsigned int index = ait->get_value ();
4925 if (index < _aux_items.size ())
4926 set_highlight_color (_aux_items [index], nForeGround, nBackGround, bSetBack);
4931 elm_scroller_region_get (_aux_area, &x, &y, &w, &h);
4932 item_width = aux_end - aux_start;
4933 if (item_width > 0) {
4934 if (item_width >= w)
4935 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4936 else if (aux_end > x + w)
4937 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4938 else if (aux_start < x)
4939 elm_scroller_region_show (_aux_area, aux_start, y, w, h);
4942 #endif /* CANDIDATE */
4945 #if ISF_BUILD_CANDIDATE_UI
4947 * @brief Update candidate/associate table.
4949 * @param table_type The table type.
4950 * @param table The lookup table for candidate or associate.
4952 static void update_table (int table_type, const LookupTable &table)
4954 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << table.get_current_page_size () << ")\n";
4956 int item_num = table.get_current_page_size ();
4963 AttributeList attrs;
4964 int i, x, y, item_0_width = 0;
4968 int seperate_width = 2;
4969 int seperate_height = 52 * _height_rate;
4970 int line_width = _candidate_scroll_width;
4971 int line_height = _v_padding;
4972 int total_width = 0;
4973 int current_width = 0;
4976 int more_item_count = 0;
4977 int scroll_0_width = _candidate_scroll_0_width_min;
4978 int cursor_pos = table.get_cursor_pos ();
4979 int cursor_line = 0;
4981 if (_candidate_angle == 90 || _candidate_angle == 270)
4982 scroll_0_width = _screen_height - _more_btn_width - _h_padding;
4984 scroll_0_width = _screen_width - _more_btn_width - _h_padding;
4986 _candidate_image_count = 0;
4987 _candidate_text_count = 0;
4988 _candidate_pop_image_count = 0;
4989 _candidate_display_number = 0;
4990 _candidate_row_items.clear ();
4992 Evas *evas = evas_object_evas_get (_candidate_window);
4993 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
4994 if (_candidate_0 [i]) {
4995 evas_object_del (_candidate_0 [i]);
4996 _candidate_0 [i] = NULL;
4998 if (_seperate_0 [i]) {
4999 evas_object_del (_seperate_0 [i]);
5000 _seperate_0 [i] = NULL;
5002 if (_seperate_items [i]) {
5003 evas_object_del (_seperate_items [i]);
5004 _seperate_items [i] = NULL;
5007 evas_object_del (_line_0 [i]);
5010 if (_line_items [i]) {
5011 evas_object_del (_line_items [i]);
5012 _line_items [i] = NULL;
5016 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
5018 bool bHighLight = false;
5019 bool bSetBack = false;
5020 uint32 nForeGround = SCIM_RGB_COLOR (249, 249, 249);
5021 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
5022 attrs = table.get_attributes_in_current_page (i);
5023 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5024 if (ait->get_type () == SCIM_ATTR_DECORATE && ait->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
5026 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
5027 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
5029 nForeGround = ait->get_value ();
5030 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
5032 nBackGround = ait->get_value ();
5036 wcs = table.get_candidate_in_current_page (i);
5037 mbs = utf8_wcstombs (wcs);
5039 if (!_candidate_0 [i] && total_width <= scroll_0_width) {
5040 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5041 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));
5042 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5043 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_0));
5045 /* Check whether this item is the last one */
5046 if (i == item_num - 1) {
5047 if (_candidate_angle == 90 || _candidate_angle == 270)
5048 scroll_0_width = _candidate_land_width;
5050 scroll_0_width = _candidate_port_width;
5053 /* Add first item */
5055 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5056 evas_object_show (_candidate_0 [i]);
5057 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5058 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, 0, item_0_width, _item_min_height);
5059 total_width += item_0_width;
5060 _candidate_display_number++;
5063 total_width += (item_0_width + seperate_width);
5064 if (total_width <= scroll_0_width) {
5065 _seperate_0 [i] = edje_object_add (evas);
5066 edje_object_file_set (_seperate_0 [i], _candidate_edje_file.c_str (), "seperate_line");
5067 evas_object_size_hint_min_set (_seperate_0 [i], seperate_width, seperate_height);
5068 elm_table_pack (_candidate_0_table, _seperate_0 [i],
5069 total_width - item_0_width - seperate_width,
5070 line_0*(_item_min_height+line_height) + (_item_min_height - seperate_height)/2,
5071 seperate_width, seperate_height);
5072 evas_object_show (_seperate_0 [i]);
5073 evas_object_show (_candidate_0 [i]);
5074 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5075 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);
5076 _candidate_display_number++;
5078 } else if ((_candidate_angle == 0 || _candidate_angle == 180) &&
5079 (_candidate_port_line > 1 && (line_0 + 1) < _candidate_port_line)) {
5081 scroll_0_width = _candidate_scroll_0_width_min;
5082 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5083 evas_object_show (_candidate_0 [i]);
5084 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5085 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
5086 total_width = item_0_width;
5087 _candidate_display_number++;
5089 _candidate_row_items.push_back (i - nLast);
5093 _candidate_row_items.push_back (i - nLast);
5099 if (!_candidate_0 [i]) {
5100 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5101 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));
5102 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5103 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_ITEMS));
5105 if (current_width > 0 && current_width + item_0_width > _candidate_scroll_width) {
5109 _candidate_row_items.push_back (i - nLast);
5111 if (cursor_pos >= i)
5114 if (current_width == 0 && !_line_items [i]) {
5115 _line_items [i] = edje_object_add (evas);
5116 edje_object_file_set (_line_items [i], _candidate_edje_file.c_str (), "popup_line");
5117 evas_object_size_hint_min_set (_line_items [i], line_width, line_height);
5119 y = line_count*(_item_min_height+line_height);
5120 elm_table_pack (_candidate_table, _line_items [i], x, y, line_width, line_height);
5121 evas_object_show (_line_items [i]);
5123 if (current_width != 0 && !_seperate_items [i]) {
5124 _seperate_items [i] = edje_object_add (evas);
5125 edje_object_file_set (_seperate_items [i], _candidate_edje_file.c_str (), "seperate_line");
5126 evas_object_size_hint_min_set (_seperate_items [i], seperate_width, seperate_height);
5128 y = line_count*(_item_min_height+line_height) + line_height + (_item_min_height - seperate_height)/2;
5129 elm_table_pack (_candidate_table, _seperate_items [i], x, y, seperate_width, seperate_height);
5130 evas_object_show (_seperate_items [i]);
5131 current_width += seperate_width;
5134 y = line_count*(_item_min_height+line_height) + line_height;
5135 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5136 evas_object_show (_candidate_0 [i]);
5137 elm_table_pack (_candidate_table, _candidate_0 [i], x, y, item_0_width, _item_min_height);
5138 current_width += item_0_width;
5140 if (candidate_expanded == false && !bHighLight)
5143 candidate_expanded = true;
5147 for (i = 1; i < _candidate_port_line; i++) {
5148 if ((_candidate_angle == 0 || _candidate_angle == 180)) {
5149 if (_line_0 [i] == NULL) {
5150 _line_0 [i] = edje_object_add (evas);
5151 edje_object_file_set (_line_0 [i], _candidate_edje_file.c_str (), "popup_line");
5152 evas_object_size_hint_min_set (_line_0 [i], line_width, line_height);
5154 y = i * (_item_min_height + line_height) - line_height;
5155 elm_table_pack (_candidate_0_table, _line_0 [i], x, y, line_width, line_height);
5156 evas_object_show (_line_0 [i]);
5159 // Create blank line
5160 if (line_0 + 1 < _candidate_port_line && i > line_0) {
5161 int nIndex = item_num + i;
5162 nIndex = nIndex < SCIM_LOOKUP_TABLE_MAX_PAGESIZE ? nIndex : SCIM_LOOKUP_TABLE_MAX_PAGESIZE - 1;
5163 _seperate_0 [nIndex] = edje_object_add (evas);
5164 edje_object_file_set (_seperate_0 [nIndex], _candidate_edje_file.c_str (), "seperate_line");
5165 evas_object_size_hint_min_set (_seperate_0 [nIndex], seperate_width, _item_min_height);
5166 elm_table_pack (_candidate_0_table, _seperate_0 [nIndex],
5167 0, i*(_item_min_height+line_height), seperate_width, _item_min_height);
5169 } else if (_line_0 [i]) {
5170 evas_object_del (_line_0 [i]);
5175 _candidate_row_items.push_back (item_num - nLast); /* Add the number of last row */
5176 _info_manager->update_displayed_candidate_number (_candidate_display_number);
5177 _info_manager->update_candidate_item_layout (_candidate_row_items);
5178 if (more_item_count == 0) {
5179 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
5180 evas_object_hide (_more_btn);
5181 evas_object_hide (_close_btn);
5182 } else if (!_candidate_area_2_visible) {
5183 evas_object_show (_more_btn);
5184 evas_object_hide (_close_btn);
5186 evas_object_hide (_more_btn);
5187 evas_object_show (_close_btn);
5191 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
5193 int line_h = _item_min_height + _v_padding;
5194 int cursor_y = cursor_line * line_h;
5196 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
5197 } else if (cursor_y >= y + h) {
5198 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
5203 #endif /* CANDIDATE */
5206 * @brief Update candidate table slot function for PanelAgent.
5208 * @param table The lookup table for candidate.
5210 static void slot_update_candidate_table (const LookupTable &table)
5212 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5214 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5215 _info_manager->update_helper_lookup_table (table);
5219 #if ISF_BUILD_CANDIDATE_UI
5220 if (_candidate_window == NULL)
5221 ui_create_candidate_window ();
5223 if (!_candidate_window || table.get_current_page_size () < 0)
5226 if (evas_object_visible_get (_candidate_area_2)) {
5227 candidate_expanded = true;
5229 candidate_expanded = false;
5232 update_table (ISF_CANDIDATE_TABLE, table);
5233 ui_tts_focus_rect_hide ();
5234 #endif /* CANDIDATE */
5238 * @brief Send selected candidate index.
5240 * @param selected candidate string index number.
5242 static void slot_select_candidate (int index)
5244 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5245 _info_manager->select_candidate (index);
5249 * @brief Get candidate geometry slot function for PanelAgent.
5251 * @param info The data is used to store candidate position and size.
5253 static void slot_get_candidate_geometry (struct rectinfo &info)
5260 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5264 info.height = height;
5268 #if ISF_BUILD_CANDIDATE_UI
5269 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5270 /* Get candidate window position */
5271 /*ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);*/
5272 /* Get exact candidate window size */
5274 evas_object_geometry_get (_candidate_window, &x2, &y2, &width, &height);*/
5278 width = _candidate_width;
5279 height = _candidate_height;
5281 #endif /* CANDIDATE */
5286 info.height = height;
5288 LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5289 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5290 << " width:" << info.width << " height:" << info.height << "\n";
5294 * @brief Get input panel geometry slot function for PanelAgent.
5296 * @param info The data is used to store input panel position and size.
5298 static void slot_get_input_panel_geometry (struct rectinfo &info)
5300 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
5305 #if ISF_BUILD_CANDIDATE_UI
5306 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5307 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5308 info.width = _candidate_width;
5309 info.height = _candidate_height;
5311 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5312 info.width = _soft_candidate_width;
5313 info.height = _soft_candidate_height;
5315 int angle = efl_get_app_window_angle ();
5316 if (angle == 90 || angle == 270)
5317 info.pos_y = _screen_width - info.height;
5319 info.pos_y = _screen_height - info.height;
5321 info = get_ise_geometry ();
5322 if (_ise_state != WINDOW_STATE_SHOW) {
5326 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5327 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5328 int height = ui_candidate_get_valid_height ();
5330 if ((_candidate_height - height) > _ise_height) {
5331 info.pos_y = info.pos_y + info.height - _candidate_height;
5332 info.height = _candidate_height;
5334 info.pos_y -= height;
5335 info.height += height;
5340 #endif /* CANDIDATE */
5343 LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5344 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5345 << " width:" << info.width << " height:" << info.height << "\n";
5349 * @brief Get the recent input panel geometry slot function for PanelAgent.
5351 * @param angle the rotation angle of application window.
5352 * @param info The data is used to store input panel position and size.
5354 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info)
5356 LOGD ("slot_get_recent_ise_geometry");
5358 /* If we have geometry reported by ISE, use the geometry information */
5363 if (angle == 0 || angle == 180) {
5364 if (_portrait_recent_ise_geometry.valid) {
5365 info = _portrait_recent_ise_geometry.geometry;
5370 if (_landscape_recent_ise_geometry.valid) {
5371 info = _landscape_recent_ise_geometry.geometry;
5382 static bool slot_check_privilege_by_sockfd (int client_id, String privilege)
5384 PrivilegeChecker privilegeChecker (client_id);
5386 bool priv_ret = privilegeChecker.checkPrivilege (privilege.c_str ());
5388 if (priv_ret == false)
5389 LOGW ("Failed to check privilege (%s)", privilege.c_str ());
5391 LOGD ("Succeeded to check privilege (%s)", privilege.c_str ());
5397 * @brief Set active ISE slot function for PanelAgent.
5399 * @param uuid The active ISE's uuid.
5400 * @param changeDefault The flag for changing default ISE.
5402 static void slot_set_active_ise (const String &uuid, bool changeDefault)
5404 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << uuid << ")\n";
5406 bool invalid = false;
5408 #ifdef HAVE_PKGMGR_INFO
5409 /* When changing the active (default) keyboard, initialize ime_info DB if appid is invalid.
5410 This may be necessary if IME packages are changed while panel process is terminated. */
5411 pkgmgrinfo_appinfo_h handle = NULL;
5412 /* Try to get in global packages */
5413 int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
5414 if (ret != PMINFO_R_OK) {
5415 LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
5416 /* This might happen if IME is uninstalled while the panel process is inactive.
5417 The variable uuid would be invalid, so set_active_ise() would return false. */
5422 pkgmgrinfo_appinfo_destroy_appinfo (handle);
5426 _initialize_ime_info ();
5427 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5429 else if (set_active_ise (uuid, _soft_keyboard_launched) == false) {
5430 if (_initial_ise_uuid.compare (uuid))
5431 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5436 * @brief Get all ISEs list slot function for PanelAgent.
5438 * @param list The list is used to store all ISEs.
5440 * @return true if this operation is successful, otherwise return false.
5442 static bool slot_get_ise_list (std::vector<String> &list)
5444 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5446 bool result = false;
5448 std::vector<String> uuids;
5449 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5450 uuids.push_back(iter->appid);
5452 if (_ime_info.size () > 0) {
5457 result = update_ise_list (list);
5464 * @brief Get all Helper ISE information from ime_info DB.
5466 * @param info This is used to store all Helper ISE information.
5468 * @return true if this operation is successful, otherwise return false.
5470 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info)
5472 bool result = false;
5473 String active_ime_appid;
5475 info.appid.clear ();
5476 info.label.clear ();
5477 info.is_enabled.clear ();
5478 info.is_preinstalled.clear ();
5479 info.has_option.clear ();
5481 if (_ime_info.size() == 0)
5482 isf_pkg_select_all_ime_info_db (_ime_info);
5484 //active_ime_appid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5485 if (_info_manager) {
5486 active_ime_appid = _info_manager->get_current_helper_uuid ();
5489 if (_ime_info.size () > 0) {
5490 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
5491 if (iter->mode == TOOLBAR_HELPER_MODE) {
5492 info.appid.push_back (iter->appid);
5493 info.label.push_back (iter->label);
5494 info.is_enabled.push_back (iter->is_enabled);
5495 info.is_preinstalled.push_back (iter->is_preinstalled);
5496 info.has_option.push_back (static_cast<uint32>(iter->has_option));
5506 * @brief Update "has_option" column of ime_info DB by Application ID
5508 * @param[in] appid Application ID of IME to enable or disable
5509 * @param[in] has_option @c true to have IME option(setting), otherwise @c false
5511 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option)
5513 if (appid.length() == 0) {
5514 LOGW ("Invalid appid");
5518 if (_ime_info.size() == 0)
5519 isf_pkg_select_all_ime_info_db(_ime_info);
5521 if (isf_db_update_has_option_by_appid(appid.c_str(), has_option)) { // Update ime_info DB
5522 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5523 if (appid == _ime_info[i].appid) {
5524 _ime_info[i].has_option = static_cast<uint32>(has_option); // Update global variable
5531 * @brief Update "is_enable" column of ime_info DB by Application ID
5533 * @param[in] appid Application ID of IME to enable or disable
5534 * @param[in] is_enabled @c true to enable the IME, otherwise @c false
5536 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled)
5538 if (appid.length() == 0) {
5539 LOGW ("Invalid appid");
5543 if (_ime_info.size() == 0)
5544 isf_pkg_select_all_ime_info_db(_ime_info);
5546 if (isf_db_update_is_enabled_by_appid(appid.c_str(), is_enabled)) { // Update ime_info DB
5547 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5548 if (appid == _ime_info[i].appid) {
5549 _ime_info[i].is_enabled = static_cast<uint32>(is_enabled); // Update global variable
5555 #ifdef HAVE_PKGMGR_INFO
5557 * @brief Finds appid with specific category
5559 * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative
5561 static int _find_appid_from_category (const pkgmgrinfo_appinfo_h handle, void *user_data)
5564 char **result = static_cast<char **>(user_data);
5569 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
5570 if (ret == PMINFO_R_OK) {
5571 *result = strdup (appid);
5574 LOGW ("pkgmgrinfo_appinfo_get_appid failed!");
5578 LOGW ("user_data is null!");
5581 return -1; // This callback is no longer called.
5586 * @brief Requests to open the installed IME list application.
5588 static void slot_show_helper_ise_list (void)
5590 // Launch IME List application; e.g., org.tizen.inputmethod-setting-list
5591 char *app_id = NULL;
5592 #ifdef HAVE_PKGMGR_INFO
5593 pkgmgrinfo_appinfo_filter_h handle;
5596 if (ime_list_app.length() < 1) {
5597 ret = pkgmgrinfo_appinfo_filter_create (&handle);
5598 if (ret == PMINFO_R_OK) {
5599 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-list");
5600 if (ret == PMINFO_R_OK) {
5601 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
5603 pkgmgrinfo_appinfo_filter_destroy (handle);
5606 ime_list_app = String (app_id);
5610 app_id = strdup (ime_list_app.c_str());
5614 app_control_launch (app_id);
5618 SECURE_LOGW ("AppID with http://tizen.org/category/ime-list category is not available.");
5623 * @brief Requests to open the installed IME selector application.
5625 static void slot_show_helper_ise_selector (void)
5627 // Launch IME Selector application; e.g., org.tizen.inputmethod-setting-selector
5628 char *app_id = NULL;
5629 #ifdef HAVE_PKGMGR_INFO
5630 pkgmgrinfo_appinfo_filter_h handle;
5633 if (ime_selector_app.length() < 1) {
5634 ret = pkgmgrinfo_appinfo_filter_create(&handle);
5635 if (ret == PMINFO_R_OK) {
5636 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
5637 if (ret == PMINFO_R_OK) {
5638 pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, _find_appid_from_category, &app_id);
5640 pkgmgrinfo_appinfo_filter_destroy(handle);
5643 ime_selector_app = String(app_id);
5647 app_id = strdup(ime_selector_app.c_str());
5651 app_control_launch (app_id);
5655 SECURE_LOGW ("AppID with http://tizen.org/category/ime-selector category is not available.");
5659 static bool slot_is_helper_ise_enabled (String appid, int &enabled)
5661 bool is_enabled = false;
5663 if (appid.length() == 0) {
5664 LOGW ("Invalid appid.");
5668 if (_ime_info.size() == 0)
5669 isf_pkg_select_all_ime_info_db(_ime_info);
5671 if (isf_db_select_is_enabled_by_appid(appid.c_str(), &is_enabled)) {
5672 enabled = static_cast<int>(is_enabled);
5681 * @brief Get the ISE's information.
5683 * @param uuid The ISE's uuid.
5684 * @param name The ISE's name.
5685 * @param language The ISE's language.
5686 * @param type The ISE's type.
5687 * @param option The ISE's option.
5689 * @return true if this operation is successful, otherwise return false.
5691 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name)
5693 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5695 if (uuid.length () > 0) {
5696 // update all ISE names according to the display languages
5697 // sometimes get_ise_information is called before vconf display language changed callback is called.
5698 update_ise_locale ();
5700 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5701 if (uuid == _ime_info[i].appid) {
5702 name = _ime_info[i].label;
5703 language = _ime_info[i].languages;
5704 type = _ime_info[i].mode;
5705 option = _ime_info[i].options;
5706 module_name = _ime_info[i].module_name;
5712 std::cerr << __func__ << " is failed!!!\n";
5717 * @brief Get keyboard ISEs list slot function for PanelAgent.
5719 * @param name_list The list is used to store keyboard ISEs.
5721 * @return true if this operation is successful, otherwise return false.
5723 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list)
5725 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5727 isf_load_ise_information (ALL_ISE, _config);
5729 std::vector<String> lang_list, uuid_list;
5730 isf_get_all_languages (lang_list);
5731 isf_get_keyboard_ises_in_languages (lang_list, uuid_list, name_list, false);
5733 _info_manager->update_ise_list (uuid_list);
5738 * @brief Get enable languages list slot function for PanelAgent.
5740 * @param list The list is used to store languages.
5742 static void slot_get_language_list (std::vector<String> &list)
5744 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5747 MapStringVectorSizeT::iterator iter = _groups.begin ();
5749 for (; iter != _groups.end (); iter++) {
5750 lang_name = scim_get_language_name (iter->first);
5751 list.push_back (lang_name);
5756 * @brief Get all languages list slot function for PanelAgent.
5758 * @param lang The list is used to store languages.
5760 static void slot_get_all_language (std::vector<String> &lang)
5762 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5764 isf_get_all_languages (lang);
5768 * @brief Get specific ISE language list slot function for PanelAgent.
5770 * @param name The ISE name.
5771 * @param list The list is used to store ISE languages.
5773 static void slot_get_ise_language (char *name, std::vector<String> &list)
5775 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5780 std::vector<String> list_tmp;
5782 for (unsigned int i = 0; i < _ime_info.size(); i++) {
5783 if (!strcmp (_ime_info[i].label.c_str (), name)) {
5784 scim_split_string_list (list_tmp, _ime_info[i].languages, ',');
5785 for (i = 0; i < list_tmp.size (); i++)
5786 list.push_back (scim_get_language_name (list_tmp[i]));
5793 * @brief Get ISE information slot function for PanelAgent.
5795 * @param uuid The ISE uuid.
5796 * @param info The variable is used to store ISE information.
5798 * @return true if this operation is successful, otherwise return false.
5800 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info)
5802 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5804 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5805 if (!uuid.compare (_ime_info[i].appid)) {
5806 info.uuid = _ime_info[i].appid;
5807 info.name = _ime_info[i].label;
5808 info.icon = _ime_info[i].iconpath;
5809 info.lang = _ime_info[i].languages;
5810 info.option = _ime_info[i].options;
5811 info.type = _ime_info[i].mode;
5820 * @brief Set keyboard ISE slot function for PanelAgent.
5822 * @param uuid The variable is ISE uuid.
5824 static void slot_set_keyboard_ise (const String &uuid)
5826 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << uuid << "\n";
5828 std::vector<String> uuids;
5829 std::vector<ImeInfoDB>::iterator iter;
5830 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5831 uuids.push_back(iter->appid);
5834 if (uuid.length () <= 0 || std::find (uuids.begin (), uuids.end (), uuid) == uuids.end ())
5837 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5838 if (_ime_info[get_ise_index (default_uuid)].mode == TOOLBAR_KEYBOARD_MODE)
5841 uint32 ise_option = 0;
5842 String ise_uuid, ise_name;
5843 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5844 if (ise_uuid == uuid)
5847 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
5848 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
5852 _info_manager->change_factory (uuid);
5856 * @brief Get current keyboard ISE name and uuid slot function for PanelAgent.
5858 * @param ise_name The variable is used to store ISE name.
5859 * @param ise_uuid The variable is used to store ISE uuid.
5861 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid)
5863 uint32 ise_option = 0;
5864 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5866 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << ise_uuid << "\n";
5870 * @brief Accept connection slot function for PanelAgent.
5872 * @param fd The file descriptor to connect.
5874 static void slot_accept_connection (int fd)
5876 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5879 get_input_window ();
5884 * @brief Close connection slot function for PanelAgent.
5886 * @param fd The file descriptor to connect.
5888 static void slot_close_connection (int fd)
5890 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5894 * @brief Exit panel process slot function for PanelAgent.
5896 static void slot_exit (void)
5898 std::cerr << __FUNCTION__ << "...\n";
5899 ISF_SAVE_LOG ("exit");
5901 #if ISF_BUILD_CANDIDATE_UI
5904 ecore_main_loop_quit ();
5905 #endif /* CANDIDATE */
5908 static void delete_ise_check_pid_alive_timer(void)
5910 LOGD("deleting ise_check_alive_timer");
5911 if (_ise_check_pid_alive_timer) {
5912 ecore_timer_del(_ise_check_pid_alive_timer);
5913 _ise_check_pid_alive_timer = NULL;
5917 static Eina_Bool ise_check_pid_alive_timer(void *data)
5919 Eina_Bool ret = ECORE_CALLBACK_RENEW;
5920 Eina_Bool retry = EINA_FALSE;
5922 int status = aul_app_get_status (_ise_check_pid_alive_uuid.c_str ());
5923 LOGD ("STATUS : %d", status);
5924 if (status >= STATUS_LAUNCHING) {
5925 /* If the status is not one of STATUS_LAUNCHING, STATUS_VISIBLE, STATUS_BG */
5926 if (status >= STATUS_DYING) {
5927 LOGE ("aul_app_get_status reports %d", status);
5932 /* Status query not successful, the ISE could have failed launching */
5933 LOGE ("aul_app_get_status failed. %d", status);
5938 _soft_keyboard_launched = false;
5939 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
5940 /* The start_helper() function below will going to call slot_run_helper,
5941 which will going to assign a new timer handle to the _ise_check_pid_alive_timer variable.
5943 LOGW ("The previous attempt to launch %s seems to be failed, restarting",
5944 _ise_check_pid_alive_uuid.c_str ());
5945 if (_info_manager->start_helper (uuid))
5946 _soft_keyboard_launched = true;
5947 ret = ECORE_CALLBACK_CANCEL;
5953 static void slot_register_helper(int id, const HelperInfo& info)
5955 LOGD ("app id : %s", info.uuid.c_str ());
5956 /* Do we need to check whether the pid of this helper is the one we are watching? */
5957 if (info.uuid.compare(_ise_check_pid_alive_uuid) == 0) {
5958 delete_ise_check_pid_alive_timer();
5962 static void slot_register_helper_properties (int id, const PropertyList &props)
5964 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5966 /* WMSYNC, #2 Receiving X window ID from ISE */
5967 /* FIXME : We should add an API to set window id of ISE */
5968 Property prop = props[0];
5969 if (prop.get_label ().compare ("XID") == 0) {
5970 Ecore_X_Window xwindow = atoi (prop.get_key ().c_str ());
5971 _ise_window = xwindow;
5972 LOGD ("ISE XID : %x", _ise_window);
5974 /* Just in case for the helper sent this message later than show_ise request */
5975 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
5976 efl_set_transient_for_app_window (_ise_window);
5979 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_ISE_WINDOW");
5980 if (atom && _control_window && _ise_window) {
5981 ecore_x_window_prop_xid_set (_control_window, atom, ECORE_X_ATOM_WINDOW, &_ise_window, 1);
5983 #ifdef HAVE_NOTIFICATION
5984 delete_notification (&ise_selector_module_noti);
5990 #if ENABLE_REMOTE_INPUT
5991 static void slot_send_remote_input_message (const String &msg, bool len)
5993 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5995 String con = msg.c_str ();
5996 ISE_MESSAGE message = CISEMessageSerializer::deserialize(con);
5998 if (remote_input_impl == NULL) {
5999 remote_input_impl = Remote_Input::get_instance();
6002 if (remote_input_impl)
6003 remote_input_impl->handle_websocket_message(message);
6006 static void slot_recv_remote_surrounding_text (int cursor, const String &text)
6008 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6010 if (remote_input_impl == NULL) {
6011 remote_input_impl = Remote_Input::get_instance();
6014 if (remote_input_impl)
6015 remote_input_impl->handle_recv_panel_message(3, text.c_str (), cursor);
6019 static void slot_show_ise (void)
6021 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6023 /* If the current toolbar mode is not HELPER_MODE, do not proceed */
6024 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
6025 LOGD ("Current toolbar mode should be TOOLBAR_HELPER_MODE but is %d, returning",
6026 _info_manager->get_current_toolbar_mode ());
6030 LOGD ("slot_show_ise ()");
6032 delete_ise_hide_timer ();
6034 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
6035 // Unset conformant area
6036 Ecore_X_Window current_app_window = efl_get_app_window ();
6037 if (_app_window != current_app_window) {
6038 struct rectinfo info = {0, 0, 0, 0};
6039 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
6040 set_keyboard_geometry_atom_info (_app_window, info);
6041 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6042 LOGD ("Conformant reset for window %x", _app_window);
6043 _app_window = current_app_window;
6045 /* If the target window has changed but our ISE is still in visible state,
6046 update the keyboard geometry information */
6047 if (_ise_state == WINDOW_STATE_SHOW) {
6048 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6052 /* If the candidate was already in SHOW state, respect the current angle */
6053 if (_candidate_state != WINDOW_STATE_SHOW) {
6054 /* FIXME : Need to check if candidate_angle and window_angle should be left as separated */
6055 _candidate_angle = efl_get_app_window_angle ();
6057 /* If the ise was already in SHOW state, respect the current angle */
6058 if (_ise_state != WINDOW_STATE_SHOW) {
6059 _ise_angle = efl_get_app_window_angle ();
6062 ecore_x_event_mask_set (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6063 efl_set_transient_for_app_window (_ise_window);
6065 /* Make clipboard window to have transient_for information on ISE window,
6066 so that the clipboard window will always be above ISE window */
6067 Ecore_X_Window clipboard_window = efl_get_clipboard_window ();
6068 if (_ise_window && clipboard_window) {
6069 ecore_x_icccm_transient_for_set (clipboard_window, _ise_window);
6072 /* If our ISE was already in SHOW state, skip state transition to WILL_SHOW */
6073 if (_ise_state != WINDOW_STATE_SHOW) {
6074 _ise_state = WINDOW_STATE_WILL_SHOW;
6078 #if ISF_BUILD_CANDIDATE_UI
6079 _candidate_angle = 0;
6080 #endif /* CANDIDATE */
6081 _ise_state = WINDOW_STATE_SHOW;
6083 #ifdef HAVE_NOTIFICATION
6084 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6085 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6086 show_ime_selector_notification ();
6093 static void slot_hide_ise (void)
6095 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6097 LOGD ("slot_hide_ise ()");
6099 if (!_ise_hide_timer)
6103 static void slot_will_hide_ack (void)
6105 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6107 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
6108 // WILL_HIDE_REQUEST_DONE Ack to WM
6109 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6110 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
6111 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
6112 root_window, _control_window);
6113 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6114 LOGD ("calling ui_candidate_hide (true, false)");
6115 ui_candidate_hide (true, false);
6118 /* WILL_HIDE_ACK means that the application finished redrawing the autoscroll area,
6119 now hide the candidate window right away if it is also in WILL_HIDE state */
6120 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6121 candidate_window_hide ();
6124 if (_off_prepare_done_timer) {
6125 ecore_timer_del (_off_prepare_done_timer);
6126 _off_prepare_done_timer = NULL;
6131 static void slot_candidate_will_hide_ack (void)
6133 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6135 LOGD ("candidate_will_hide_ack");
6136 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6137 candidate_window_hide ();
6142 static void slot_set_keyboard_mode (int mode)
6144 LOGD ("slot_set_keyboard_mode called (TOOLBAR_MODE : %d)", mode);
6146 change_keyboard_mode ((TOOLBAR_MODE_T)mode);
6149 static void slot_get_ise_state (int &state)
6151 if (_ise_state == WINDOW_STATE_SHOW ||
6152 ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (_candidate_state == WINDOW_STATE_SHOW))) {
6153 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6155 /* Currently we don't have WILL_HIDE / HIDE state distinction in Ecore_IMF */
6156 switch (_ise_state) {
6157 case WINDOW_STATE_SHOW :
6158 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6160 case WINDOW_STATE_WILL_SHOW :
6161 state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
6163 case WINDOW_STATE_WILL_HIDE :
6164 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6166 case WINDOW_STATE_HIDE :
6167 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6170 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6173 LOGD ("state = %d", state);
6174 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " state = " << state << "\n";
6177 static void slot_start_default_ise (void)
6179 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6181 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE)) {
6182 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6183 int pid = aul_app_get_pid (uuid.c_str ());
6185 if (STATUS_DYING == aul_app_get_status (uuid.c_str ()))
6188 if ((_launch_ise_on_request || !_enable_auto_restart) && !_soft_keyboard_launched && pid < 0) {
6189 LOGD ("Start helper (%s)", uuid.c_str ());
6190 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
6192 if (_info_manager->start_helper (uuid))
6193 _soft_keyboard_launched = true;
6195 LOGW ("Failed to start helper (%s)", uuid.c_str ());
6200 static void slot_stop_default_ise (bool is_exist)
6202 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6205 if (_launch_ise_on_request && _auto_destroy_ise && _soft_keyboard_launched) {
6206 String uuid = _info_manager->get_current_helper_uuid ();
6208 if (uuid.length () > 0) {
6209 _info_manager->hide_helper (uuid);
6210 _info_manager->stop_helper (uuid);
6211 _soft_keyboard_launched = false;
6212 LOGD ("stop helper (%s)", uuid.c_str ());
6216 if (_soft_keyboard_launched)
6217 _soft_keyboard_launched = false;
6221 static void launch_helper (const char* exec, const char *name, const char *appid, const char *config, const char *display)
6227 if (pid < 0) return;
6230 const char *argv [] = { exec,
6233 "--display", display,
6234 const_cast<char*> (name),
6235 const_cast<char*> (appid),
6238 SCIM_DEBUG_MAIN (2) << " Call scim-helper-launcher.\n";
6239 ISF_SAVE_LOG ("Exec scim_helper_launcher(%s %s)", name, appid);
6241 unsetenv ("ELM_THEME");
6242 unsetenv ("ELM_SCALE");
6245 LOGD ("launch execpath : %s", exec);
6246 execv (exec, const_cast<char **>(argv));
6247 #if ISF_BUILD_CANDIDATE_UI
6250 ecore_main_loop_quit ();
6251 #endif /* CANDIDATE */
6255 static bool app_control_launch (const char *app_id)
6257 app_control_h app_control;
6260 ret = app_control_create (&app_control);
6261 if (ret != APP_CONTROL_ERROR_NONE) {
6262 LOGW ("app_control_create returned %08x", ret);
6266 ret = app_control_set_operation (app_control, APP_CONTROL_OPERATION_DEFAULT);
6267 if (ret != APP_CONTROL_ERROR_NONE) {
6268 LOGW ("app_control_set_operation returned %08x", ret);
6269 app_control_destroy (app_control);
6273 ret = app_control_set_app_id (app_control, app_id);
6274 if (ret != APP_CONTROL_ERROR_NONE) {
6275 LOGW ("app_control_set_app_id returned %08x", ret);
6276 app_control_destroy (app_control);
6281 ret = app_control_add_extra_data(app_control, "__K_EX_FORCE_BOOST", "enable");
6282 if (ret != APP_CONTROL_ERROR_NONE) {
6283 LOGW ("app_control_add_extra_data returned %08x", ret);
6289 if (tries != 0) usleep(1000000); /* If we are retrying to launch, pause for a while */
6290 ret = app_control_send_launch_request(app_control, NULL, NULL);
6291 LOGW ("app_control_send_launch_request returned %08x, app_id=%s", ret, app_id);
6292 } while (ret != APP_CONTROL_ERROR_NONE && (++tries) < 3);
6294 app_control_destroy (app_control);
6296 if (ret != APP_CONTROL_ERROR_NONE) {
6297 LOGW ("Failed to launch IME. appid(%s). reason(%s)", app_id, get_error_message(ret));
6299 LOGD ("Succeeded to launch IME. appid(%s)", app_id);
6302 return (ret == APP_CONTROL_ERROR_NONE);
6305 static void add_ise_check_pid_alive_timer(const String &uuid) {
6306 delete_ise_check_pid_alive_timer ();
6307 LOGD ("Register check_alive timer for uuid : %s", uuid.c_str ());
6308 _ise_check_pid_alive_uuid = uuid;
6309 _ise_check_pid_alive_timer = ecore_timer_add (_ise_check_pid_alive_time,
6310 ise_check_pid_alive_timer, NULL);
6313 static void terminate_active_ise (const String uuid)
6315 /* Check if IME with the same AppID is alive */
6316 int status_ret = aul_app_get_status (uuid.c_str ());
6317 if (status_ret >= STATUS_LAUNCHING) {
6318 /* Request to terminate IME */
6319 int ime_pid = aul_app_get_pid (uuid.c_str ());
6320 status_ret = aul_terminate_pid (ime_pid);
6321 if (status_ret < AUL_R_OK) {
6322 LOGE ("aul_terminate_pid(%d) failed: %d", ime_pid, status_ret);
6325 LOGD ("Requested to terminate IME(%s)", uuid.c_str ());
6331 static void set_cpu_boosting ()
6333 resource_pid_t resource_st;
6334 resource_st.pid = getpid();
6335 int ret = resource_set_cpu_boosting(resource_st, CPU_BOOSTING_LEVEL_STRONG, CPU_BOOSTING_RESET_ON_FORK, -1);
6337 LOGE("Failed to set cpu boosting");
6340 static void clear_cpu_boosting ()
6342 resource_pid_t resource_st;
6343 resource_st.pid = getpid();
6344 int ret = resource_clear_cpu_boosting(resource_st);
6346 LOGE("Failed to clear cpu boosting");
6349 static void slot_run_helper (const String &uuid, const String &config, const String &display)
6351 ISF_SAVE_LOG ("time:%ld pid:%d %s %s uuid(%s)",
6352 time (0), getpid (), __FILE__, __func__, uuid.c_str ());
6354 String scim_helper_path;
6356 delete_ise_check_pid_alive_timer ();
6358 #ifdef HAVE_PKGMGR_INFO
6359 char *execpath = NULL;
6361 pkgmgrinfo_appinfo_h appinfo_handle;
6363 /* get app info handle */
6364 /* Try to get in global packages */
6365 ret = pkgmgr_get_appinfo (uuid.c_str (), &appinfo_handle);
6366 if (ret != PMINFO_R_OK) {
6367 LOGE ("pkgmgr_get_appinfo failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6368 add_ise_check_pid_alive_timer (uuid);
6373 ret = pkgmgrinfo_appinfo_get_exec (appinfo_handle, &execpath);
6374 if (ret != PMINFO_R_OK) {
6375 LOGE ("pkgmgrinfo_appinfo_get_exec failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6376 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6377 add_ise_check_pid_alive_timer (uuid);
6381 LOGD ("exec path : %s %zu", execpath, _ime_info.size ());
6382 scim_helper_path = String (execpath);
6384 if (appinfo_handle) {
6385 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6386 appinfo_handle = NULL;
6389 scim_helper_path = String (SCIM_HELPER_LAUNCHER_PROGRAM);
6392 for (size_t i = 0; i < _ime_info.size (); ++i) {
6393 if (_ime_info[i].appid == uuid && _ime_info[i].module_name.length ()) {
6394 if (scim_helper_path != String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
6395 terminate_active_ise (uuid);
6396 /* execute type IME */
6397 LOGD ("Try to launch IME (%s)", uuid.c_str ());
6398 app_control_launch (uuid.c_str ());
6400 /* ISE check alive only works for AUL based IMEs */
6401 add_ise_check_pid_alive_timer (uuid);
6404 /* shared object (so) type IME */
6405 launch_helper (scim_helper_path.c_str(), _ime_info[i].module_name.c_str (), uuid.c_str (), config.c_str (), display.c_str ());
6408 _soft_keyboard_launched = true;
6413 SCIM_DEBUG_MAIN (2) << " exit run_helper ().\n";
6416 static bool slot_launch_option_application (String ime_appid)
6418 String ime_setting_app = isf_pkg_get_setting_app (ime_appid);
6420 LOGD ("IME appid(%s), IME setting app id(%s)", ime_appid.c_str (), ime_setting_app.c_str ());
6422 if (ime_setting_app.length () > 0) {
6423 app_control_launch (ime_setting_app.c_str ());
6430 static bool slot_get_ise_setting_appid (String ime_appid, String &ime_setting_appid)
6432 ime_setting_appid = isf_pkg_get_setting_app (ime_appid);
6434 LOGD ("IME appid : %s, IME setting app ID : %s", ime_appid.c_str(), ime_setting_appid.c_str());
6435 return ime_setting_appid.length () > 0 ? true : false;
6438 //////////////////////////////////////////////////////////////////////
6439 // End of PanelAgent-Functions
6440 //////////////////////////////////////////////////////////////////////
6444 * @brief Callback function for abnormal signal.
6446 * @param sig The signal.
6448 static void signalhandler (int sig)
6450 std::cerr << __FUNCTION__ << " Signal=" << sig << "\n";
6451 ISF_SAVE_LOG ("Signal=%d", sig);
6453 #if ISF_BUILD_CANDIDATE_UI
6456 ecore_main_loop_quit ();
6457 #endif /* CANDIDATE */
6461 static void update_ise_locale (const char *language)
6466 strLang = String (language);
6469 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
6471 if (_locale_string.compare(lang_str) == 0) {
6476 strLang = String (lang_str);
6482 LOGD ("update all ISE names according to display language : %s", strLang.c_str ());
6483 set_language_and_locale (strLang.c_str ());
6485 bool need_to_init_db = false;
6486 #ifdef HAVE_PKGMGR_INFO
6490 pkgmgrinfo_appinfo_h handle = NULL;
6492 /* Read DB from ime_info table */
6493 isf_load_ise_information(ALL_ISE, _config);
6495 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6496 ret = pkgmgr_get_appinfo (_ime_info[i].appid.c_str(), &handle);
6498 if (ret == PMINFO_R_OK) {
6499 ret = pkgmgrinfo_appinfo_is_category_exist(handle, "http://tizen.org/category/ime", &exist);
6500 if (ret == PMINFO_R_OK && exist) {
6501 ret = pkgmgrinfo_appinfo_get_label(handle, &label);
6502 if (ret == PMINFO_R_OK && label) {
6503 _ime_info[i].label = String(label);
6504 /* Update label column in ime_info db table */
6505 if (isf_db_update_label_by_appid(_ime_info[i].appid.c_str(), label)) {
6506 _ime_info[i].label = label;
6511 // The appid is invalid.. Need to initialize ime_info DB.
6512 need_to_init_db = true;
6514 pkgmgrinfo_appinfo_destroy_appinfo(handle);
6517 // The appid is invalid.. Need to initialize ime_info DB.
6518 need_to_init_db = true;
6523 if (need_to_init_db) {
6524 _initialize_ime_info ();
6527 if (strLang.length () > 0) {
6528 isf_db_update_disp_lang (strLang.c_str ());
6529 _locale_string = strLang;
6534 * @brief Set language and locale.
6538 static void set_language_and_locale (const char *lang_str)
6540 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6545 LOGD ("language : %s", lang_str);
6546 #if ISF_BUILD_CANDIDATE_UI
6547 elm_language_set (lang_str);
6548 #endif /* CANDIDATE */
6550 snprintf (language, sizeof (language), "%s:en_US:en_GB:en", lang_str);
6551 setenv ("LANGUAGE", language, 1);
6552 setenv ("LANG", lang_str, 1);
6553 setlocale (LC_MESSAGES, lang_str);
6555 setenv ("LANG", "en_US.utf8", 1);
6556 setlocale (LC_MESSAGES, "en_US.utf8");
6561 * @brief Callback function for display language change.
6563 * @param key The key node.
6564 * @param data The data to pass to this callback.
6568 static void display_language_changed_cb (keynode_t *key, void* data)
6570 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6572 char *lang_str = vconf_keynode_get_str (key);
6573 LOGD ("lang : %s", lang_str);
6574 set_language_and_locale (lang_str);
6576 /* Update all ISE names according to display language */
6577 update_ise_locale ();
6579 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
6580 unsigned int ise_idx = get_ise_index (default_uuid);
6582 if (ise_idx < _ime_info.size ()) {
6583 String default_name = _ime_info[ise_idx].label;
6584 _info_manager->set_current_ise_name (default_name);
6590 * @brief Callback function for keyboard mode change.
6592 * @param key The key node.
6593 * @param data The data to pass to this callback.
6597 static void keyboard_mode_changed_cb (keynode_t *key, void* data)
6599 bool val = vconf_keynode_get_bool (key);
6602 _info_manager->reset_keyboard_ise ();
6603 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6604 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6609 static void set_hw_keyboard_input_detect_flag(bool flag)
6612 int input_detect = false;
6614 if (vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect) == 0) {
6615 if (input_detect != flag) {
6616 if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, flag) != 0)
6617 LOGW ("Failed to set vconf key");
6619 LOGD ("Succeeded to set vconf key");
6626 * @brief Change keyboard mode.
6628 * @param mode The keyboard mode.
6632 static void change_keyboard_mode (TOOLBAR_MODE_T mode)
6634 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6637 bool _support_hw_keyboard_mode = false;
6639 unsigned int val = 0;
6642 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6643 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6644 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
6646 if (mode == TOOLBAR_KEYBOARD_MODE && _support_hw_keyboard_mode) {
6647 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6648 LOGD ("HARDWARE_KEYBOARD_MODE return");
6652 LOGD ("HARDWARE KEYBOARD MODE");
6653 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 1);
6656 if (_ime_info[get_ise_index(default_uuid)].mode == TOOLBAR_HELPER_MODE) {
6657 /* Get the keyboard ISE */
6658 isf_get_keyboard_ise (_config, uuid, name, option);
6659 if (option & SCIM_IME_NOT_SUPPORT_HARDWARE_KEYBOARD) {
6660 uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
6661 std::cerr << __FUNCTION__ << ": Keyboard ISE (" << name << ") can not support hardware keyboard!!!\n";
6663 /* Try to find reasonable keyboard ISE according to helper ISE language */
6664 if (uuid == String (SCIM_COMPOSE_KEY_FACTORY_UUID)) {
6665 String helper_language = _ime_info[get_ise_index(default_uuid)].languages;
6666 if (helper_language.length () > 0) {
6667 std::vector<String> ise_langs;
6668 scim_split_string_list (ise_langs, helper_language);
6669 for (size_t i = 0; i < _groups[ise_langs[0]].size (); ++i) {
6670 int j = _groups[ise_langs[0]][i];
6671 if (_ime_info[j].appid != uuid && _ime_info[j].mode == TOOLBAR_KEYBOARD_MODE) {
6672 uuid = _ime_info[j].appid;
6680 uuid = default_uuid;
6682 #if ISF_BUILD_CANDIDATE_UI
6683 _soft_candidate_width = 0;
6684 _soft_candidate_height = 0;
6685 #endif /* CANDIDATE */
6686 _ise_state = WINDOW_STATE_HIDE;
6687 _info_manager->set_current_toolbar_mode (TOOLBAR_KEYBOARD_MODE);
6688 _info_manager->hide_helper (helper_uuid);
6690 /* Check whether stop soft keyboard */
6691 if (_focus_in && (_ime_info[get_ise_index (helper_uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
6692 /* If focus in and soft keyboard can support hardware key event, then don't stop it */
6694 } else if (_launch_ise_on_request && _soft_keyboard_launched) {
6695 _info_manager->stop_helper (helper_uuid);
6696 _soft_keyboard_launched = false;
6699 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6702 #ifdef HAVE_NOTIFICATION
6703 LOGI("Input detected from H/W keyboard");
6704 if (_MOBILE || _COMMON) {
6705 notification_status_message_post (_("Input detected from hardware keyboard"));
6707 /* Read configurations for notification app (isf-kbd-mode-changer) */
6708 String kbd_mode_changer = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_KBD_MODE_CHANGER_PROGRAM), String (""));
6709 hwkbd_module_noti.launch_app = kbd_mode_changer;
6710 LOGD ("Create kbd_mode_changer notification with : %s", kbd_mode_changer.c_str ());
6711 create_notification (&hwkbd_module_noti);
6715 set_hw_keyboard_input_detect_flag(true);
6716 } else if (mode == TOOLBAR_HELPER_MODE) {
6717 LOGD ("SOFTWARE KEYBOARD MODE");
6718 /* When switching back to S/W keyboard mode, let's hide candidate window first */
6719 #if ISF_BUILD_CANDIDATE_UI
6720 LOGD ("calling ui_candidate_hide (true, true, true)");
6721 ui_candidate_hide (true, true, true);
6722 #endif /* CANDIDATE */
6723 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
6725 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6726 uuid = helper_uuid.length () > 0 ? helper_uuid : _initial_ise_uuid;
6727 if (_launch_ise_on_request) {
6728 if (set_active_ise (uuid, false) == false) {
6729 if (_initial_ise_uuid.compare(uuid))
6730 set_active_ise (_initial_ise_uuid, false);
6734 if (set_active_ise (uuid, true) == false) {
6735 if (_initial_ise_uuid.compare(uuid)) {
6736 LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
6737 set_active_ise (_initial_ise_uuid, true);
6743 #ifdef HAVE_NOTIFICATION
6744 delete_notification (&hwkbd_module_noti);
6747 set_hw_keyboard_input_detect_flag(false);
6752 #ifdef HAVE_NOTIFICATION
6753 static void show_ime_selector_notification ()
6757 if (!_MOBILE && !_COMMON) return;
6759 unsigned int idx = get_ise_index (_info_manager->get_current_helper_uuid ());
6760 if (idx < _ime_info.size ())
6761 ise_name = _ime_info[idx].label;
6763 String noti_icon_path = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_QUICK_PANEL_ICON_PATH), String (SCIM_ICONDIR));
6764 noti_icon_path += ISF_ISE_SELECTOR_ICON_FILE;
6766 LOGD("IME selector icon path : %s", noti_icon_path.c_str ());
6768 ise_selector_module_noti.icon = noti_icon_path;
6769 ise_selector_module_noti.content = ise_name;
6771 /* Find IME Selector appid for notification */
6772 if (ime_selector_app.length () < 1) {
6773 char *app_id = NULL;
6774 pkgmgrinfo_appinfo_filter_h handle;
6775 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
6776 if (ret == PMINFO_R_OK) {
6777 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
6778 if (ret == PMINFO_R_OK) {
6779 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
6781 pkgmgrinfo_appinfo_filter_destroy (handle);
6784 ime_selector_app = String (app_id);
6791 if (ime_selector_app.length () > 0) {
6792 ise_selector_module_noti.launch_app = ime_selector_app;
6793 LOGD ("Create ise_selector notification with : %s", ime_selector_app.c_str ());
6794 create_notification (&ise_selector_module_noti);
6797 LOGW ("AppID with http://tizen.org/category/ime-selector category is not available");
6803 * @brief Callback function for ECORE_X_EVENT_WINDOW_PROPERTY.
6805 * @param data Data to pass when it is called.
6806 * @param ev_type The event type.
6807 * @param ev The information for current message.
6809 * @return ECORE_CALLBACK_PASS_ON
6811 static Eina_Bool x_event_window_property_cb (void *data, int ev_type, void *event)
6813 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6815 Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property *)event;
6818 return ECORE_CALLBACK_PASS_ON;
6820 if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
6821 if (ev->win == _control_window) {
6822 /* WMSYNC, #6 The keyboard window is displayed fully so set the conformant geometry */
6823 LOGD ("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE : win : %p, atom : %d", ev->win, ev->atom);
6824 Ecore_X_Virtual_Keyboard_State state;
6825 state = ecore_x_e_virtual_keyboard_state_get (ev->win);
6826 if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON) {
6827 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_ON");
6828 _ise_state = WINDOW_STATE_SHOW;
6830 /* Make sure that we have the same rotation angle with the keyboard window */
6832 _candidate_angle = efl_get_ise_window_angle ();
6833 _ise_angle = efl_get_ise_window_angle ();
6836 if (_candidate_show_requested) {
6837 LOGD ("calling ui_candidate_show (true)");
6838 ui_candidate_show (true);
6840 if (_candidate_area_1_visible) {
6841 LOGD ("calling ui_candidate_show (false)");
6842 ui_candidate_show (false);
6846 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6847 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6848 _info_manager->update_input_panel_event (
6849 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_SHOW);
6852 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW);
6855 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6856 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6857 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6859 #ifdef HAVE_NOTIFICATION
6860 show_ime_selector_notification ();
6865 _updated_hide_state_geometry = false;
6867 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
6868 } else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) {
6869 /* WMSYNC, #9 The keyboard window is hidden fully so send HIDE state */
6870 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF");
6871 // For now don't send HIDE signal here
6872 //_info_manager->update_input_panel_event (
6873 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6874 _ise_state = WINDOW_STATE_HIDE;
6876 if (!_updated_hide_state_geometry) {
6877 /* When the ISE gets hidden by the window manager forcefully without OFF_PREPARE,
6878 the application might not have updated its autoscroll area */
6879 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6880 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6881 _info_manager->update_input_panel_event (
6882 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6884 _updated_hide_state_geometry = true;
6886 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6887 LOGD ("calling ui_candidate_hide (true, false)");
6888 ui_candidate_hide (true, false);
6890 ui_settle_candidate_window ();
6894 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
6897 #ifdef HAVE_NOTIFICATION
6898 delete_notification (&ise_selector_module_noti);
6901 _ise_reported_geometry.valid = false;
6903 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
6905 ui_settle_candidate_window ();
6907 } else if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
6908 if (ev->win == efl_get_quickpanel_window ()) {
6909 int angle = efl_get_quickpanel_window_angle ();
6910 LOGD ("ev->win : %p, change window angle : %d", ev->win, angle);
6914 return ECORE_CALLBACK_PASS_ON;
6918 * @brief Callback function for X event client message.
6920 * @param data Data to pass when it is called.
6921 * @param type The event type.
6922 * @param event The information for current message.
6924 * @return ECORE_CALLBACK_RENEW
6926 static Eina_Bool x_event_client_message_cb (void *data, int type, void *event)
6928 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6930 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
6933 return ECORE_CALLBACK_RENEW;
6936 if ((ev->win == _control_window)) {
6937 if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST) {
6938 /* WMSYNC, #4 Send WILL_SHOW event when the keyboard window is about to displayed */
6939 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST");
6941 /* WMSYNC, #5 Let the Window Manager to actually show keyboard window */
6942 // WILL_SHOW_REQUEST_DONE Ack to WM
6943 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6944 ecore_x_e_virtual_keyboard_on_prepare_done_send (root_window, _control_window);
6945 LOGD ("_ecore_x_e_virtual_keyboard_on_prepare_done_send (%x, %x)",
6946 root_window, _control_window);
6948 _info_manager->update_input_panel_event (
6949 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
6950 ui_create_candidate_window ();
6952 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_SHOW);
6953 } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST) {
6954 _ise_state = WINDOW_STATE_WILL_HIDE;
6955 /* WMSYNC, #7 Send WILL_HIDE event when the keyboard window is about to hidden */
6956 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST");
6957 // Clear conformant geometry information first
6959 if (_off_prepare_done_timer) {
6960 ecore_timer_del (_off_prepare_done_timer);
6961 _off_prepare_done_timer = NULL;
6963 _off_prepare_done_timer = ecore_timer_add (1.0, off_prepare_done_timeout, NULL);
6965 _ise_reported_geometry.valid = false;
6966 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6967 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6968 _updated_hide_state_geometry = true;
6970 /* If the input panel is getting hidden because of hw keyboard mode while
6971 the candidate window is still opened, it is considered to be an
6972 "input panel being resized" event instead of "input panel being hidden",
6973 since the candidate window will work as an "input panel" afterwards */
6974 bool send_input_panel_hide_event = true;
6975 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6976 LOGD ("_candidate_state : %d", _candidate_state);
6977 if (_candidate_state == WINDOW_STATE_SHOW) {
6978 send_input_panel_hide_event = false;
6981 if (send_input_panel_hide_event) {
6982 _info_manager->update_input_panel_event (
6983 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6985 // For now don't send WILL_HIDE signal here
6986 //_info_manager->update_input_panel_event (
6987 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_HIDE);
6988 // Instead send HIDE signal
6989 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_HIDE);
6990 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE) {
6991 /* WMSYNC, #10 Register size hints for candidate window and set conformant geometry */
6992 // PRE_ROTATE_DONE Ack to WM
6993 _candidate_angle = ev->data.l[1];
6994 _ise_angle = ev->data.l[1];
6995 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE : %d", _candidate_angle);
6997 if (_candidate_angle == 90 || _candidate_angle == 270) {
6998 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
7000 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
7002 if (_ise_state == WINDOW_STATE_SHOW) {
7003 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7004 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7006 ui_settle_candidate_window ();
7007 ui_candidate_window_rotate (_candidate_angle);
7008 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
7009 LOGD ("ecore_x_e_window_rotation_change_prepare_done_send (%d)", _candidate_angle);
7010 ecore_x_e_window_rotation_change_prepare_done_send (root_window,
7011 _control_window, _candidate_angle);
7012 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7013 int ise_angle = (int)ev->data.l[1];
7014 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST for ISE WINDOW : ISE angle : %d, Candidate angle : %d", ise_angle, _candidate_angle);
7015 _candidate_angle = ise_angle;
7016 _ise_angle = ise_angle;
7017 if (_ise_state == WINDOW_STATE_SHOW) {
7018 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7019 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7020 ui_settle_candidate_window ();
7023 } else if (ev->win == elm_win_xwindow_get (_candidate_window)) {
7024 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST || ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE) {
7025 /* WMSYNC, #11 Actual rotate the candidate window */
7026 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7027 _candidate_angle = (int)ev->data.l[1];
7028 ui_candidate_window_rotate (_candidate_angle);
7029 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST : %d", _candidate_angle);
7030 } else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE &&
7031 _ise_state != WINDOW_STATE_SHOW) {
7032 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_TRUE);
7033 _candidate_angle = (int)ev->data.l[0];
7034 if (_candidate_angle == 90 || _candidate_angle == 270) {
7035 evas_object_resize (_candidate_window, _candidate_land_width, _candidate_land_height_min);
7037 evas_object_resize (_candidate_window, _candidate_port_width, _candidate_port_height_min);
7039 ui_candidate_window_rotate (_candidate_angle);
7040 ui_settle_candidate_window ();
7041 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_FALSE);
7042 LOGD ("ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE : %d", _candidate_angle);
7044 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " : ANGLE (" << _candidate_angle << ")\n";
7049 /* Screen reader feature */
7050 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL) {
7051 static int last_pos_x = -10000;
7052 static int last_pos_y = -10000;
7054 if (_candidate_window) {
7055 if ((unsigned int)ev->data.l[0] == elm_win_xwindow_get (_candidate_window)) {
7056 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE) {
7057 // 1 finger double tap
7058 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger double tap focus index = " << _candidate_tts_focus_index << "\n";
7059 ui_mouse_click (_candidate_tts_focus_index);
7060 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ) {
7062 // 1 finger touch & move
7063 last_pos_x = ev->data.l[2];
7064 last_pos_y = ev->data.l[3];
7065 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger touch & move (" << last_pos_x << ", " << last_pos_y << ")\n";
7066 ui_mouse_over (last_pos_x, last_pos_y);
7067 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT ||
7068 (unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV) {
7069 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT) {
7071 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick right\n";
7072 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_display_number - 1))
7073 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : 0;
7074 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7075 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7076 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7077 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7078 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7079 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? 0 : _candidate_row_items[0];
7080 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7081 _candidate_tts_focus_index = _candidate_row_items[0];
7082 else if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < (g_isf_candidate_table.get_current_page_size () - 1))
7083 _candidate_tts_focus_index++;
7084 else if (_candidate_tts_focus_index == (g_isf_candidate_table.get_current_page_size () - 1))
7085 _candidate_tts_focus_index = 0;
7088 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick left\n";
7089 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == 0)
7090 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : _candidate_display_number - 1;
7091 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7092 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7093 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7094 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7095 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7096 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7097 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7098 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7099 else if (_candidate_tts_focus_index > 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ())
7100 _candidate_tts_focus_index--;
7101 else if (_candidate_tts_focus_index == 0)
7102 _candidate_tts_focus_index = g_isf_candidate_table.get_current_page_size () - 1;
7105 int x = 0, y = 0, w = 0, h = 0;
7106 _wait_stop_event = false;
7107 if (candidate_expanded) {
7109 int cursor_line = 0;
7110 for (unsigned int i = 0; i < _candidate_row_items.size (); i++) {
7111 total += _candidate_row_items [i];
7112 if (total > (int)_candidate_display_number && _candidate_tts_focus_index >= total)
7116 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
7118 int line_h = _item_min_height + _v_padding;
7119 int cursor_y = cursor_line * line_h;
7121 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
7122 _wait_stop_event = true;
7123 } else if (cursor_y >= y + h) {
7124 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
7125 _wait_stop_event = true;
7130 String strTts = String ("");
7131 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
7132 strTts = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (_candidate_tts_focus_index));
7133 if (_candidate_0 [_candidate_tts_focus_index])
7134 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
7135 } else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX) {
7136 strTts = String (_("more button"));
7137 evas_object_geometry_get (_more_btn, &x, &y, &w, &h);
7138 } else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX) {
7139 strTts = String (_("close button"));
7140 evas_object_geometry_get (_close_btn, &x, &y, &w, &h);
7142 ui_tts_focus_rect_hide ();
7145 if (w > 0 && h > 0) {
7146 if (!_wait_stop_event)
7147 ui_tts_focus_rect_show (x, y, w, h);
7149 ui_tts_focus_rect_hide ();
7156 return ECORE_CALLBACK_RENEW;
7160 Eina_Bool check_focus_out_by_popup_win ()
7162 Eina_Bool ret = EINA_FALSE;
7164 Ecore_X_Window focus_win = ecore_x_window_focus_get ();
7165 Ecore_X_Window_Type win_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
7167 if (!ecore_x_netwm_window_type_get (focus_win, &win_type))
7170 LOGD ("win type : %d", win_type);
7172 if (win_type == ECORE_X_WINDOW_TYPE_POPUP_MENU ||
7173 win_type == ECORE_X_WINDOW_TYPE_NOTIFICATION) {
7182 * @brief Callback function for focus out event of application window
7184 * @param data Data to pass when it is called.
7186 * @return ECORE_CALLBACK_RENEW
7188 static Eina_Bool x_event_window_focus_out_cb (void *data, int ev_type, void *event)
7190 Ecore_X_Event_Window_Focus_Out *e = (Ecore_X_Event_Window_Focus_Out*)event;
7192 if (e && e->win == _app_window) {
7193 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7194 if (check_focus_out_by_popup_win ())
7195 return ECORE_CALLBACK_RENEW;
7197 #if ENABLE_MULTIWINDOW_SUPPORT
7198 unsigned int layout = 0;
7199 LOGD ("Application window focus OUT!");
7200 delete_ise_hide_timer ();
7202 // Check multi window mode
7203 if (ecore_x_window_prop_card32_get (efl_get_app_window (), ECORE_X_ATOM_E_WINDOW_DESKTOP_LAYOUT, &layout, 1) != -1) {
7204 if (layout == 0 || layout == 1) {
7206 LOGD ("Multi window mode. start timer to hide IME");
7208 // Use timer not to hide and show IME again in focus-out and focus-in event between applications
7209 _ise_hide_timer = ecore_timer_add (ISF_ISE_HIDE_DELAY, ise_hide_timeout, NULL);
7213 if (!_ise_hide_timer) {
7214 LOGD ("Panel hides ISE");
7215 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7217 ui_candidate_hide (true, false, false);
7220 LOGD ("Application window focus OUT! Panel hides ISE");
7221 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7223 ui_candidate_hide (true, false, false);
7228 return ECORE_CALLBACK_RENEW;
7232 static void restore_config ()
7234 if (!_config.null ()) {
7235 String uuid = _initial_ise_uuid;
7237 String global_uuid = scim_global_config_read (String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String(""));
7238 if (global_uuid.length () > 0) uuid = global_uuid;
7240 String default_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
7241 if (default_uuid.length() > 0) uuid = default_uuid;
7243 if (global_uuid.length() == 0) {
7244 scim_global_config_write (String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), uuid);
7246 if (default_uuid.length() == 0) {
7247 _config->write (SCIM_CONFIG_DEFAULT_HELPER_ISE, uuid);
7250 scim_global_config_flush ();
7253 scim_global_config_reload ();
7259 * @brief : Launches default soft keyboard for performance enhancement (It's not mandatory)
7261 static void launch_default_soft_keyboard (keynode_t *key, void* data)
7263 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7266 if (!_config.null()) {
7267 helper_uuid = _config->read(SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
7269 if (helper_uuid.length () > 0) {
7270 /* Start default ISE */
7271 change_keyboard_mode (TOOLBAR_HELPER_MODE);
7273 if (!_launch_ise_on_request) {
7274 set_temporary_ise (_initial_ise_uuid);
7280 static String sanitize_string (const char *str, int maxlen = 32)
7283 static char acceptables[] =
7284 "abcdefghijklmnopqrstuvwxyz"
7285 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7288 char *newstr = NULL;
7290 newstr = new char[maxlen + 1];
7294 memset (newstr, 0x00, sizeof (char) * (maxlen + 1));
7297 while (len < maxlen && str[len] != '\0' && strchr (acceptables, str[len]) != NULL) {
7298 newstr[len] = str[len];
7308 static Eina_Bool monitor_user_data_path_timer(void *data)
7310 const char *path = static_cast<const char*>(data);
7311 bool user_data_path_exists = g_file_test (path, G_FILE_TEST_EXISTS);
7312 bool user_data_path_is_dir = g_file_test (path, G_FILE_TEST_IS_DIR);
7313 if (user_data_path_exists && user_data_path_is_dir) {
7314 LOGW ("'%s' exists : %d, is_dir : %d", path,
7315 (user_data_path_exists ? 1 : 0), (user_data_path_is_dir ? 1 : 0));
7317 scim_global_config_reload (true);
7321 /* Read all ime info from db */
7323 isf_pkg_select_all_ime_info_db (_ime_info);
7326 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
7329 if (_launch_ise_on_request) {
7332 String default_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
7334 set_active_ise (default_ise_uuid, launch);
7338 g_monitor_user_data_path_timer = NULL;
7339 return ECORE_CALLBACK_CANCEL;
7342 return ECORE_CALLBACK_RENEW;
7345 int main (int argc, char *argv [])
7347 struct tms tiks_buf;
7348 _clock_start = times (&tiks_buf);
7353 bool daemon = false;
7354 bool should_resident = true;
7357 char **new_argv = new char * [40];
7358 int display_name_c = 0;
7359 ConfigModule *config_module = NULL;
7360 String config_name = String ("simple");
7361 String display_name = String ();
7362 char buf[256] = {0};
7364 String user_data_path = String ();
7365 bool user_data_path_exists = false;
7366 bool user_data_path_is_dir = false;
7369 Ecore_Event_Handler *xclient_message_handler = NULL;
7370 Ecore_Event_Handler *xwindow_property_handler = NULL;
7371 Ecore_Event_Handler *xwindow_focus_out_handler = NULL;
7374 check_time ("\nStarting ISF Panel EFL...... ");
7375 ISF_SAVE_LOG ("Starting ISF Panel EFL......");
7377 DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
7378 DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
7380 /* Parse command options */
7386 if (String ("-c") == argv [i] || String ("--config") == argv [i]) {
7388 std::cerr << "no argument for option " << argv [i-1] << "\n";
7392 config_name = argv [i];
7396 if (String ("-h") == argv [i] || String ("--help") == argv [i]) {
7397 std::cout << "Usage: " << argv [0] << " [option]...\n\n"
7398 << "The options are: \n"
7399 << " --display DISPLAY Run on display DISPLAY.\n"
7400 << " -c, --config NAME Uses specified Config module.\n"
7401 << " -d, --daemon Run " << argv [0] << " as a daemon.\n"
7402 << " -ns, --no-stay Quit if no connected client.\n"
7404 << " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
7405 << " -o, --output FILE Output debug information into FILE.\n"
7407 << " -h, --help Show this help message.\n";
7412 if (String ("-d") == argv [i] || String ("--daemon") == argv [i]) {
7417 if (String ("-ns") == argv [i] || String ("--no-stay") == argv [i]) {
7418 should_resident = false;
7422 if (String ("-v") == argv [i] || String ("--verbose") == argv [i]) {
7424 std::cerr << "no argument for option " << argv [i-1] << "\n";
7428 DebugOutput::set_verbose_level (atoi (argv [i]));
7432 if (String ("-o") == argv [i] || String ("--output") == argv [i]) {
7434 std::cerr << "No argument for option " << argv [i-1] << "\n";
7438 DebugOutput::set_output (sanitize_string (argv [i]));
7442 if (String ("--display") == argv [i]) {
7444 std::cerr << "No argument for option " << argv [i-1] << "\n";
7448 display_name = sanitize_string (argv [i]);
7452 if (String ("--") == argv [i])
7455 std::cerr << "Invalid command line option: " << argv [i] << "\n";
7458 } /* End of command line parsing. */
7461 new_argv [new_argc ++] = argv [0];
7463 /* Store the rest argvs into new_argv. */
7464 for (++i; i < argc && new_argc < 37; ++i) {
7465 new_argv [new_argc ++] = argv [i];
7468 /* Make up DISPLAY env. */
7469 if (display_name.length ()) {
7470 new_argv [new_argc ++] = const_cast <char*> ("--display");
7471 display_name_c = new_argc;
7472 new_argv [new_argc ++] = strdup (display_name.c_str ());
7474 setenv ("DISPLAY", display_name.c_str (), 1);
7477 new_argv [new_argc] = 0;
7480 if (!config_name.length ()) {
7481 std::cerr << "No Config module is available!\n";
7486 /* Get current display. */
7488 const char *p = getenv ("DISPLAY");
7490 display_name = String (p);
7493 snprintf (buf, sizeof (buf), "config_name=%s display_name=%s", config_name.c_str (), display_name.c_str ());
7497 check_time ("ISF Panel EFL run as daemon");
7501 /* No loading default theme to reduce heap memory */
7502 setenv ("ELM_THEME", "", 1);
7504 #if ISF_BUILD_CANDIDATE_UI
7505 elm_init (argc, argv);
7508 ecore_app_args_set(argc, (const char **)argv);
7509 #endif /* CANDIDATE */
7511 check_time ("elm_init");
7515 #if ISF_BUILD_CANDIDATE_UI
7516 elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
7517 #endif /* CANDIDATE */
7519 if (config_name != "dummy") {
7520 /* Load config module */
7521 config_module = new ConfigModule (config_name);
7523 if (!config_module || !config_module->valid ()) {
7524 std::cerr << "Can not load " << config_name << " Config module.\n";
7529 _config = new DummyConfig ();
7532 /* Create config instance */
7533 if (_config.null () && config_module && config_module->valid ())
7534 _config = config_module->create_config ();
7535 if (_config.null ()) {
7536 std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
7540 ConfigBase::set (_config);
7541 check_time ("create config instance");
7546 if (!initialize_panel_agent (_config, display_name, should_resident)) {
7547 check_time ("Failed to initialize Panel Agent!");
7548 std::cerr << "Failed to initialize Panel Agent!\n";
7549 LOGE ("Failed to initialize Panel Agent!");
7553 } catch (scim::Exception & e) {
7554 std::cerr << e.what () << "\n";
7559 check_time ("initialize_panel_agent");
7561 #if ISF_BUILD_CANDIDATE_UI
7562 /* Initialize global variables and pointers for candidate items and etc. */
7563 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; i++) {
7564 _candidate_0 [i] = NULL;
7565 _seperate_0 [i] = NULL;
7566 _seperate_items [i] = NULL;
7568 _line_items [i] = NULL;
7569 _candidate_text [i] = NULL;
7570 _candidate_image [i] = NULL;
7571 _candidate_pop_image [i] = NULL;
7573 #endif /* CANDIDATE */
7575 /* Connect the configuration reload signal. */
7576 _config_connection = _config->signal_connect_reload (slot (config_reload_cb));
7579 if (!efl_create_control_window ()) {
7580 LOGW ("Failed to create control window");
7585 #if ISF_BUILD_CANDIDATE_UI
7586 efl_get_screen_resolution (_screen_width, _screen_height);
7588 _width_rate = (float)(_screen_width / 720.0);
7589 _height_rate = (float)(_screen_height / 1280.0);
7590 _blank_width = (int)(_blank_width * _width_rate);
7591 _item_min_width = (int)(_item_min_width * _width_rate);
7592 _item_min_height = (int)(_item_min_height * _height_rate);
7593 _candidate_width = (int)(_candidate_port_width * _width_rate);
7594 _candidate_height = (int)(_candidate_port_height_min * _height_rate);
7595 _indicator_height = (int)(_indicator_height * _height_rate);
7597 _aux_font_size = (int)(_aux_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7598 _candidate_font_size = (int)(_candidate_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7599 #endif /* CANDIDATE */
7601 /* Load ISF configuration */
7602 user_data_path = scim_get_user_data_dir ();
7603 user_data_path_exists = g_file_test (user_data_path.c_str(), G_FILE_TEST_EXISTS);
7604 user_data_path_is_dir = g_file_test (user_data_path.c_str(), G_FILE_TEST_IS_DIR);
7605 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
7606 if (vconf_set_bool (VCONFKEY_ISF_IME_LAUNCH_ON_DEMAND, _launch_ise_on_request) != 0)
7607 LOGW ("Failed to set vconf key");
7609 if (user_data_path_exists && user_data_path_is_dir) {
7612 LOGW ("'%s' exists : %d, is_dir : %d", user_data_path.c_str (),
7613 (user_data_path_exists ? 1 : 0), (user_data_path_is_dir ? 1 : 0));
7614 g_monitor_user_data_path_timer = ecore_timer_add (1.0, monitor_user_data_path_timer, user_data_path.c_str ());
7616 check_time("load_config");
7620 lang_str = vconf_get_str (VCONFKEY_LANGSET);
7621 set_language_and_locale (lang_str);
7625 /* Add callback function for input language and display language */
7626 vconf_notify_key_changed (VCONFKEY_LANGSET, display_language_changed_cb, NULL);
7627 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
7631 /* Update ISE list */
7632 std::vector<String> list;
7633 update_ise_list (list);
7635 /* Load initial ISE information */
7636 _initial_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_INITIAL_ISE_UUID), String (SCIM_COMPOSE_KEY_FACTORY_UUID));
7638 /* Check if SCIM_CONFIG_DEFAULT_HELPER_ISE is available. If it's not, set it as _initial_ise_uuid.
7639 e.g., This might be necessary when the platform is upgraded from 2.3 to 2.4. */
7640 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
7641 if (_initial_ise_uuid.length() > 0 && helper_uuid != _initial_ise_uuid) {
7643 for (unsigned int u = 0; u < _ime_info.size (); u++) {
7644 if (_ime_info[u].mode == TOOLBAR_HELPER_MODE && helper_uuid == _ime_info[u].appid) {
7650 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), _initial_ise_uuid);
7654 /* Request to terminate active IME */
7655 terminate_active_ise (_initial_ise_uuid);
7657 /* Launches default soft keyboard when all conditions are satisfied */
7658 launch_default_soft_keyboard ();
7660 /* Update the name of each ISE according to display language */
7661 update_ise_locale ();
7662 } catch (scim::Exception & e) {
7663 std::cerr << e.what () << "\n";
7664 } catch (std::logic_error & e) {
7665 std::cerr << e.what () << "\n";
7668 xclient_message_handler = ecore_event_handler_add (ECORE_X_EVENT_CLIENT_MESSAGE, x_event_client_message_cb, NULL);
7669 xwindow_property_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, x_event_window_property_cb, NULL);
7670 xwindow_focus_out_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_FOCUS_OUT, x_event_window_focus_out_cb, NULL);
7673 #if ENABLE_REMOTE_INPUT
7675 launch_remote_input = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_REMOTE_INPUT), launch_remote_input);
7677 /* Create remote input */
7678 if (launch_remote_input) {
7679 LOGD("remote input start");
7680 remote_input_impl = new Remote_Input();
7681 if (remote_input_impl) {
7682 remote_input_impl->init(_info_manager);
7688 #if ISF_BUILD_CANDIDATE_UI
7689 _system_scale = elm_config_scale_get ();
7691 /* Set elementary scale */
7692 if (_screen_width) {
7693 _app_scale = _screen_width / 720.0;
7694 elm_config_scale_set (_app_scale);
7696 snprintf (buf, sizeof (buf), "%4.3f", _app_scale);
7697 setenv ("ELM_SCALE", buf, 1);
7699 #endif /* CANDIDATE */
7701 signal (SIGQUIT, signalhandler);
7702 signal (SIGTERM, signalhandler);
7703 signal (SIGINT, signalhandler);
7704 signal (SIGHUP, signalhandler);
7706 check_time ("EFL Panel launch time");
7708 if (!isf_cynara_initialize())
7709 LOGW ("Failed to initialize cynara");
7711 clear_cpu_boosting();
7713 #if ISF_BUILD_CANDIDATE_UI
7716 ecore_main_loop_begin ();
7717 #endif /* CANDIDATE */
7719 LOGW("out of loop");
7721 isf_cynara_finish();
7726 if (g_monitor_user_data_path_timer) {
7727 ecore_timer_del (g_monitor_user_data_path_timer);
7728 g_monitor_user_data_path_timer = NULL;
7732 if (xclient_message_handler) {
7733 ecore_event_handler_del (xclient_message_handler);
7734 xclient_message_handler = NULL;
7737 if (xwindow_property_handler) {
7738 ecore_event_handler_del (xwindow_property_handler);
7739 xwindow_property_handler = NULL;
7742 if (xwindow_focus_out_handler) {
7743 ecore_event_handler_del (xwindow_focus_out_handler);
7744 xwindow_focus_out_handler = NULL;
7749 /* Remove callback function for input language and display language */
7750 vconf_ignore_key_changed (VCONFKEY_LANGSET, display_language_changed_cb);
7751 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
7755 #if ISF_BUILD_CANDIDATE_UI
7756 ui_destroy_candidate_window ();
7757 ui_candidate_delete_check_size_timer ();
7758 ui_candidate_delete_longpress_timer ();
7759 ui_candidate_delete_destroy_timer ();
7760 #endif /* CANDIDATE */
7761 #ifdef HAVE_PKGMGR_INFO
7763 package_manager_destroy (pkgmgr);
7767 delete_ise_check_pid_alive_timer();
7769 if (_info_manager) {
7771 _info_manager->stop ();
7772 } catch (scim::Exception & e) {
7773 std::cerr << "Exception is thrown from _info_manager->stop (), error is " << e.what () << "\n";
7775 delete _info_manager;
7777 _config_connection.disconnect ();
7778 if (!_config.null ())
7780 ConfigBase::set (0);
7783 delete config_module;
7785 #if ISF_BUILD_CANDIDATE_UI
7789 #endif /* CANDIDATE */
7792 if ((display_name_c > 0) && new_argv [display_name_c]) {
7793 free (new_argv [display_name_c]);
7798 ISF_SAVE_LOG ("ret=%d", ret);
7800 std::cerr << "Successfully exited.\n";
7803 std::cerr << "Abnormally exited.\n";
7809 vi:ts=4:nowrap:expandtab