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>
43 #include "scim_private.h"
45 #include "scim_stl_map.h"
46 #if ISF_BUILD_CANDIDATE_UI
48 #include <Elementary.h>
51 #include <Ecore_Wayland.h>
52 #endif /* HAVE_ECOREWL */
55 #endif /* HAVE_ECOREX */
58 #include <X11/Xatom.h>
65 #endif /* HAVE_FEEDBACK */
66 #endif /* CANDIDATE */
69 #include <vconf-keys.h>
72 #ifdef HAVE_NOTIFICATION
73 #include <notification.h>
74 #include <notification_internal.h>
78 #include <bluetooth.h>
80 #ifdef HAVE_PKGMGR_INFO
81 #include <package_manager.h>
82 #include <pkgmgr-info.h>
84 #include <app_control.h>
87 #include "isf_panel_efl.h"
88 #include "isf_panel_utility.h"
89 #include "isf_query_utility.h"
91 #include "privilege_checker.h"
92 #include "remote_input.h"
93 #include "tizen_profile.h"
98 /////////////////////////////////////////////////////////////////////////////
99 // Declaration of macro.
100 /////////////////////////////////////////////////////////////////////////////
101 #define EFL_CANDIDATE_THEME1 (SCIM_DATADIR "/isf_candidate_theme1.edj")
103 #define ISF_CANDIDATE_TABLE 0
105 #define ISF_EFL_AUX 1
106 #define ISF_EFL_CANDIDATE_0 2
107 #define ISF_EFL_CANDIDATE_ITEMS 3
109 #define ISE_DEFAULT_HEIGHT_PORTRAIT 444
110 #define ISE_DEFAULT_HEIGHT_LANDSCAPE 316
112 #define ISF_CANDIDATE_DESTROY_DELAY 3
113 #define ISF_ISE_HIDE_DELAY 0.15
115 #define ISF_PREEDIT_BORDER 16
116 #define ISE_LAUNCH_TIMEOUT 2.0
118 #define ISF_POP_PLAY_ICON_FILE (SCIM_ICONDIR "/pop_play.png")
119 #define ISF_KEYBOARD_ICON_FILE (SCIM_ICONDIR "/noti_keyboard_connected.png")
120 #define ISF_ISE_SELECTOR_ICON_FILE "/noti_keyboard.png"
122 #define HOST_BUS_NAME "org.tizen.usb.host"
123 #define HOST_OBJECT_PATH "/Org/Tizen/Usb/Host"
124 #define HOST_INTERFACE_NAME "org.tizen.usb.host"
125 #define HOST_KEYBOARD_SIGNAL "usbkeyboard"
126 #define HOST_ADDED "added"
127 #define HOST_REMOVED "removed"
129 #define E_PROP_DEVICEMGR_INPUTWIN "DeviceMgr Input Window"
132 /////////////////////////////////////////////////////////////////////////////
133 // Declaration of external variables.
134 /////////////////////////////////////////////////////////////////////////////
135 extern MapStringVectorSizeT _groups;
136 extern std::vector<ImeInfoDB> _ime_info;
138 CommonLookupTable g_isf_candidate_table;
141 /////////////////////////////////////////////////////////////////////////////
142 // Declaration of internal data types.
143 /////////////////////////////////////////////////////////////////////////////
144 typedef enum _WINDOW_STATE {
145 WINDOW_STATE_HIDE = 0,
146 WINDOW_STATE_WILL_HIDE,
147 WINDOW_STATE_WILL_SHOW,
152 typedef struct NotiData
161 typedef std::vector < std::pair <String, uint32> > VectorPairStringUint32;
163 /////////////////////////////////////////////////////////////////////////////
164 // Declaration of internal functions.
165 /////////////////////////////////////////////////////////////////////////////
166 #if ISF_BUILD_CANDIDATE_UI
167 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect);
168 #endif /* CANDIDATE */
171 static void efl_set_transient_for_app_window (Ecore_X_Window window);
173 #if ISF_BUILD_CANDIDATE_UI
174 static int efl_get_app_window_angle (void);
175 #endif /* CANDIDATE */
176 static int efl_get_ise_window_angle (void);
177 #if ISF_BUILD_CANDIDATE_UI
179 static int efl_get_quickpanel_window_angle (void);
180 #endif /* HAVE_ECOREX */
182 static int ui_candidate_get_valid_height (void);
183 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd = true, bool will_hide = false);
184 static void ui_destroy_candidate_window (void);
185 static void ui_settle_candidate_window (void);
186 static void ui_candidate_show (bool bSetVirtualKbd = true);
187 static void ui_create_candidate_window (void);
188 static void update_table (int table_type, const LookupTable &table);
189 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info);
190 #endif /* CANDIDATE */
191 static void set_soft_candidate_geometry (int x, int y, int width, int height);
192 #if ISF_BUILD_CANDIDATE_UI
193 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack);
194 static void ui_tts_focus_rect_hide (void);
195 #endif /* CANDIDATE */
197 #if ISF_BUILD_CANDIDATE_UI
198 static Evas_Object *get_candidate (const String& str, Evas_Object *parent, int *total_width, uint32 ForeGround, uint32 BackGround, bool HighLight, bool SetBack, int item_num, int item);
199 static bool tokenize_tag (const String& str, struct image *image_data);
200 #endif /* CANDIDATE */
202 static void launch_default_soft_keyboard (keynode_t *key = NULL, void* data = NULL);
204 /* PanelAgent related functions */
205 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident);
207 static void slot_focus_in (void);
208 static void slot_focus_out (void);
209 static void slot_expand_candidate (void);
210 static void slot_contract_candidate (void);
211 static void slot_set_candidate_style (int portrait_line, int mode);
212 static void slot_update_input_context (int type, int value);
213 static void slot_update_ise_geometry (int x, int y, int width, int height);
214 static void slot_update_spot_location (int x, int y, int top_y);
215 static void slot_update_factory_info (const PanelFactoryInfo &info);
216 static void slot_show_preedit_string (void);
217 static void slot_show_aux_string (void);
218 static void slot_show_candidate_table (void);
219 static void slot_hide_preedit_string (void);
220 static void slot_hide_aux_string (void);
221 static void slot_hide_candidate_table (void);
222 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret);
223 static void slot_update_preedit_caret (int caret);
224 static void slot_update_aux_string (const String &str, const AttributeList &attrs);
225 static void slot_update_candidate_table (const LookupTable &table);
226 static void slot_select_candidate (int index);
227 static void slot_set_active_ise (const String &uuid, bool changeDefault);
228 static bool slot_get_ise_list (std::vector<String> &list);
229 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info);
230 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option);
231 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled);
232 static void slot_show_helper_ise_list (void);
233 static void slot_show_helper_ise_selector (void);
234 static bool slot_is_helper_ise_enabled (String appid, int &enabled);
235 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name);
236 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list);
237 static void slot_get_language_list (std::vector<String> &name);
238 static void slot_get_all_language (std::vector<String> &lang);
239 static void slot_get_ise_language (char *name, std::vector<String> &list);
240 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info);
241 static void slot_get_candidate_geometry (struct rectinfo &info);
242 static void slot_get_input_panel_geometry (struct rectinfo &info);
243 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info);
244 static bool slot_check_privilege_by_sockfd (int client_id, String privilege);
245 static void slot_set_keyboard_ise (const String &uuid);
246 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid);
247 static void slot_accept_connection (int fd);
248 static void slot_close_connection (int fd);
249 static void slot_exit (void);
251 static void slot_register_helper (int id, const HelperInfo& info);
252 static void slot_register_helper_properties (int id, const PropertyList &props);
253 static void slot_show_ise (void);
254 static void slot_hide_ise (void);
256 static void slot_will_hide_ack (void);
257 static void slot_candidate_will_hide_ack (void);
259 static void slot_set_keyboard_mode (int mode);
260 static void slot_get_ise_state (int &state);
261 static void slot_start_default_ise (void);
262 static void slot_stop_default_ise (void);
263 static void slot_run_helper (const String &uuid, const String &config, const String &display);
264 static bool slot_launch_option_application (String ime_appid);
266 #if ENABLE_REMOTE_INPUT
267 static void slot_send_remote_input_message (const String &msg, bool len);
268 static void slot_recv_remote_surrounding_text (int cursor, const String &text);
272 static Eina_Bool efl_create_control_window (void);
273 static Ecore_X_Window efl_get_app_window (void);
274 static Ecore_X_Window efl_get_quickpanel_window (void);
275 static Ecore_X_Window efl_get_global_navigation_window (void);
278 static void change_keyboard_mode (TOOLBAR_MODE_T mode);
279 static unsigned int get_ise_index (const String uuid);
280 static bool set_active_ise (const String &uuid, bool launch_ise);
281 static bool update_ise_list (std::vector<String> &list);
282 static void update_ise_locale (const char *lang = NULL);
283 #ifdef HAVE_NOTIFICATION
284 static void delete_notification (NotificationData *noti_data);
285 static void create_notification (NotificationData *noti_data);
286 static void show_ime_selector_notification (void);
288 static void set_language_and_locale (const char *lang_str);
289 static bool app_control_launch (const char *app_id);
291 /////////////////////////////////////////////////////////////////////////////
292 // Declaration of internal variables.
293 /////////////////////////////////////////////////////////////////////////////
294 #if ISF_BUILD_CANDIDATE_UI
295 static Evas_Object *_candidate_window = 0;
296 static Evas_Object *_candidate_area_1 = 0;
297 static Evas_Object *_candidate_area_2 = 0;
298 static Evas_Object *_candidate_bg = 0;
299 static Evas_Object *_candidate_0_scroll = 0;
300 static Evas_Object *_candidate_scroll = 0;
301 static Evas_Object *_scroller_bg = 0;
302 static Evas_Object *_candidate_0_table = 0;
303 static Evas_Object *_candidate_table = 0;
304 static Evas_Object *_candidate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
305 static Evas_Object *_candidate_text [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
306 static Evas_Object *_candidate_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
307 static Evas_Object *_candidate_pop_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
308 static Evas_Object *_seperate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
309 static Evas_Object *_seperate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
310 static Evas_Object *_line_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
311 static Evas_Object *_line_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
312 static Evas_Object *_more_btn = 0;
313 static Evas_Object *_close_btn = 0;
314 static bool _candidate_show_requested = false;
315 #endif /* CANDIDATE */
316 static bool _updated_hide_state_geometry = false;
317 #if ISF_BUILD_CANDIDATE_UI
318 static int _candidate_x = 0;
319 static int _candidate_y = 0;
320 static int _candidate_width = 0;
321 static int _candidate_height = 0;
322 #endif /* CANDIDATE */
323 static int _soft_candidate_width = 0;
324 static int _soft_candidate_height = 0;
325 #if ISF_BUILD_CANDIDATE_UI
326 static int _candidate_valid_height = 0;
328 static bool _candidate_area_1_visible = false;
329 static bool _candidate_area_2_visible = false;
330 static bool _aux_area_visible = false;
331 #endif /* CANDIDATE */
333 static ISF_CANDIDATE_MODE_T _candidate_mode = SOFT_CANDIDATE_WINDOW;
334 static ISF_CANDIDATE_PORTRAIT_LINE_T _candidate_port_line = ONE_LINE_CANDIDATE;
336 #if ISF_BUILD_CANDIDATE_UI
337 static int _candidate_port_width = 480;
338 static int _candidate_port_height_min = 76;
339 static int _candidate_port_height_min_2 = 150;
340 static int _candidate_port_height_max = 286;
341 static int _candidate_port_height_max_2 = 350;
342 static int _candidate_land_width = 784;
343 static int _candidate_land_height_min = 84;
344 static int _candidate_land_height_min_2 = 168;
345 static int _candidate_land_height_max = 150;
346 static int _candidate_land_height_max_2 = 214;
347 static int _candidate_area_1_pos [2] = {0, 2};
348 static int _more_btn_pos [4] = {369, 11, 689, 11};
349 static int _close_btn_pos [4] = {362, 211, 682, 75};
350 static int _more_btn_width = 80;
351 static int _more_btn_height = 64;
353 static int _h_padding = 4;
354 static int _v_padding = 2;
355 static int _item_min_width = 99;
356 static int _item_min_height = 82;
358 static int _candidate_scroll_0_width_min = 350;
359 static int _candidate_scroll_0_width_max = 670;
361 static int _candidate_scroll_width = 453;
362 static int _candidate_scroll_width_min = 453;
363 static int _candidate_scroll_width_max = 663;
364 static int _candidate_scroll_height_min = 124;
365 static int _candidate_scroll_height_max = 190;
367 const int MORE_BUTTON_INDEX = -1;
368 const int CLOSE_BUTTON_INDEX = -2;
369 const int INVALID_TTS_FOCUS_INDEX = -100;
370 static int _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
371 static uint32 _candidate_display_number = 0;
372 static std::vector<uint32> _candidate_row_items;
373 static Evas_Object *_tts_focus_rect = 0;
374 static bool _wait_stop_event = false;
376 static Evas_Object *_preedit_window = 0;
377 static Evas_Object *_preedit_text = 0;
378 static int _preedit_width = 100;
379 static int _preedit_height = 54;
381 static Evas_Object *_aux_area = 0;
382 static Evas_Object *_aux_line = 0;
383 static Evas_Object *_aux_table = 0;
384 static int _aux_height = 0;
385 static int _aux_port_width = 444;
386 static int _aux_land_width = 764;
387 static std::vector<Evas_Object *> _aux_items;
388 static std::vector<Evas_Object *> _aux_seperates;
390 static Evas_Object *_tmp_preedit_text = 0;
391 static Evas_Object *_tmp_aux_text = 0;
392 static Evas_Object *_tmp_candidate_text = 0;
394 static int _spot_location_x = -1;
395 static int _spot_location_y = -1;
396 static int _spot_location_top_y = -1;
397 static int _candidate_angle = 0;
398 #endif /* CANDIDATE */
400 static int _ise_angle = -1;
401 static int _ise_x = 0;
402 static int _ise_y = 0;
403 static int _ise_width = 0;
404 static int _ise_height = 0;
405 static WINDOW_STATE _ise_state = WINDOW_STATE_HIDE;
406 static WINDOW_STATE _candidate_state = WINDOW_STATE_HIDE;
408 #if ISF_BUILD_CANDIDATE_UI
409 static int _indicator_height = 0;//24;
410 static int _screen_width = 720;
411 static int _screen_height = 1280;
412 static float _width_rate = 1.0;
413 static float _height_rate = 1.0;
414 static int _blank_width = 30;
416 static String _candidate_name = String ("candidate");
417 static String _candidate_edje_file = String (EFL_CANDIDATE_THEME1);
419 static String _candidate_font_name = String ("Tizen");
420 static int _candidate_font_size = 38;
421 static int _aux_font_size = 38;
422 static int _click_object = 0;
423 static int _click_down_pos [2] = {0, 0};
424 static int _click_up_pos [2] = {0, 0};
425 static bool _is_click = true;
426 #endif /* CANDIDATE */
427 static String _initial_ise_uuid = String ("");
428 static String _locale_string = String ("");
429 static ConfigPointer _config;
430 static Connection _config_connection;
432 static InfoManager *_info_manager = 0;
434 static clock_t _clock_start;
436 #if ISF_BUILD_CANDIDATE_UI
437 static Ecore_Timer *_check_size_timer = NULL;
438 static Ecore_Timer *_longpress_timer = NULL;
439 static Ecore_Timer *_destroy_timer = NULL;
440 #endif /* CANDIDATE */
442 static Ecore_Timer *_off_prepare_done_timer = NULL;
444 #if ISF_BUILD_CANDIDATE_UI
445 static Ecore_Timer *_candidate_hide_timer = NULL;
446 #endif /* CANDIDATE */
447 static Ecore_Timer *_ise_hide_timer = NULL;
450 static Ecore_X_Window _ise_window = 0;
451 static Ecore_X_Window _app_window = 0;
452 static Ecore_X_Window _control_window = 0;
453 static Ecore_X_Window _input_win = 0;
456 #ifdef HAVE_PKGMGR_INFO
457 static package_manager_h pkgmgr = NULL;
458 static VectorPairStringUint32 g_pkgids_to_be_uninstalled;
459 static Ecore_Timer *g_release_uninstalled_ime_info_timer = NULL;
460 static String g_stopped_helper_pkgid = "";
461 static Ecore_Timer *g_start_default_helper_timer = NULL;
462 static VectorPairStringUint32 g_pkgids_to_be_updated_and_installed;
463 static String g_updated_helper_pkgid = "";
466 static bool _launch_ise_on_request = false;
467 static bool _soft_keyboard_launched = false;
468 static bool _focus_in = false;
470 #if ISF_BUILD_CANDIDATE_UI
471 static bool candidate_expanded = false;
472 static int _candidate_image_count = 0;
473 static int _candidate_text_count = 0;
474 static int _candidate_pop_image_count = 0;
475 static int candidate_image_height = 38;
476 static int candidate_play_image_width_height = 19;
478 static const int CANDIDATE_TEXT_OFFSET = 2;
480 static double _app_scale = 1.0;
481 static double _system_scale = 1.0;
482 #endif /* CANDIDATE */
484 #ifdef HAVE_NOTIFICATION
485 static NotificationData hwkbd_module_noti = {"Input detected from hardware keyboard", "Tap to use virtual keyboard", ISF_KEYBOARD_ICON_FILE, "", 0};
486 static NotificationData ise_selector_module_noti = {"Select input method", NULL, "", "", 0};
489 #if ISF_BUILD_CANDIDATE_UI
491 static tts_h _tts = NULL;
495 static bool feedback_initialized = false;
497 #endif /* CANDIDATE */
499 static E_DBus_Connection *edbus_conn;
500 static E_DBus_Signal_Handler *edbus_handler;
502 #if ENABLE_REMOTE_INPUT
503 static Remote_Input* remote_input_impl = NULL;
504 static bool launch_remote_input = false;
507 #if ISF_BUILD_CANDIDATE_UI
509 static Ecore_Event_Handler *_candidate_show_handler = NULL;
511 #endif /* CANDIDATE */
513 static String ime_selector_app = "";
514 static String ime_list_app = "";
516 static Ecore_Timer *_ise_check_pid_alive_timer = NULL;
517 static const double _ise_check_pid_alive_time = 1.0f;
518 static String _ise_check_pid_alive_uuid;
521 EMOJI_IMAGE_WIDTH = 0,
524 EMOJI_IMAGE_TAG_FLAG,
525 EMOJI_IMAGE_POP_FLAG,
532 int emoji_option[EMOJI_IMAGE_END];
535 /* This structure stores the geometry information reported by ISE */
538 bool valid; /* Whether this information is currently valid */
539 int angle; /* For which angle this information is useful */
540 struct rectinfo geometry; /* Geometry information */
543 static struct GeometryCache _ise_reported_geometry = {0, 0, {0, 0, 0, 0}};
544 static struct GeometryCache _portrait_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
545 static struct GeometryCache _landscape_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
548 static void get_input_window (void)
551 Ecore_X_Atom atom = 0;
553 if (_input_win == 0) {
554 atom = ecore_x_atom_get (E_PROP_DEVICEMGR_INPUTWIN);
555 win_ret = ecore_x_window_prop_window_get (ecore_x_window_root_first_get (), atom, &_input_win, 1);
556 if (_input_win == 0 || win_ret < 1) {
557 LOGW ("Input window is NULL!");
559 ecore_x_event_mask_set (_input_win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
565 static int pkgmgr_get_appinfo (const char *appid, pkgmgrinfo_appinfo_h *handle)
568 /* Try to get in global packages */
569 ret = pkgmgrinfo_appinfo_get_appinfo (appid, handle);
570 if (ret != PMINFO_R_OK) {
571 LOGW ("[pkgmgrinfo_appinfo_get_appinfo] appid : '%s', ret : %d", appid, ret);
572 /* Try to get in user packages */
573 ret = pkgmgrinfo_appinfo_get_usr_appinfo (appid, getuid (), handle);
574 if (ret != PMINFO_R_OK)
575 LOGW ("[pkgmgrinfo_appinfo_get_usr_appinfo] appid : '%s', ret : %d", appid, ret);
581 static void usb_keyboard_signal_cb (void *data, DBusMessage *msg)
591 if (dbus_message_is_signal (msg, HOST_INTERFACE_NAME, HOST_KEYBOARD_SIGNAL) == 0) {
592 LOGW ("HOST_KEYBOARD_SIGNAL");
596 dbus_error_init (&err);
598 if (dbus_message_get_args (msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) {
599 LOGW ("DBUS_TYPE_INVALID");
605 if (!strncmp (str, HOST_ADDED, strlen (HOST_ADDED))) {
610 if (!strncmp (str, HOST_REMOVED, strlen (HOST_REMOVED))) {
611 LOGD ("HOST_REMOVED");
612 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
613 change_keyboard_mode (TOOLBAR_HELPER_MODE);
618 LOGW ("ERROR: msg (%s) is improper", str);
621 static void unregister_edbus_signal_handler (void)
624 LOGD ("unregister signal handler for keyboard");
626 e_dbus_signal_handler_del (edbus_conn, edbus_handler);
627 edbus_handler = NULL;
629 e_dbus_connection_close (edbus_conn);
635 static int register_edbus_signal_handler (void)
640 while (e_dbus_init () == 0) {
647 edbus_conn = e_dbus_bus_get (DBUS_BUS_SYSTEM);
649 LOGW ("edbus connection fail");
653 edbus_handler = e_dbus_signal_handler_add (edbus_conn, NULL, HOST_OBJECT_PATH, HOST_INTERFACE_NAME, HOST_KEYBOARD_SIGNAL, usb_keyboard_signal_cb, NULL);
654 if (!edbus_handler) {
655 LOGW ("cannot register signal");
659 LOGD ("Success edbus register");
664 #ifdef HAVE_NOTIFICATION
665 static void delete_notification (NotificationData *noti_data)
667 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
669 if (!_MOBILE) return;
671 if (noti_data->noti_id != 0) {
672 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
673 LOGD ("deleted notification : %s", noti_data->launch_app.c_str ());
674 noti_data->noti_id = 0;
678 static void create_notification (NotificationData *noti_data)
680 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
682 notification_h notification = NULL;
685 if (!_MOBILE) return;
687 if (noti_data->noti_id != 0) {
688 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
689 noti_data->noti_id = 0;
692 notification = notification_create (NOTIFICATION_TYPE_ONGOING);
693 if (notification != NULL) {
694 notification_set_pkgname (notification, "isf-panel-efl");
695 notification_set_layout (notification, NOTIFICATION_LY_ONGOING_EVENT);
697 notification_set_image (notification, NOTIFICATION_IMAGE_TYPE_ICON, noti_data->icon);
699 if (noti_data->title)
700 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_TITLE, _(noti_data->title), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
702 if (noti_data->content)
703 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_CONTENT, _(noti_data->content), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
705 notification_set_display_applist (notification, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
707 app_control_h service = NULL;
708 if (app_control_create (&service) == APP_CONTROL_ERROR_NONE) {
709 app_control_set_operation (service, APP_CONTROL_OPERATION_DEFAULT);
710 app_control_set_app_id (service, noti_data->launch_app.c_str ());
712 notification_set_launch_option (notification, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)service);
713 ret = notification_insert (notification, ¬i_data->noti_id);
714 if (ret != NOTIFICATION_ERROR_NONE) {
715 LOGW ("Failed to insert notification. error code : %d", ret);
717 app_control_destroy (service);
720 LOGW ("Failed to create appcontrol");
722 notification_free (notification);
725 LOGW ("Failed to create notification");
728 #endif /* HAVE_NOTIFICATION */
730 #if ISF_BUILD_CANDIDATE_UI
731 static bool tokenize_tag (const String& str, struct image *image_token)
733 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
734 if (str.length () <= 0) {
735 LOGW ("str is empty!!!");
739 char **tag_str = NULL;
741 tag_str = eina_str_split (str.c_str (), "\u3013", 0);
746 for (i = 0; tag_str [i]; i++) {
748 if (str.length () == strlen (tag_str[i])) {
758 image_token->path = String (tag_str[i]);
760 if (i - 1 < EMOJI_IMAGE_END)
761 image_token->emoji_option [i - 1] = atoi (tag_str[i]);
763 LOGW ("emoji option is more than EMOJI_IMAGE_END!!!");
775 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)
777 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
779 struct image image_data;
780 int object_width = 0, text_width = 0, image_width = 0, image_height = 0, max_width = 0, button_width = 0;
782 int image_get_width = 0, image_get_height = 0;
783 char image_key [10] = {0, };
784 char **splited_string = NULL;
785 char **sub_splited_string = NULL;
786 double image_rate = 0.0;
787 bool tokenize_result = false;
788 bool candidate_is_long = false;
790 Evas_Object *candidate_object_table = NULL;
791 Evas_Object *candidate_object_table_bg_rect = NULL;
792 Evas_Object *candidate_left_padding = NULL;
794 candidate_object_table = elm_table_add (parent);
796 candidate_left_padding = evas_object_rectangle_add (evas_object_evas_get (parent));
797 evas_object_size_hint_weight_set (candidate_left_padding, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
798 evas_object_size_hint_align_set (candidate_left_padding, EVAS_HINT_FILL, EVAS_HINT_FILL);
799 evas_object_size_hint_min_set (candidate_left_padding, _blank_width, 1);
800 evas_object_color_set (candidate_left_padding, 0, 0, 0, 0);
801 elm_table_pack (candidate_object_table, candidate_left_padding, 0, 0, _blank_width, 1);
802 evas_object_show (candidate_left_padding);
804 object_width += _blank_width;
805 if (item_num > 1 && item_index == 0)
806 button_width = 92 * _width_rate;
810 splited_string = eina_str_split (str.c_str (), "\uE000", 0);
811 if (splited_string) {
812 for (i = 0; splited_string [i]; i++) {
813 if (candidate_is_long)
815 sub_splited_string = eina_str_split (splited_string [i], "\uE001", 0);
816 if (sub_splited_string) {
817 for (j = 0; sub_splited_string [j]; j++) {
818 if (candidate_is_long)
820 tokenize_result = tokenize_tag (sub_splited_string [j], &image_data);
821 if (tokenize_result && _candidate_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
822 _candidate_image [_candidate_image_count] = elm_image_add (parent);
823 snprintf (image_key, sizeof (image_key), "%d", _candidate_image_count);
824 elm_image_file_set (_candidate_image [_candidate_image_count], image_data.path.c_str (), image_key);
825 elm_image_animated_set (_candidate_image [_candidate_image_count], EINA_TRUE);
826 elm_image_animated_play_set (_candidate_image [_candidate_image_count], EINA_TRUE);
827 elm_image_object_size_get (_candidate_image [_candidate_image_count], &image_get_width, &image_get_height);
828 LOGD ("image_path=%s, key=%s", image_data.path.c_str (), image_key);
830 if (image_get_height > image_get_width)
831 image_rate = ((double)candidate_image_height / (double)image_get_width);
833 image_rate = ((double)candidate_image_height / (double)image_get_height);
835 image_width = (int)((double)image_get_width * image_rate);
836 image_height = candidate_image_height;
838 if (_candidate_angle == 90 || _candidate_angle == 270)
839 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
841 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
843 if (image_width > max_width) {
844 Evas_Object *candidate_end = edje_object_add (evas_object_evas_get (parent));
845 edje_object_file_set (candidate_end, _candidate_edje_file.c_str (), _candidate_name.c_str ());
846 evas_object_show (candidate_end);
847 edje_object_part_text_set (candidate_end, "candidate", "...");
848 edje_object_scale_set (_candidate_text [_candidate_text_count], _height_rate);
850 text_width = max_width;
851 evas_object_size_hint_min_set (candidate_end, text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
852 if (HighLight || SetBack) {
853 set_highlight_color (candidate_end, ForeGround, BackGround, SetBack);
855 elm_table_pack (candidate_object_table, candidate_end, object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
856 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
858 if (_candidate_image [_candidate_image_count]) {
859 evas_object_del (_candidate_image [_candidate_image_count]);
860 _candidate_image [_candidate_image_count] = NULL;
862 candidate_is_long = true;
866 evas_object_resize (_candidate_image [_candidate_image_count], image_width, image_height);
867 evas_object_show (_candidate_image [_candidate_image_count]);
868 evas_object_size_hint_min_set (_candidate_image [_candidate_image_count], image_width, image_height);
870 elm_table_pack (candidate_object_table, _candidate_image [_candidate_image_count], object_width, 1, image_width, image_height);
871 object_width += image_width;
872 _candidate_image_count++;
874 if (image_data.emoji_option [EMOJI_IMAGE_POP_FLAG] == 1 && image_width > 0 && _candidate_pop_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
875 _candidate_pop_image [_candidate_pop_image_count] = elm_image_add (parent);
876 elm_image_file_set (_candidate_pop_image [_candidate_pop_image_count], ISF_POP_PLAY_ICON_FILE, image_key);
877 evas_object_resize (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
878 evas_object_show (_candidate_pop_image [_candidate_pop_image_count]);
879 evas_object_size_hint_min_set (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
881 elm_table_pack (candidate_object_table, _candidate_pop_image [_candidate_pop_image_count],
882 object_width - candidate_play_image_width_height, image_height - candidate_play_image_width_height - 2,
883 candidate_play_image_width_height, candidate_play_image_width_height);
885 _candidate_pop_image_count++;
888 } else if (strlen (sub_splited_string [j]) > 0 && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
889 _candidate_text [_candidate_text_count] = edje_object_add (evas_object_evas_get (parent));
890 edje_object_file_set (_candidate_text [_candidate_text_count], _candidate_edje_file.c_str (), _candidate_name.c_str ());
891 evas_object_show (_candidate_text [_candidate_text_count]);
892 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", sub_splited_string [j]);
893 edje_object_text_class_set (_candidate_text [_candidate_text_count], "tizen",
894 _candidate_font_name.c_str (), _candidate_font_size);
895 evas_object_text_text_set (_tmp_candidate_text, sub_splited_string [j]);
896 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &text_width, NULL);
898 if (_candidate_angle == 90 || _candidate_angle == 270)
899 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
901 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
903 if (text_width > max_width) {
904 candidate_is_long = true;
905 /* In order to avoid overlap issue, calculate show_string */
906 String show_string = String (sub_splited_string [j]);
907 int show_length = text_width;
908 while (show_length > max_width && show_string.length () > 1) {
909 show_string = show_string.substr (0, show_string.length () - 1);
910 evas_object_text_text_set (_tmp_candidate_text, (show_string + String ("...")).c_str ());
911 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &show_length, NULL);
913 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", (show_string + String ("...")).c_str ());
914 text_width = max_width;
917 evas_object_size_hint_min_set (_candidate_text [_candidate_text_count], text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
918 if (HighLight || SetBack) {
919 set_highlight_color (_candidate_text [_candidate_text_count], ForeGround, BackGround, SetBack);
921 elm_table_pack (candidate_object_table, _candidate_text [_candidate_text_count], object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
922 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
923 _candidate_text_count++;
929 if (splited_string [0])
930 free (splited_string [0]);
932 free (splited_string);
935 if (sub_splited_string) {
936 if (sub_splited_string [0])
937 free (sub_splited_string [0]);
939 free (sub_splited_string);
942 *total_width = object_width + _blank_width;
944 candidate_object_table_bg_rect = edje_object_add (evas_object_evas_get (parent));
945 edje_object_file_set (candidate_object_table_bg_rect, _candidate_edje_file.c_str (), "candidate_object_table");
946 evas_object_size_hint_weight_set (candidate_object_table_bg_rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
947 evas_object_size_hint_align_set (candidate_object_table_bg_rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
948 evas_object_size_hint_min_set (candidate_object_table_bg_rect, *total_width, _item_min_height);
949 elm_table_pack (candidate_object_table, candidate_object_table_bg_rect, 0, 0, *total_width, _item_min_height);
950 evas_object_show (candidate_object_table_bg_rect);
952 evas_object_size_hint_align_set (candidate_object_table, EVAS_HINT_FILL, EVAS_HINT_FILL);
953 evas_object_size_hint_weight_set (candidate_object_table, EVAS_HINT_EXPAND, 0.0);
955 return candidate_object_table;
957 #endif /* CANDIDATE */
959 /////////////////////////////////////////////////////////////////////////////
960 // Implementation of internal functions.
961 /////////////////////////////////////////////////////////////////////////////
963 * @brief Print system time point for panel performance.
965 * @param strInfo The output information.
967 static void check_time (const char *strInfo)
969 gettime (_clock_start, strInfo);
970 ISF_LOG ("%s ppid=%d pid=%d\n", strInfo, getppid (), getpid ());
974 * @brief Flush memory for elm.
978 static void flush_memory (void)
980 #if ISF_BUILD_CANDIDATE_UI
981 elm_cache_all_flush ();
986 #if ISF_BUILD_CANDIDATE_UI
988 * @brief Get ISE geometry information.
989 * Returns the "expected" ISE geometry when kbd_state is ON, otherwise w/h set to 0
991 * @param info The data is used to store ISE position and size.
992 * @param kbd_state The keyboard state.
994 static struct rectinfo get_ise_geometry ()
996 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
998 struct rectinfo info = {0, 0, 0, 0};
1002 Ecore_X_Window gnb_win = efl_get_global_navigation_window ();
1004 ecore_x_window_size_get (gnb_win, &w, &h);
1007 int win_w = _screen_width, win_h = _screen_height;
1008 int angle = (_ise_angle == -1) ? efl_get_app_window_angle () : _ise_angle;
1011 /* The height of global navigation bar */
1014 if (angle == 90 || angle == 270) {
1015 win_w = _screen_height;
1016 win_h = _screen_width;
1021 /* If we have geometry reported by ISE, use the geometry information */
1022 if (_ise_reported_geometry.valid && _ise_reported_geometry.angle == angle) {
1023 info = _ise_reported_geometry.geometry;
1024 /* But still, if the current ISE is not in SHOW state, set w/h to 0 */
1025 if (_ise_state != WINDOW_STATE_SHOW) {
1026 info.pos_y = (win_h > win_w) ? win_h : win_w;
1031 /* READ ISE's SIZE HINT HERE */
1034 int pos_x, pos_y, width, height;
1035 if (ecore_x_e_window_rotation_geometry_get (_ise_window, angle,
1036 &pos_x, &pos_y, &width, &height)) {
1040 if (angle == 90 || angle == 270) {
1041 info.width = height;
1042 info.height = width;
1045 info.height = height;
1048 info.pos_x = (int)info.width > win_w ? 0 : (win_w - info.width) / 2;
1049 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
1051 info.pos_y = (win_h > win_w) ? win_h : win_w;
1055 if (_ise_state == WINDOW_STATE_SHOW) {
1056 info.pos_y = win_h - info.height - gnb_height;
1058 info.pos_y = (win_h > win_w) ? win_h : win_w;
1064 LOGD ("angle : %d, w_angle : %d, mode : %d, Geometry : %d %d %d %d",
1066 _info_manager->get_current_toolbar_mode (),
1067 info.pos_x, info.pos_y, info.width, info.height);
1076 // FIXME: Get the ISE's SIZE.
1084 _ise_width = info.width;
1085 _ise_height = info.height;
1089 #endif /* CANDIDATE */
1093 * @brief Set keyboard geometry for autoscroll.
1094 * This includes the ISE geometry together with candidate window
1096 * @param kbd_state The keyboard state.
1098 static void set_keyboard_geometry_atom_info (Ecore_X_Window window, struct rectinfo ise_rect)
1100 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1102 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
1105 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1106 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1107 ise_rect.width = _candidate_width;
1108 ise_rect.height = _candidate_height;
1110 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
1111 ise_rect.width = _soft_candidate_width;
1112 ise_rect.height = _soft_candidate_height;
1115 int angle = efl_get_app_window_angle ();
1116 if (angle == 90 || angle == 270)
1117 ise_rect.pos_y = _screen_width - ise_rect.height;
1119 ise_rect.pos_y = _screen_height - ise_rect.height;
1121 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1122 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1123 _candidate_valid_height = ui_candidate_get_valid_height ();
1124 if ((_candidate_height - _candidate_valid_height) > _ise_height) {
1125 _candidate_valid_height = _candidate_height;
1126 ise_rect.pos_y = ise_rect.pos_y + ise_rect.height - _candidate_height;
1127 ise_rect.height = _candidate_height;
1129 ise_rect.pos_y -= _candidate_valid_height;
1130 ise_rect.height += _candidate_valid_height;
1136 ecore_x_e_illume_keyboard_geometry_set (window, ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1137 LOGD ("KEYBOARD_GEOMETRY_SET : %d %d %d %d", ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1138 SCIM_DEBUG_MAIN (3) << " KEYBOARD_GEOMETRY x=" << ise_rect.pos_x << " y=" << ise_rect.pos_y
1139 << " width=" << ise_rect.width << " height=" << ise_rect.height << "\n";
1141 /* even the kbd_state is OFF, consider the keyboard is still ON if we have candidate opened */
1142 if (ise_rect.width == 0 && ise_rect.height == 0) {
1143 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1145 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1147 if (_ise_angle == 0 || _ise_angle == 180) {
1148 _portrait_recent_ise_geometry.valid = true;
1149 _portrait_recent_ise_geometry.geometry = ise_rect;
1152 _landscape_recent_ise_geometry.valid = true;
1153 _landscape_recent_ise_geometry.geometry = ise_rect;
1160 * @brief Get ISE index according to uuid.
1162 * @param uuid The ISE uuid.
1164 * @return The ISE index
1166 static unsigned int get_ise_index (const String uuid)
1168 unsigned int index = 0;
1169 if (uuid.length () > 0) {
1170 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1171 if (uuid == _ime_info[i].appid) {
1181 static void set_keyboard_engine (String active_uuid)
1183 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
1184 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
1185 if (active_uuid != keyboard_uuid) {
1186 _info_manager->change_factory (active_uuid);
1187 _config->write (IMENGINE_KEY, active_uuid);
1192 static void _update_ime_info(void)
1194 std::vector<String> ise_langs;
1197 isf_pkg_select_all_ime_info_db(_ime_info);
1199 /* Update _groups */
1201 for (size_t i = 0; i < _ime_info.size (); ++i) {
1202 scim_split_string_list(ise_langs, _ime_info[i].languages);
1203 for (size_t j = 0; j < ise_langs.size (); j++) {
1204 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
1205 _groups[ise_langs[j]].push_back (i);
1211 static void _initialize_ime_info (void)
1213 std::vector<ImeInfoDB>::iterator iter;
1214 VectorPairStringUint32 ime_on_off;
1215 // Store is_enabled values of each keyboard
1216 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1217 if (iter->mode == TOOLBAR_HELPER_MODE) {
1218 ime_on_off.push_back (std::make_pair (iter->appid, iter->is_enabled));
1221 // Delete the whole ime_info DB and reload
1222 isf_db_delete_ime_info ();
1223 _update_ime_info ();
1224 // Restore is_enabled value to valid keyboards
1225 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1226 if (iter->mode == TOOLBAR_HELPER_MODE) {
1227 for (VectorPairStringUint32::iterator it = ime_on_off.begin (); it != ime_on_off.end (); it++) {
1228 if (it->first.compare (iter->appid) == 0) {
1229 if (it->second != iter->is_enabled) {
1230 iter->is_enabled = it->second;
1231 isf_db_update_is_enabled_by_appid (iter->appid.c_str (), static_cast<bool>(iter->is_enabled));
1233 ime_on_off.erase (it);
1241 #ifdef HAVE_PKGMGR_INFO
1243 * @brief Insert or update ime_info data with pkgid.
1245 * @param pkgid pkgid to insert/update ime_info table.
1247 * @return 1 on successful insert, 2 on successful update, -1 if pkgid is not IME package, otherwise return 0.
1249 static int _isf_insert_ime_info_by_pkgid(const char *pkgid)
1252 pkgmgrinfo_pkginfo_h handle = NULL;
1253 int result = 0; // 0: not IME, 1: Inserted, 2: Updated (because of the same appid)
1254 uid_t uid = getpid ();
1258 LOGW ("pkgid is null.");
1262 /* Try to get in global packages */
1263 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &handle);
1264 if (ret != PMINFO_R_OK) {
1265 /* Try to get in user packages */
1266 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, uid, &handle);
1267 if (ret != PMINFO_R_OK) {
1268 LOGW ("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d", pkgid, ret);
1277 /* Try to get in user packages */
1278 ret = pkgmgrinfo_appinfo_get_usr_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result, uid);
1281 /* Try to get in global packages */
1282 ret = pkgmgrinfo_appinfo_get_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result);
1285 if (ret != PMINFO_R_OK) {
1286 LOGW ("Failed to call %s failed(%d)", user ? "pkgmgrinfo_appinfo_get_usr_list" : "pkgmgrinfo_appinfo_get_list", ret);
1293 pkgmgrinfo_pkginfo_destroy_pkginfo (handle);
1299 * @brief Timer to start initial Helper ISE if the active (selected) 3rd party keyboard is uninstalled.
1301 * @param data User data
1303 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1304 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1306 static Eina_Bool _start_default_helper_timer(void *data)
1308 std::vector<String> total_appids;
1309 std::vector<ImeInfoDB>::iterator it;
1310 VectorPairStringUint32::iterator iter;
1312 /* Let panel know that ISE is deleted... */
1313 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1314 total_appids.push_back(it->appid);
1316 if (total_appids.size() > 0)
1317 _info_manager->update_ise_list (total_appids);
1319 LOGD ("Try to start the initial helper");
1320 set_active_ise(_initial_ise_uuid, true);
1322 for (iter = g_pkgids_to_be_uninstalled.begin (); iter != g_pkgids_to_be_uninstalled.end (); iter++) {
1323 if (iter->first.compare(g_stopped_helper_pkgid) == 0) {
1324 g_pkgids_to_be_uninstalled.erase (iter);
1328 g_stopped_helper_pkgid = "";
1330 g_start_default_helper_timer = NULL;
1331 return ECORE_CALLBACK_CANCEL;
1335 * @brief Timer to release uninstalled IME related info; g_pkgids_to_be_uninstalled has appid and is_enabled.
1337 * @param data User data
1339 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1340 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1342 static Eina_Bool _release_uninstalled_pkginfo_timer(void *data)
1344 g_pkgids_to_be_uninstalled.clear ();
1345 g_release_uninstalled_ime_info_timer = NULL;
1346 return ECORE_CALLBACK_CANCEL;
1350 * @brief Called when the package is installed, uninstalled or updated, and the progress of the request to the package manager changes.
1352 * @param[in] type The type of the package to be installed, uninstalled or updated
1353 * @param[in] package The name of the package to be installed, uninstalled or updated
1354 * @param[in] event_type The type of the request to the package manager
1355 * @param[in] event_state The current state of the request to the package manager
1356 * @param[in] progress The progress for the request that is being processed by the package manager \n
1357 * The range of progress is from 0 to 100
1358 * @param[in] error The error code when the package manager failed to process the request
1359 * @param[in] user_data The user data passed from package_manager_set_event_cb()
1360 * @see package_manager_set_event_cb()
1361 * @see package_manager_unset_event_cb()
1363 INFO: Package install/update/uninstall scenario
1364 Install and Uninstall are obviously simple.
1365 Install: just INSTALL
1366 Uninstall: just UNINSTALL
1367 Update package (change the source codes in IME project and Run As again), there are four scenarios:
1370 2. UNINSTALL -> INSTALL
1371 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1372 and change Application ID in tizen-manifest.xml file and Run As.
1373 3. UPDATE -> INSTALL
1374 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1375 and change Application ID in tizen-manifest.xml file and Run As.
1376 At UPDATE event, pkgid (package parameter) is invalid...
1378 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1379 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1381 If multiple packages (including non-IME pkgs) are uninstalled and installed; Z300H UPS (ultra power saving) mode scenario.
1382 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
1384 Assuming IMEngine won't be changed through this. IMEngine might have multiple appids for one pkgid.
1385 Assuming preinstalled IME won't be changed through this.
1387 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)
1389 String current_ime_appid; // now appid is uuid.
1390 std::vector<String> appids;
1391 std::vector<String> total_appids;
1392 std::vector<ImeInfoDB>::iterator it;
1393 std::vector<String>::iterator it2;
1394 VectorPairStringUint32::iterator it3;
1397 if (!package || !type)
1400 if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
1401 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1402 LOGD ("type=%s package=%s event_type=UPDATE event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1404 ret = _isf_insert_ime_info_by_pkgid (package); // If package is not IME, -1 would be returned.
1405 if (ret == 1) { // In case the package is updated with the changed appid. In this case, there will be two IMEs
1406 ret = isf_db_select_appids_by_pkgid (package, appids);
1408 if (_ime_info.size () > 0 && _ime_info [get_ise_index (appids.front ())].is_enabled)
1409 isf_db_update_is_enabled_by_appid (appids.back ().c_str (), true);
1410 isf_db_delete_ime_info_by_appid (appids.front ().c_str ());
1413 _update_ime_info ();
1415 /* Let panel know that ise list is changed... */
1416 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1417 total_appids.push_back(it->appid);
1419 if (total_appids.size() > 0)
1420 _info_manager->update_ise_list (total_appids);
1422 if (ret > 1 && _soft_keyboard_launched) { // If the previous appid of pkgid is the current IME, restart it with new appid.
1423 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1424 if (current_ime_appid.compare (appids.front ()) == 0) {
1425 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1426 _info_manager->hide_helper (current_ime_appid);
1427 _info_manager->stop_helper (current_ime_appid);
1428 LOGD ("Start IME(%s)", appids.back ().c_str ());
1429 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids.back ());
1430 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1431 _info_manager->start_helper (appids.back ());
1435 else if (ret == 2) { // In case IME package is just updated...
1436 _update_ime_info ();
1438 if (_soft_keyboard_launched) { // If package is the current IME, restart it.
1439 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1440 if (isf_db_select_appids_by_pkgid(package, appids)) {
1441 if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the current ISE package is updated, restart it.
1442 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1443 if (it->mode == TOOLBAR_HELPER_MODE && it->appid.compare(current_ime_appid) == 0) { // Make sure it's Helper ISE...
1444 LOGD ("Restart IME(%s)", current_ime_appid.c_str ());
1445 _info_manager->hide_helper (current_ime_appid);
1446 _info_manager->stop_helper (current_ime_appid);
1447 _info_manager->start_helper (current_ime_appid);
1455 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...
1456 if (isf_db_select_appids_by_pkgid(package, appids) == 1) {
1457 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1458 if (it->pkgid.compare(package) == 0) {
1459 g_pkgids_to_be_updated_and_installed.push_back (std::make_pair (it->pkgid, it->is_enabled));
1463 if (it == _ime_info.end ()) // Probably not going to happen.
1464 g_pkgids_to_be_updated_and_installed.push_back(std::make_pair (String(package), 0));
1466 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1467 if (_soft_keyboard_launched && std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the updated IME is the current ISE...
1468 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1469 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1470 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1471 _info_manager->hide_helper (current_ime_appid);
1472 _info_manager->stop_helper (current_ime_appid);
1473 _soft_keyboard_launched = false;
1474 g_updated_helper_pkgid = package;
1480 if (appids.size () > 0) // Probably appids size is 1.
1481 LOGD ("Delete IME(%s)", appids[0].c_str ());
1482 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1485 /* Let panel know that ise is deleted... */
1486 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1487 total_appids.push_back(it->appid);
1489 if (total_appids.size() > 0)
1490 _info_manager->update_ise_list (total_appids);
1494 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1499 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL) {
1500 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1501 LOGD ("type=%s package=%s event_type=INSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1503 ///////////////// UNINSTALL -> INSTALL and if the uninstalled IME is reinstalled /////////////////
1504 if (g_stopped_helper_pkgid.compare(package) == 0 && g_start_default_helper_timer) {
1505 LOGD ("Cancel timer to start the default IME");
1506 ecore_timer_del(g_start_default_helper_timer);
1507 g_start_default_helper_timer = NULL;
1508 g_stopped_helper_pkgid = "";
1510 ret = _isf_insert_ime_info_by_pkgid(package);
1512 /* Find appid by pkgid. There might be multiple appid, but assume Helper always has one appid.
1513 And appid can be changed, but pkgid won't be changed. */
1514 ret = isf_db_select_appids_by_pkgid(package, appids);
1515 if (ret == 1 && appids.size () == 1) {
1516 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1517 if (it3->first.compare(package) == 0) {
1519 isf_db_update_is_enabled_by_appid(appids[0].c_str (), (bool)it3->second);
1523 /* Let panel know that ise is added... */
1524 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1525 total_appids.push_back(it->appid);
1527 if (total_appids.size() > 0)
1528 _info_manager->update_ise_list (total_appids);
1530 LOGD ("Restart IME(%s)", appids[0].c_str ());
1531 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids[0]);
1532 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1533 _info_manager->start_helper (appids[0]);
1534 _soft_keyboard_launched = true;
1536 g_pkgids_to_be_uninstalled.erase (it3);
1542 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1546 /* Let panel know that ise is added... */
1547 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1548 total_appids.push_back(it->appid);
1550 if (total_appids.size() > 0)
1551 _info_manager->update_ise_list (total_appids);
1555 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1558 else { // If new package is installed...
1559 ret = _isf_insert_ime_info_by_pkgid(package); // If package is not IME, -1 would be returned.
1560 if (ret > 0) { // In case package is IME...
1561 ///////////////// INSTALL /////////////////
1564 /* Let panel know that ise is added... */
1565 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1566 total_appids.push_back(it->appid);
1568 if (total_appids.size() > 0)
1569 _info_manager->update_ise_list (total_appids);
1570 ///////////////// END /////////////////
1572 /* For example, the following happens if appid is changed in IME project and Run As again. The appid would be changed this time.
1573 Assuming only Helper (3rd party) might be installed after update or uninstall and there is one appid per each pkgid...*/
1575 ///////////////// UPDATE -> INSTALL /////////////////
1576 for (it3 = g_pkgids_to_be_updated_and_installed.begin (); it3 != g_pkgids_to_be_updated_and_installed.end (); it3++) {
1577 if (it3->first.compare(package) == 0) {
1579 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1580 if (it->pkgid.compare(package) == 0) {
1581 it->is_enabled = it3->second;
1582 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1587 g_pkgids_to_be_updated_and_installed.erase (it3);
1591 if (g_updated_helper_pkgid.compare(package) == 0) {
1592 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1593 if (it->mode == TOOLBAR_HELPER_MODE && it->pkgid.compare(package) == 0) {
1594 LOGD ("Start IME(%s)", it->appid.c_str ());
1595 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), it->appid);
1596 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1597 _info_manager->start_helper (it->appid);
1598 _soft_keyboard_launched = true;
1602 g_updated_helper_pkgid = "";
1605 ///////////////// END /////////////////
1607 ///////////////// UNINSTALL -> INSTALL /////////////////
1608 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1609 if (it3->first.compare(package) == 0) {
1611 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1612 if (it->pkgid.compare(package) == 0) {
1613 it->is_enabled = it3->second;
1614 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1619 g_pkgids_to_be_uninstalled.erase (it3);
1623 ///////////////// END /////////////////
1625 else if (ret == 0) {
1626 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1631 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL) {
1632 switch (event_state) {
1633 case PACKAGE_MANAGER_EVENT_STATE_STARTED:
1634 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=STARTED progress=%d error=%d", type, package, progress, error);
1636 // Need to check if there is "http://tizen.org/category/ime" category; it can be done by comparing pkgid with ime_info db.
1638 if (_ime_info.size() == 0)
1641 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1642 if (it->pkgid.compare(package) == 0 && it->is_preinstalled == 0) { // Ignore if it's preinstalled IME and IMEngine.
1649 // 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.
1650 LOGD ("%s for pkgid(\"%s\") is about to be deleted", it->appid.c_str (), package);
1651 g_pkgids_to_be_uninstalled.push_back(std::make_pair (String(package), it->is_enabled));
1653 if (_soft_keyboard_launched && isf_db_select_appids_by_pkgid(package, appids)) {
1654 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1655 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.
1656 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1657 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1658 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1659 _info_manager->hide_helper (current_ime_appid);
1660 _info_manager->stop_helper (current_ime_appid);
1661 _soft_keyboard_launched = false;
1662 g_stopped_helper_pkgid = package;
1672 case PACKAGE_MANAGER_EVENT_STATE_COMPLETED:
1673 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1675 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1676 if (it3->first.compare(package) == 0) {
1677 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1681 if (g_stopped_helper_pkgid.compare(package) == 0) { // If the uninstalled ISE is the current ISE, start the initial helper ISE by timer.
1682 if (g_start_default_helper_timer)
1683 ecore_timer_del(g_start_default_helper_timer);
1684 LOGD ("Add timer to start the default IME");
1685 g_start_default_helper_timer = ecore_timer_add(3.0, _start_default_helper_timer, NULL);
1687 else { // Need to clean up g_pkgids_to_be_uninstalled info unless the same package is installed again; e.g., UNINSTALL -> INSTALL case.
1688 if (g_release_uninstalled_ime_info_timer)
1689 ecore_timer_del(g_release_uninstalled_ime_info_timer);
1690 LOGD ("Add timer to release uninstalled IME pkg info");
1691 g_release_uninstalled_ime_info_timer = ecore_timer_add(7.0, _release_uninstalled_pkginfo_timer, NULL);
1694 /* Let panel know that ise is deleted... */
1695 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1696 total_appids.push_back(it->appid);
1698 if (total_appids.size() > 0)
1699 _info_manager->update_ise_list (total_appids);
1706 case PACKAGE_MANAGER_EVENT_STATE_FAILED:
1707 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=FAILED progress=%d error=%d", type, package, progress, error);
1709 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1710 if (it3->first.compare(package) == 0) {
1711 // Update _ime_info for sure...
1714 if (g_stopped_helper_pkgid.compare(package) == 0) {
1715 ret = isf_db_select_appids_by_pkgid(package, appids);
1716 if (ret == 1 && appids.size () == 1) {
1717 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1718 if (it->appid.compare(appids[0]) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1719 LOGD ("Restart IME(%s)", appids[0].c_str ());
1720 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1721 _info_manager->start_helper (appids[0]);
1722 _soft_keyboard_launched = true;
1728 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1730 g_stopped_helper_pkgid = "";
1733 g_pkgids_to_be_uninstalled.erase (it3);
1747 * @brief Set keyboard ISE.
1749 * @param uuid The keyboard ISE's uuid.
1751 * @return false if keyboard ISE change is failed, otherwise return true.
1753 static bool set_keyboard_ise (const String &uuid)
1755 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1757 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1759 if (TOOLBAR_HELPER_MODE == mode) {
1760 String pre_uuid = _info_manager->get_current_helper_uuid ();
1761 _info_manager->hide_helper (pre_uuid);
1762 _info_manager->stop_helper (pre_uuid);
1763 _soft_keyboard_launched = false;
1764 } else if (TOOLBAR_KEYBOARD_MODE == mode) {
1765 uint32 kbd_option = 0;
1766 String kbd_uuid, kbd_name;
1767 isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
1768 if (kbd_uuid == uuid)
1772 _info_manager->change_factory (uuid);
1774 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
1775 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
1781 * @brief Set helper ISE.
1783 * @param uuid The helper ISE's uuid.
1784 * @param launch_ise The flag for launching helper ISE.
1786 * @return false if helper ISE change is failed, otherwise return true.
1788 static bool set_helper_ise (const String &uuid, bool launch_ise)
1790 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1792 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1793 String pre_uuid = _info_manager->get_current_helper_uuid ();
1794 LOGD ("pre_appid=%s, appid=%s, launch_ise=%d, %d", pre_uuid.c_str(), uuid.c_str(), launch_ise, _soft_keyboard_launched);
1795 if (pre_uuid == uuid && _soft_keyboard_launched)
1798 if (TOOLBAR_HELPER_MODE == mode && pre_uuid.length () > 0 && _soft_keyboard_launched) {
1799 _info_manager->hide_helper (pre_uuid);
1800 _info_manager->stop_helper (pre_uuid);
1801 _soft_keyboard_launched = false;
1802 LOGD ("stop helper : %s", pre_uuid.c_str ());
1806 LOGD ("Start helper (%s)", uuid.c_str ());
1808 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1809 if (_info_manager->start_helper (uuid))
1810 _soft_keyboard_launched = true;
1812 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), uuid);
1817 #ifdef HAVE_PKGMGR_INFO
1818 int get_ime_app_list_cb (const pkgmgrinfo_appinfo_h handle, void *user_data)
1821 char *appid = NULL, *pkgid = NULL, *pkgtype = NULL, *exec = NULL, *label = NULL, *path = NULL;
1822 pkgmgrinfo_pkginfo_h pkginfo_handle = NULL;
1824 int *result = static_cast<int*>(user_data);
1826 if (result) /* in this case, need to check category */ {
1828 ret = pkgmgrinfo_appinfo_is_category_exist (handle, "http://tizen.org/category/ime", &exist);
1829 if (ret != PMINFO_R_OK || !exist) {
1835 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
1836 if (ret == PMINFO_R_OK)
1837 ime_db.appid = String (appid ? appid : "");
1839 LOGE ("pkgmgrinfo_appinfo_get_appid failed! error code=%d", ret);
1843 ime_db.iconpath = "";
1846 ret = pkgmgrinfo_appinfo_get_pkgid (handle, &pkgid);
1847 if (ret == PMINFO_R_OK)
1848 ime_db.pkgid = String (pkgid ? pkgid : "");
1850 LOGE ("pkgmgrinfo_appinfo_get_pkgid failed! error code=%d", ret);
1855 ret = pkgmgrinfo_appinfo_get_exec (handle, &exec);
1856 if (ret == PMINFO_R_OK)
1857 ime_db.exec = String (exec ? exec : "");
1859 LOGE ("pkgmgrinfo_appinfo_get_exec failed! error code=%d", ret);
1864 ret = pkgmgrinfo_appinfo_get_label (handle, &label);
1865 if (ret == PMINFO_R_OK)
1866 ime_db.label = String (label ? label : "");
1868 /* get pkgmgrinfo_pkginfo_h */
1869 /* Try to get in global packages */
1870 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &pkginfo_handle);
1871 if (ret != PMINFO_R_OK) {
1872 /* Try to get in user packages */
1873 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, getpid (), &pkginfo_handle);
1876 if (ret == PMINFO_R_OK && pkginfo_handle) {
1878 ret = pkgmgrinfo_pkginfo_get_type (pkginfo_handle, &pkgtype);
1880 if (ret == PMINFO_R_OK)
1881 ime_db.pkgtype = String (pkgtype ? pkgtype : "");
1883 ISF_SAVE_LOG ("pkgtype is not available!");
1884 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1889 pkgmgrinfo_pkginfo_get_root_path (pkginfo_handle, &path);
1892 ime_db.languages = "en";
1893 ime_db.display_lang = "";
1895 if (ime_db.pkgtype.compare ("rpm") == 0 && //1 Inhouse IMEngine ISE(IME)
1896 ime_db.exec.find ("scim-launcher") != String::npos) // Some IMEngine's pkgid doesn't have "ise-engine" prefix.
1898 ime_db.mode = TOOLBAR_KEYBOARD_MODE;
1900 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1901 + String (SCIM_PATH_DELIM_STRING) + String ("IMEngine");
1902 ime_db.module_name = ime_db.pkgid;
1903 ime_db.is_enabled = 1;
1904 ime_db.is_preinstalled = 1;
1905 ime_db.has_option = 0; // It doesn't matter. No option for IMEngine...
1908 ime_db.mode = TOOLBAR_HELPER_MODE;
1909 if (ime_db.pkgtype.compare ("rpm") == 0) //1 Inhouse Helper ISE(IME)
1912 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1914 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART;
1916 ime_db.module_name = ime_db.pkgid;
1918 String module_path = String (path) + String ("/lib");
1919 String fullpath = module_path + String (SCIM_PATH_DELIM_STRING) + ime_db.module_name + String (".so");
1921 if (stat (fullpath.c_str (), &st) < 0) {
1922 /* Not found in lib directory of package's root path */
1923 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1924 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1927 ime_db.module_path = module_path;
1930 ime_db.is_enabled = 1;
1931 ime_db.is_preinstalled = 1;
1932 ime_db.has_option = 1; // Let's assume the inhouse IME always has an option menu.
1934 else if (ime_db.pkgtype.compare ("wgt") == 0) //1 Download Web IME
1936 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1937 | SCIM_HELPER_NEED_SPOT_LOCATION_INFO | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1938 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1939 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1940 ime_db.module_name = String ("ise-web-helper-agent");
1941 if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1942 ime_db.is_enabled = 1;
1943 ime_db.is_preinstalled = 1;
1947 ime_db.is_enabled = 0;
1949 ime_db.is_enabled = 1;
1951 ime_db.is_preinstalled = 0;
1953 ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1955 else if (ime_db.pkgtype.compare ("tpk") == 0) //1 Download Native IME
1957 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1958 | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1960 ime_db.module_path = String (path) + String ("/lib");
1962 ime_db.module_path = String (tzplatform_getenv(TZ_SYS_RW_APP)) + ime_db.pkgid + String ("/lib");
1963 ime_db.module_name = String ("lib") + ime_db.exec.substr (ime_db.exec.find_last_of (SCIM_PATH_DELIM) + 1);
1964 if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1965 ime_db.is_enabled = 1;
1966 ime_db.is_preinstalled = 1;
1970 ime_db.is_enabled = 0;
1972 ime_db.is_enabled = 1;
1974 ime_db.is_preinstalled = 0;
1976 ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1979 LOGE ("Unsupported pkgtype(%s)", ime_db.pkgtype.c_str ());
1980 if (pkginfo_handle) {
1981 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1982 pkginfo_handle = NULL;
1988 _ime_info.push_back(ime_db);
1990 if (pkginfo_handle) {
1991 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1992 pkginfo_handle = NULL;
2000 * @brief Set active ISE.
2002 * @param uuid The ISE's uuid.
2003 * @param launch_ise The flag for launching helper ISE.
2005 * @return false if ISE change is failed, otherwise return true.
2007 static bool set_active_ise (const String &uuid, bool launch_ise)
2009 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2010 LOGD ("set ISE (%s) %d", uuid.c_str(), launch_ise);
2012 if (uuid.length () <= 0)
2015 bool ise_changed = false, valid = false;
2017 int ime_num = -1; /* If we failed retrieving the number of IMEs installed, assume we need to clear IME related settings */
2018 pkgmgrinfo_appinfo_filter_h handle;
2019 int ret = pkgmgrinfo_appinfo_filter_create(&handle);
2020 if (ret == PMINFO_R_OK) {
2021 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
2022 if (ret == PMINFO_R_OK) {
2023 ret = pkgmgrinfo_appinfo_filter_count(handle, &ime_num);
2024 if (ret != PMINFO_R_OK) {
2025 LOGW("pkgmgrinfo_appinfo_filter_count failed(%d)", ret);
2028 pkgmgrinfo_appinfo_filter_destroy (handle);
2031 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
2034 /* If the ime_num and _ime_info.size() are different, it is likely that the isf-panel-efl was
2035 terminated abnormally while processing package manager's install / uninstall events */
2036 LOGD("Checking whether db file needs to be re-created : %d %d", ime_num, _ime_info.size());
2037 if (ime_num != (int)_ime_info.size()) {
2039 isf_db_delete_ime_info();
2040 isf_pkg_reload_ime_info_db();
2041 isf_pkg_select_all_ime_info_db(_ime_info);
2044 if (_ime_info.size () == 0) {
2045 #ifdef HAVE_PKGMGR_INFO
2046 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
2047 if (ret == PMINFO_R_OK) {
2048 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
2049 if (ret == PMINFO_R_OK)
2050 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
2052 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
2054 pkgmgrinfo_appinfo_filter_destroy (handle);
2057 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
2062 for (unsigned int i = 0; i < _ime_info.size (); i++) {
2063 if (!uuid.compare (_ime_info[i].appid)) {
2064 if (TOOLBAR_KEYBOARD_MODE == _ime_info[i].mode)
2065 ise_changed = set_keyboard_ise (_ime_info[i].appid);
2066 else if (TOOLBAR_HELPER_MODE == _ime_info[i].mode) {
2067 if (_ime_info[i].is_enabled) {
2068 if (_ime_info[i].exec == String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
2069 /* If IME so is deleted somehow, main() in scim_helper_launcher.cpp will return -1.
2070 Checking HelperModule validity seems necessary here. */
2071 HelperModule helper_module (_ime_info[i].module_name);
2072 if (helper_module.valid ())
2074 helper_module.unload ();
2077 /* executable type */
2082 ise_changed = set_helper_ise (_ime_info[i].appid, launch_ise);
2084 LOGW ("Helper ISE(appid=\"%s\",module_name=\"%s\") is not valid.", _ime_info[i].appid.c_str (), _ime_info[i].module_name.c_str ());
2087 LOGW ("Helper ISE(appid=\"%s\") is not enabled.", _ime_info[i].appid.c_str ());
2090 _info_manager->set_current_toolbar_mode (_ime_info[i].mode);
2092 /* From Tizen 4.0 all the ISEs need to handle H/W keyboard events */
2093 _ime_info[i].options |= ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
2094 _info_manager->set_current_helper_option (_ime_info[i].options);
2095 _info_manager->set_current_ise_name (_ime_info[i].label);
2098 _ise_state = WINDOW_STATE_HIDE;
2099 _candidate_mode = SOFT_CANDIDATE_WINDOW;
2100 _candidate_port_line = ONE_LINE_CANDIDATE;
2101 _soft_candidate_width = 0;
2102 _soft_candidate_height = 0;
2103 #if ISF_BUILD_CANDIDATE_UI
2104 if (_candidate_window)
2105 ui_create_candidate_window ();
2108 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _ime_info[i].appid);
2109 scim_global_config_flush ();
2115 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2119 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2126 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2132 * @brief Load ISF configuration and ISEs information.
2134 static void load_config (void)
2136 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2138 /* Read configurations. */
2139 if (!_config.null ()) {
2140 bool shared_ise = _config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), false);
2141 _info_manager->set_should_shared_ise (shared_ise);
2143 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
2145 isf_load_ise_information (ALL_ISE, _config);
2149 * @brief Reload config callback function for ISF panel.
2151 * @param config The config pointer.
2153 static void config_reload_cb (const ConfigPointer &config)
2155 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2156 /* load_config (); */
2157 _info_manager->reload_config ();
2160 #if ISF_BUILD_CANDIDATE_UI
2161 //////////////////////////////////////////////////////////////////////
2162 // Start of Candidate Functions
2163 //////////////////////////////////////////////////////////////////////
2165 * @brief Get candidate window valid height for autoscroll.
2167 * @return The valid height.
2169 static int ui_candidate_get_valid_height (void)
2171 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2176 if (_candidate_window) {
2177 if (_candidate_state == WINDOW_STATE_SHOW)
2178 angle = _candidate_angle;
2180 angle = efl_get_app_window_angle ();
2182 if (_aux_area_visible && _candidate_area_1_visible) {
2183 if (angle == 90 || angle == 270)
2184 height = _candidate_land_height_min_2;
2186 height = _candidate_port_height_min_2;
2188 if (angle == 90 || angle == 270)
2189 height = _candidate_land_height_min;
2191 height = _candidate_port_height_min;
2198 * @brief Resize candidate window size.
2200 * @param new_width New width for candidate window.
2201 * @param new_height New height for candidate window.
2203 static void ui_candidate_window_resize (int new_width, int new_height)
2205 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " width:" << new_width << " height:" << new_height << "\n";
2207 if (!_candidate_window)
2212 LOGD ("%s (w: %d, h: %d)", __func__, new_width, new_height);
2213 evas_object_resize (_aux_line, new_width, 2);
2214 _candidate_width = new_width;
2215 _candidate_height = new_height;
2216 if (_candidate_state == WINDOW_STATE_SHOW)
2217 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2219 if (_candidate_state == WINDOW_STATE_SHOW && _candidate_mode == FIXED_CANDIDATE_WINDOW) {
2220 height = ui_candidate_get_valid_height ();
2221 if ((_ise_width == 0 && _ise_height == 0) ||
2222 (_ise_height > 0 && _candidate_valid_height != height) ||
2223 (_ise_height > 0 && (_candidate_height - height) > _ise_height) ||
2224 ((_candidate_angle == 90 || _candidate_angle == 270) && (_ise_width < _screen_height)) ||
2225 ((_candidate_angle == 0 || _candidate_angle == 180) && (_ise_width > _screen_width ))) {
2227 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2229 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2233 /* Get height for portrait and landscape */
2234 int port_width = _candidate_port_width;
2235 int port_height = _candidate_port_height_min;
2236 int land_width = _candidate_land_width;
2237 int land_height = _candidate_land_height_min;
2238 if (_candidate_angle == 90 || _candidate_angle == 270) {
2239 land_height = new_height;
2240 if (land_height == _candidate_land_height_min_2) {
2241 port_height = _candidate_port_height_min_2;
2242 } else if (land_height == _candidate_land_height_max) {
2243 port_height = _candidate_port_height_max;
2244 } else if (land_height == _candidate_land_height_max_2) {
2245 port_height = _candidate_port_height_max_2;
2248 port_height = new_height;
2249 if (port_height == _candidate_port_height_min_2) {
2250 land_height = _candidate_land_height_min_2;
2251 } else if (port_height == _candidate_port_height_max) {
2252 land_height = _candidate_land_height_max;
2253 } else if (port_height == _candidate_port_height_max_2) {
2254 land_height = _candidate_land_height_max_2;
2258 LOGD ("window_rotation_geometry_set (_candidate_window), port (%d, %d), land (%d, %d)",
2259 port_width, port_height, land_width, land_height);
2263 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2264 0, 0, 0, port_width, port_height);
2265 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2266 90, 0, 0, land_height, land_width);
2267 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2268 180, 0, 0, port_width, port_height);
2269 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2270 270, 0, 0, land_height, land_width);
2273 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
2274 0, 0, 0, port_width, port_height);
2275 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
2276 90, 0, 0, land_height, land_width);
2277 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
2278 180, 0, 0, port_width, port_height);
2279 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
2280 270, 0, 0, land_height, land_width);
2285 * @brief This function will show/hide widgets of candidate window,
2286 * and resize candidate window size according to aux_area/candidate_area.
2288 static void ui_candidate_window_adjust (void)
2290 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2291 if (!_candidate_window)
2294 int x = 0, y = 0, width = 0, height = 0;
2296 /* Get candidate window size */
2299 if (_candidate_angle == 90 || _candidate_angle == 270) {
2300 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2301 &x, &y, &height, &width);
2303 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2304 &x, &y, &width, &height);
2308 if (_candidate_angle == 90 || _candidate_angle == 270)
2309 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &height, &width);
2311 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
2314 if (_aux_area_visible && _candidate_area_2_visible) {
2315 evas_object_show (_aux_line);
2316 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);
2317 if (_candidate_angle == 90 || _candidate_angle == 270) {
2318 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2319 _ise_height > _candidate_land_height_max_2 - _candidate_land_height_min_2)
2320 ui_candidate_window_resize (width, _candidate_land_height_min_2 + _ise_height);
2322 ui_candidate_window_resize (width, _candidate_land_height_max_2);
2323 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2324 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min_2);
2325 evas_object_move (_scroller_bg, 0, _candidate_land_height_min_2);
2326 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2328 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2329 _ise_height > _candidate_port_height_max_2 - _candidate_port_height_min_2)
2330 ui_candidate_window_resize (width, _candidate_port_height_min_2 + _ise_height);
2332 ui_candidate_window_resize (width, _candidate_port_height_max_2);
2333 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2334 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min_2);
2335 evas_object_move (_scroller_bg, 0, _candidate_port_height_min_2);
2336 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2338 } else if (_aux_area_visible && _candidate_area_1_visible) {
2339 evas_object_show (_aux_line);
2340 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);
2341 if (_candidate_angle == 90 || _candidate_angle == 270) {
2342 ui_candidate_window_resize (width, _candidate_land_height_min_2);
2343 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2344 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2346 ui_candidate_window_resize (width, _candidate_port_height_min_2);
2347 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2348 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2350 } else if (_aux_area_visible) {
2351 evas_object_hide (_aux_line);
2352 ui_candidate_window_resize (width, _aux_height + 2);
2353 evas_object_resize (_candidate_bg, width, _aux_height + 2);
2354 } else if (_candidate_area_2_visible) {
2355 evas_object_hide (_aux_line);
2356 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2357 if (_candidate_angle == 90 || _candidate_angle == 270) {
2358 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2359 _ise_height > _candidate_land_height_max - _candidate_land_height_min)
2360 ui_candidate_window_resize (width, _candidate_land_height_min + _ise_height);
2362 ui_candidate_window_resize (width, _candidate_land_height_max);
2363 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3]);
2364 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min);
2365 evas_object_move (_scroller_bg, 0, _candidate_land_height_min);
2366 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2368 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2369 _ise_height > _candidate_port_height_max - _candidate_port_height_min)
2370 ui_candidate_window_resize (width, _candidate_port_height_min + _ise_height);
2372 ui_candidate_window_resize (width, _candidate_port_height_max);
2373 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
2374 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min);
2375 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
2376 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2379 evas_object_hide (_aux_line);
2380 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2381 if (_candidate_angle == 90 || _candidate_angle == 270) {
2382 ui_candidate_window_resize (width, _candidate_land_height_min);
2383 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3]);
2384 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2386 ui_candidate_window_resize (width, _candidate_port_height_min);
2387 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
2388 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2394 * @brief Rotate candidate window.
2396 * @param angle The angle of candidate window.
2398 static void ui_candidate_window_rotate (int angle)
2400 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2401 if (!_candidate_window)
2404 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
2406 if (angle == 90 || angle == 270) {
2407 _candidate_scroll_width = _candidate_scroll_width_max;
2408 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
2409 evas_object_resize (_aux_area, _aux_land_width, _aux_height);
2410 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_max, _item_min_height);
2411 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_min);
2412 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_min + 6);
2414 _candidate_scroll_width = _candidate_scroll_width_min;
2415 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
2416 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
2417 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
2418 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_max);
2419 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
2422 evas_object_hide (_candidate_area_2);
2423 _candidate_area_2_visible = false;
2424 ui_candidate_window_adjust ();
2425 if (_candidate_area_1_visible) {
2426 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2427 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
2428 ui_tts_focus_rect_hide ();
2434 * @brief This function is used to judge whether candidate window should be hidden.
2436 * @return true if candidate window should be hidden, otherwise return false.
2438 static bool ui_candidate_can_be_hide (void)
2440 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2442 if (_aux_area_visible || _candidate_area_1_visible || _candidate_area_2_visible)
2449 * @brief Delete check candidate window size timer.
2453 static void ui_candidate_delete_check_size_timer (void)
2455 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2457 if (_check_size_timer != NULL) {
2458 ecore_timer_del (_check_size_timer);
2459 _check_size_timer = NULL;
2464 * @brief Callback function for check candidate window size timer.
2466 * @param data Data to pass when it is called.
2468 * @return ECORE_CALLBACK_CANCEL
2470 static Eina_Bool ui_candidate_check_size_timeout (void *data)
2472 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2474 ui_candidate_delete_check_size_timer ();
2475 ui_candidate_window_resize (_candidate_width, _candidate_height);
2476 ui_settle_candidate_window ();
2477 return ECORE_CALLBACK_CANCEL;
2481 * @brief Delete longpress timer.
2485 static void ui_candidate_delete_longpress_timer (void)
2487 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2489 if (_longpress_timer != NULL) {
2490 ecore_timer_del (_longpress_timer);
2491 _longpress_timer = NULL;
2496 * @brief Callback function for candidate longpress timer.
2498 * @param data Data to pass when it is called.
2500 * @return ECORE_CALLBACK_CANCEL
2502 static Eina_Bool ui_candidate_longpress_timeout (void *data)
2504 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2506 int index = (int)GPOINTER_TO_INT (data);
2507 ui_candidate_delete_longpress_timer ();
2509 _info_manager->send_longpress_event (_click_object, index);
2510 return ECORE_CALLBACK_CANCEL;
2514 * @brief Delete destroy timer.
2518 static void ui_candidate_delete_destroy_timer (void)
2520 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2522 if (_destroy_timer != NULL) {
2523 ecore_timer_del (_destroy_timer);
2524 _destroy_timer = NULL;
2529 * @brief Callback function for destroy timer.
2531 * @param data Data to pass when it is called.
2533 * @return ECORE_CALLBACK_CANCEL
2535 static Eina_Bool ui_candidate_destroy_timeout (void *data)
2537 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2539 ui_candidate_delete_destroy_timer ();
2540 ui_destroy_candidate_window ();
2541 return ECORE_CALLBACK_CANCEL;
2543 #endif /* CANDIDATE */
2547 * @brief Callback function for off_prepare_done.
2549 * @param data Data to pass when it is called.
2551 * @return ECORE_CALLBACK_CANCEL
2553 static Eina_Bool off_prepare_done_timeout (void *data)
2555 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2557 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
2558 // WILL_HIDE_REQUEST_DONE Ack to WM
2559 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
2560 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
2561 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
2562 root_window, _control_window);
2563 _off_prepare_done_timer = NULL;
2565 return ECORE_CALLBACK_CANCEL;
2567 #endif /* HAVE_ECOREX */
2569 #if ISF_BUILD_CANDIDATE_UI
2571 * @brief Delete candidate hide timer.
2575 static void delete_candidate_hide_timer (void)
2577 LOGD ("deleting candidate_hide_timer");
2578 if (_candidate_hide_timer) {
2579 ecore_timer_del (_candidate_hide_timer);
2580 _candidate_hide_timer = NULL;
2584 static void candidate_window_hide (void)
2586 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2588 delete_candidate_hide_timer ();
2589 _candidate_state = WINDOW_STATE_HIDE;
2591 LOGD ("evas_object_hide (_candidate_window, %p)", elm_win_xwindow_get (_candidate_window));
2593 if (_candidate_window) {
2594 /* There are cases that when there are rapid ISE_HIDE and ISE_SHOW requests,
2595 candidate window should be displayed but STATE_OFF for the first ISE_HIDE
2596 calls this function, so when the candidate window is shown by the following
2597 STATE_ON message, a blank area is displayed in candidate window -
2598 so we let the _candidate_area_1 as the default area that would be displayed */
2599 //evas_object_hide (_candidate_area_1);
2600 //evas_object_hide (_more_btn);
2601 _candidate_area_1_visible = false;
2603 evas_object_hide (_candidate_window);
2604 SCIM_DEBUG_MAIN (3) << " Hide candidate window\n";
2609 * @brief Callback function for candidate hide timer
2611 * @param data Data to pass when it is called.
2613 * @return ECORE_CALLBACK_CANCEL
2615 static Eina_Bool candidate_hide_timer (void *data)
2617 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2619 LOGD ("calling candidate_window_hide ()");
2620 candidate_window_hide ();
2622 return ECORE_CALLBACK_CANCEL;
2627 * @brief Delete candidate show handler.
2631 static void delete_candidate_show_handler (void)
2633 if (_candidate_show_handler) {
2634 ecore_event_handler_del (_candidate_show_handler);
2635 _candidate_show_handler = NULL;
2640 * @brief Callback function for window show completion event
2642 * @param data Data to pass when it is called.
2644 * @return ECORE_CALLBACK_CANCEL
2647 static Eina_Bool x_event_window_show_cb (void *data, int ev_type, void *event)
2649 delete_candidate_show_handler ();
2651 Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
2652 if (_candidate_state == WINDOW_STATE_WILL_SHOW) {
2653 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2654 LOGD ("Candidate window show callback");
2656 /* If our candidate window is in WILL_SHOW state and this show callback was called,
2657 now we are finally displayed on to the screen */
2658 _candidate_state = WINDOW_STATE_SHOW;
2660 /* Update the geometry information for auto scrolling */
2661 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2662 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2663 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2665 /* And the state event */
2666 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2668 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2669 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2670 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2671 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2676 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2677 LOGD ("Candidate window show callback, but _candidate_state is %d", _candidate_state);
2681 return ECORE_CALLBACK_CANCEL;
2683 #endif /* HAVE_ECOREX */
2686 * @brief Show candidate window.
2688 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2690 static void ui_candidate_show (bool bSetVirtualKbd)
2692 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2694 delete_candidate_hide_timer ();
2696 if (!_candidate_window) return;
2697 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
2700 /* FIXME : SHOULD UNIFY THE METHOD FOR CHECKING THE HW KEYBOARD EXISTENCE */
2701 /* If the ISE is not visible currently, wait for the ISE to be opened and then show our candidate window */
2702 _candidate_show_requested = true;
2703 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) && (_ise_state != WINDOW_STATE_SHOW)) {
2704 LOGD ("setting _show_candidate_requested to TRUE");
2708 /* If the ISE angle is valid, respect the value to make sure
2709 the candidate window always have the same angle with ISE */
2710 if (_ise_angle != -1) {
2711 _candidate_angle = _ise_angle;
2713 ui_candidate_window_rotate (_candidate_angle);
2715 /* If the candidate window was about to hide, turn it back to SHOW state now */
2716 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
2717 _candidate_state = WINDOW_STATE_SHOW;
2720 /* Change to WILL_SHOW state only when we are not currently in SHOW state */
2721 if (_candidate_state != WINDOW_STATE_SHOW) {
2722 _candidate_state = WINDOW_STATE_WILL_SHOW;
2726 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2727 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
2728 // Unset conformant area
2729 Ecore_X_Window current_app_window = efl_get_app_window ();
2730 if (_app_window != current_app_window) {
2731 struct rectinfo info = {0, 0, 0, 0};
2732 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
2733 set_keyboard_geometry_atom_info (_app_window, info);
2734 LOGD ("Conformant reset for window %x", _app_window);
2735 _app_window = current_app_window;
2739 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2740 if (bSetVirtualKbd) {
2741 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2744 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
2747 ui_candidate_delete_check_size_timer ();
2748 _check_size_timer = ecore_timer_add (0.02, ui_candidate_check_size_timeout, NULL);
2750 SCIM_DEBUG_MAIN (3) << " Show candidate window\n";
2752 if (_ise_state == WINDOW_STATE_SHOW) {
2753 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
2754 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
2756 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
2757 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
2760 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2761 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2762 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2763 LOGD ("sending ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW");
2764 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
2768 if (_candidate_state != WINDOW_STATE_SHOW) {
2770 if (_candidate_show_handler) {
2771 LOGD ("Was still waiting for CANDIDATE_WINDOW_SHOW....");
2773 delete_candidate_show_handler ();
2774 LOGD ("Registering ECORE_X_EVENT_WINDOW_SHOW event, %d", _candidate_state);
2775 _candidate_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_window_show_cb, NULL);
2779 LOGD ("The candidate window was already in SHOW state, update geometry information");
2780 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2781 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2783 /* And the state event */
2784 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2786 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2787 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2788 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2789 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2794 evas_object_show (_candidate_window);
2798 * @brief Hide candidate window.
2800 * @param bForce The flag to hide candidate window by force.
2801 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2803 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd, bool will_hide)
2805 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " bForce:" << bForce << " bSetVirtualKbd:" << bSetVirtualKbd << " will_hide:" << will_hide << "...\n";
2807 if (!_candidate_window)
2811 if (_candidate_area_2 && _candidate_area_2_visible) {
2812 evas_object_hide (_candidate_area_2);
2813 _candidate_area_2_visible = false;
2814 evas_object_hide (_scroller_bg);
2815 evas_object_hide (_close_btn);
2816 _info_manager->candidate_more_window_hide ();
2817 ui_candidate_window_adjust ();
2821 if (bForce || ui_candidate_can_be_hide ()) {
2823 LOGD ("candidate_state = WILL_HIDE");
2824 _candidate_state = WINDOW_STATE_WILL_HIDE;
2826 delete_candidate_hide_timer ();
2827 _candidate_hide_timer = ecore_timer_add (2.0, candidate_hide_timer, NULL);
2830 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2831 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2832 /* FIXME : should check if bSetVirtualKbd flag is really needed in this case */
2834 if (_ise_state == WINDOW_STATE_SHOW) {
2835 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2837 if (bSetVirtualKbd) {
2838 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2842 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2843 _info_manager->update_input_panel_event
2844 ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_HIDE);
2848 /* Update the new keyboard geometry first, and then send the candidate hide event */
2849 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_HIDE);
2852 /* If we are not in will_hide state, hide the candidate window immediately */
2853 candidate_window_hide ();
2855 if (_preedit_window)
2856 evas_object_hide (_preedit_window);
2862 * @brief Callback function for more button.
2864 * @param data Data to pass when it is called.
2865 * @param e The evas for current event.
2866 * @param button The evas object for current event.
2867 * @param event_info The information for current event.
2869 static void ui_candidate_window_more_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2871 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2873 _info_manager->candidate_more_window_show ();
2875 if (candidate_expanded == false) {
2876 candidate_expanded = true;
2877 int number = SCIM_LOOKUP_TABLE_MAX_PAGESIZE;
2878 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
2879 if (_candidate_0 [i] == NULL) {
2884 if (g_isf_candidate_table.get_current_page_size () != number)
2885 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2888 if (_candidate_angle == 180) {
2889 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2890 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2891 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2892 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2894 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2895 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2896 * for avoiding this situation.
2898 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2899 ecore_evas_move_resize (ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2900 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2901 ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2904 evas_object_show (_candidate_area_2);
2905 _candidate_area_2_visible = true;
2906 evas_object_show (_scroller_bg);
2907 evas_object_hide (_more_btn);
2908 evas_object_show (_close_btn);
2910 ui_candidate_window_adjust ();
2911 ui_settle_candidate_window ();
2916 * @brief Callback function for close button.
2918 * @param data Data to pass when it is called.
2919 * @param e The evas for current event.
2920 * @param button The evas object for current event.
2921 * @param event_info The information for current event.
2923 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2925 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2927 if (_candidate_area_2 == NULL || !_candidate_area_2_visible)
2930 _info_manager->candidate_more_window_hide ();
2932 evas_object_hide (_candidate_area_2);
2933 _candidate_area_2_visible = false;
2934 evas_object_hide (_scroller_bg);
2935 evas_object_hide (_close_btn);
2937 candidate_expanded = false;
2938 evas_object_show (_candidate_area_1);
2939 _candidate_area_1_visible = true;
2940 evas_object_show (_more_btn);
2942 elm_scroller_region_show (_candidate_area_2, 0, 0, _candidate_scroll_width, 100);
2943 if (_candidate_angle == 180) {
2944 Ecore_Evas *ee= ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2945 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2946 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2947 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2949 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2950 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2951 * for avoiding this situation.
2953 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2954 ecore_evas_move_resize (ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2955 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2956 ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2959 ui_candidate_window_adjust ();
2960 ui_settle_candidate_window ();
2965 * @brief Callback function for mouse button press.
2967 * @param data Data to pass when it is called.
2968 * @param e The evas for current event.
2969 * @param button The evas object for current event.
2970 * @param event_info The information for current event.
2972 static void ui_mouse_button_pressed_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2974 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2976 _click_object = GPOINTER_TO_INT (data) & 0xFF;
2979 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
2982 _click_down_pos [0] = ev->canvas.x;
2983 _click_down_pos [1] = ev->canvas.y;
2985 if (_click_object == ISF_EFL_CANDIDATE_0 || _click_object == ISF_EFL_CANDIDATE_ITEMS) {
2986 int index = (int)GPOINTER_TO_INT (data) >> 8;
2988 #ifdef HAVE_FEEDBACK
2989 if (feedback_initialized) {
2990 int feedback_result = 0;
2991 bool sound_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_SOUND_FEEDBACK, false);
2993 if (sound_feedback) {
2994 feedback_result = feedback_play_type (FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_SIP);
2996 if (FEEDBACK_ERROR_NONE == feedback_result)
2997 LOGD ("Sound play successful");
2999 LOGW ("Cannot play feedback sound : %d", feedback_result);
3002 bool vibrate_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_VIBRATION_FEEDBACK, false);
3004 if (vibrate_feedback) {
3005 feedback_result = feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
3007 if (FEEDBACK_ERROR_NONE == feedback_result)
3008 LOGD ("Vibration play successful");
3010 LOGW ("Cannot play feedback vibration : %d", feedback_result);
3015 ui_candidate_delete_longpress_timer ();
3016 _longpress_timer = ecore_timer_add (1.0, ui_candidate_longpress_timeout, (void *)index);
3021 * @brief Callback function for mouse button release.
3023 * @param data Data to pass when it is called.
3024 * @param e The evas for current event.
3025 * @param button The evas object for current event.
3026 * @param event_info The information for current event.
3028 static void ui_mouse_button_released_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3030 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " index:" << GPOINTER_TO_INT (data) << "...\n";
3032 ui_candidate_delete_longpress_timer ();
3034 int index = GPOINTER_TO_INT (data);
3035 if (_click_object == ISF_EFL_AUX && _is_click) {
3037 const char *buf = edje_object_part_state_get (button, "aux", &ret);
3038 if (strcmp ("selected", buf)) {
3039 for (unsigned int i = 0; i < _aux_items.size (); i++) {
3040 buf = edje_object_part_state_get (_aux_items [i], "aux", &ret);
3041 if (!strcmp ("selected", buf))
3042 edje_object_signal_emit (_aux_items [i], "aux,state,unselected", "aux");
3044 edje_object_signal_emit (button, "aux,state,selected", "aux");
3045 _info_manager->select_aux (index);
3047 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
3048 edje_object_color_class_get (_aux_items [index], "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
3049 // Normal item is clicked
3050 if (!(r == 62 && g == 207 && b == 255)) {
3051 for (unsigned int i = 0; i < _aux_items.size (); i++) {
3052 edje_object_color_class_set (_aux_items [i], "text_color", 249, 249, 249, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3054 edje_object_color_class_set (_aux_items [index], "text_color", 62, 207, 255, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3055 _info_manager->select_aux (index);
3057 } else if (_click_object == ISF_EFL_CANDIDATE_0 && _is_click) {
3058 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3059 _info_manager->select_candidate (index);
3060 } else if (_click_object == ISF_EFL_CANDIDATE_ITEMS && _is_click) {
3061 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3062 _info_manager->select_candidate (index);
3067 * @brief Callback function for mouse move.
3069 * @param data Data to pass when it is called.
3070 * @param e The evas for current event.
3071 * @param button The evas object for current event.
3072 * @param event_info The information for current event.
3074 static void ui_mouse_moved_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3076 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3078 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
3081 _click_up_pos [0] = ev->canvas.x;
3082 _click_up_pos [1] = ev->canvas.y;
3084 if (abs (_click_up_pos [0] - _click_down_pos [0]) >= (int)(15 * _height_rate) ||
3085 abs (_click_up_pos [1] - _click_down_pos [1]) >= (int)(15 * _height_rate)) {
3087 ui_candidate_delete_longpress_timer ();
3093 * @brief Open TTS device.
3095 * @return false if open is failed, otherwise return true.
3097 static bool ui_open_tts (void)
3099 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3101 int r = tts_create (&_tts);
3102 if (TTS_ERROR_NONE != r) {
3103 LOGW ("tts_create FAILED : result (%d)", r);
3108 r = tts_set_mode (_tts, TTS_MODE_SCREEN_READER);
3109 if (TTS_ERROR_NONE != r) {
3110 LOGW ("tts_set_mode FAILED : result (%d)", r);
3113 tts_state_e current_state;
3114 r = tts_get_state (_tts, ¤t_state);
3115 if (TTS_ERROR_NONE != r) {
3116 LOGW ("tts_get_state FAILED : result (%d)", r);
3119 if (TTS_STATE_CREATED == current_state) {
3120 r = tts_prepare (_tts);
3121 if (TTS_ERROR_NONE != r) {
3122 LOGW ("tts_prepare FAILED : ret (%d)", r);
3129 * @brief Close TTS device.
3131 static void ui_close_tts (void)
3133 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3136 int r = tts_unprepare (_tts);
3137 if (TTS_ERROR_NONE != r) {
3138 LOGW ("tts_unprepare FAILED : result (%d)", r);
3141 r = tts_destroy (_tts);
3142 if (TTS_ERROR_NONE != r) {
3143 LOGW ("tts_destroy FAILED : result (%d)", r);
3149 * @brief Play string by TTS.
3151 * @param str The string for playing.
3153 static void ui_play_tts (const char* str)
3155 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << "\n";
3160 if (!ui_open_tts ())
3166 tts_state_e current_state;
3168 r = tts_get_state (_tts, ¤t_state);
3169 if (TTS_ERROR_NONE != r) {
3170 LOGW ("Fail to get state from TTS : ret (%d)", r);
3173 if (TTS_STATE_PLAYING == current_state) {
3174 r = tts_stop (_tts);
3175 if (TTS_ERROR_NONE != r) {
3176 LOGW ("Fail to stop TTS : ret (%d)", r);
3180 /* Get ISE language */
3181 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
3182 String language = String ("en_US");
3183 if (default_uuid.length () > 0) {
3184 language = _ime_info[get_ise_index (default_uuid)].languages;
3185 if (language.length () > 0) {
3186 std::vector<String> ise_langs;
3187 scim_split_string_list (ise_langs, language);
3188 language = ise_langs[0];
3191 LOGD ("TTS language:%s, str:%s", language.c_str (), str);
3193 r = tts_add_text (_tts, str, language.c_str (), TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &utt_id);
3194 if (TTS_ERROR_NONE == r) {
3195 r = tts_play (_tts);
3196 if (TTS_ERROR_NONE != r) {
3197 LOGW ("Fail to play TTS : ret (%d)", r);
3201 #endif /* HAVE_TTS */
3204 * @brief Show rect for candidate focus object when screen reader is enabled.
3206 * @param x Rect X position.
3207 * @param y Rect Y position.
3208 * @param w Rect width.
3209 * @param h Rect height.
3211 static void ui_tts_focus_rect_show (int x, int y, int w, int h)
3213 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3214 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
3217 if (_tts_focus_rect == NULL) {
3218 _tts_focus_rect = evas_object_rectangle_add (evas_object_evas_get ((Evas_Object*)_candidate_window));
3219 evas_object_color_set (_tts_focus_rect, 0, 0, 0, 0);
3220 elm_access_highlight_set (elm_access_object_register (_tts_focus_rect, (Evas_Object*)_candidate_window));
3222 evas_object_move (_tts_focus_rect, x, y);
3223 evas_object_resize (_tts_focus_rect, w, h);
3224 evas_object_raise (_tts_focus_rect);
3225 evas_object_show (_tts_focus_rect);
3229 * @brief Hide rect for candidate focus object when screen reader is enabled.
3231 static void ui_tts_focus_rect_hide (void)
3233 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3235 if (_tts_focus_rect) {
3236 //evas_object_hide (_tts_focus_rect);
3237 evas_object_move (_tts_focus_rect, -1000, -1000);
3242 * @brief Callback function for candidate scroller stop event.
3244 * @param data Data to pass when it is called.
3245 * @param obj The evas object for current event.
3246 * @param event_info The information for current event.
3248 static void ui_candidate_scroller_stop_cb (void *data, Evas_Object *obj, void *event_info)
3250 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3251 if (!_wait_stop_event)
3254 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
3255 if (_candidate_0 [_candidate_tts_focus_index]) {
3257 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
3258 ui_tts_focus_rect_show (x, y, w, h);
3261 _wait_stop_event = false;
3266 * @brief Mouse over (find focus object and play text by TTS) when screen reader is enabled.
3268 * @param mouse_x Mouse X position.
3269 * @param mouse_y Mouse Y position.
3271 static void ui_mouse_over (int mouse_x, int mouse_y)
3273 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3274 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
3277 int x, y, width, height;
3278 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3279 if (_candidate_0 [i]) {
3280 evas_object_geometry_get (_candidate_0 [i], &x, &y, &width, &height);
3281 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3282 /* FIXME: Should consider emoji case */
3283 String mbs = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (i));
3284 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " play candidate string: " << mbs << "\n";
3286 ui_play_tts (mbs.c_str ());
3288 _candidate_tts_focus_index = i;
3289 ui_tts_focus_rect_show (x, y, width, height);
3295 String strTts = String ("");
3296 if (_candidate_area_2_visible) {
3297 evas_object_geometry_get (_close_btn, &x, &y, &width, &height);
3298 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3299 strTts = String (_("close button"));
3300 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
3301 ui_tts_focus_rect_show (x, y, width, height);
3304 evas_object_geometry_get (_more_btn, &x, &y, &width, &height);
3305 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3306 strTts = String (_("more button"));
3307 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
3308 ui_tts_focus_rect_show (x, y, width, height);
3312 if (strTts.length () > 0)
3313 ui_play_tts (strTts.c_str ());
3318 * @brief Mouse click (find focus object and do click event) when screen reader is enabled.
3320 * @param focus_index focused candidate index.
3322 static void ui_mouse_click (int focus_index)
3324 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3325 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW || focus_index == INVALID_TTS_FOCUS_INDEX)
3328 if (focus_index >= 0 && focus_index < g_isf_candidate_table.get_current_page_size ()) {
3329 if (_candidate_0 [focus_index]) {
3330 int x, y, width, height;
3331 evas_object_geometry_get (_candidate_0 [focus_index], &x, &y, &width, &height);
3332 Evas_Event_Mouse_Down event_info;
3333 event_info.canvas.x = x + width / 2;
3334 event_info.canvas.y = y + height / 2;
3335 ui_mouse_button_pressed_cb (GINT_TO_POINTER ((focus_index << 8) + ISF_EFL_CANDIDATE_0), NULL, NULL, &event_info);
3336 ui_mouse_button_released_cb (GINT_TO_POINTER (focus_index), NULL, NULL, &event_info);
3338 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
3339 ui_tts_focus_rect_hide ();
3343 if (_candidate_area_2_visible) {
3344 if (focus_index == CLOSE_BUTTON_INDEX) {
3345 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
3346 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
3349 if (focus_index == MORE_BUTTON_INDEX) {
3350 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
3351 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
3355 #endif /* HAVE_ECOREX */
3358 * @brief Create preedit window.
3360 static void ui_create_preedit_window (void)
3362 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3364 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3367 _preedit_width = 100;
3368 _preedit_height = _preedit_height * _height_rate;
3369 if (_preedit_window == NULL) {
3370 _preedit_window = efl_create_window ("ISF Popup", "Preedit Window");
3371 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
3372 int rots [4] = {0, 90, 180, 270};
3373 elm_win_wm_rotation_available_rotations_set (_preedit_window, rots, 4);
3374 int preedit_font_size = (int)(32 * _width_rate);
3376 _preedit_text = edje_object_add (evas_object_evas_get (_preedit_window));
3377 edje_object_file_set (_preedit_text, _candidate_edje_file.c_str (), "preedit_text");
3378 evas_object_size_hint_fill_set (_preedit_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
3379 evas_object_size_hint_weight_set (_preedit_text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3380 elm_win_resize_object_add (_preedit_window, _preedit_text);
3381 evas_object_show (_preedit_text);
3383 _tmp_preedit_text = evas_object_text_add (evas_object_evas_get (_preedit_window));
3384 evas_object_text_font_set (_tmp_preedit_text, _candidate_font_name.c_str (), preedit_font_size);
3389 * @brief Create native style candidate window.
3391 static void ui_create_native_candidate_window (void)
3393 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3394 _more_btn_width = 80 * (_width_rate > 1 ? 1 : _width_rate);
3395 _more_btn_height = 64 * _height_rate;
3397 _candidate_port_width = _screen_width;
3398 _candidate_port_height_min = 84 * _height_rate * _candidate_port_line;
3399 _candidate_port_height_min_2 = 84 * _height_rate + _candidate_port_height_min;
3400 _candidate_port_height_max = 426 * _height_rate + _candidate_port_height_min;
3401 _candidate_port_height_max_2 = 84 * _height_rate + _candidate_port_height_max;
3402 _candidate_land_width = _screen_height;
3403 _candidate_land_height_min = 84 * _width_rate;
3404 _candidate_land_height_min_2 = 168 * _width_rate;
3405 _candidate_land_height_max = 342 * _width_rate;
3406 _candidate_land_height_max_2 = 426 * _width_rate;
3408 _candidate_scroll_0_width_min= _screen_width;
3409 _candidate_scroll_0_width_max= _screen_height;
3410 _candidate_scroll_width_min = _screen_width;
3411 _candidate_scroll_width_max = _screen_height;
3412 _candidate_scroll_height_min = 252 * _width_rate;
3413 _candidate_scroll_height_max = 420 * _height_rate;
3415 _candidate_area_1_pos [0] = 0 * _width_rate;
3416 _candidate_area_1_pos [1] = 2 * _height_rate;
3417 _more_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3418 _more_btn_pos [1] = 12 * _height_rate;
3419 _more_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3420 _more_btn_pos [3] = 12 * _width_rate;
3421 _close_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3422 _close_btn_pos [1] = 12 * _height_rate;
3423 _close_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3424 _close_btn_pos [3] = 12 * _width_rate;
3426 _aux_height = 84 * _height_rate - 2;
3427 _aux_port_width = _screen_width;
3428 _aux_land_width = _screen_height;
3430 _item_min_height = 84 * _height_rate - 2;
3432 /* Create candidate window */
3433 if (_candidate_window == NULL) {
3434 _candidate_window = efl_create_window ("ISF Popup", "Prediction Window");
3435 int rots [4] = {0, 90, 180, 270};
3436 elm_win_wm_rotation_available_rotations_set (_candidate_window, rots, 4);
3437 if (_candidate_angle == 90 || _candidate_angle == 270) {
3438 _candidate_width = _candidate_land_width;
3439 _candidate_height = _candidate_land_height_min;
3441 _candidate_width = _candidate_port_width;
3442 _candidate_height = _candidate_port_height_min;
3446 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3447 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3448 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3449 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3450 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3451 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3452 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3453 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3456 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3457 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3458 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3459 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3460 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3461 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3462 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3463 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3465 /* Add dim background */
3466 Evas_Object *dim_bg = elm_bg_add (_candidate_window);
3467 evas_object_color_set (dim_bg, 0, 0, 0, 153);
3468 elm_win_resize_object_add (_candidate_window, dim_bg);
3469 evas_object_show (dim_bg);
3471 /* Add candidate background */
3472 _candidate_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3473 edje_object_file_set (_candidate_bg, _candidate_edje_file.c_str (), "candidate_bg");
3474 evas_object_size_hint_weight_set (_candidate_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3475 evas_object_resize (_candidate_bg, _candidate_port_width, _candidate_port_height_min);
3476 evas_object_move (_candidate_bg, 0, 0);
3477 evas_object_show (_candidate_bg);
3479 /* Create _candidate_0 scroller */
3480 _candidate_0_scroll = elm_scroller_add (_candidate_window);
3481 elm_scroller_bounce_set (_candidate_0_scroll, EINA_TRUE, EINA_FALSE);
3482 elm_scroller_policy_set (_candidate_0_scroll, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3483 evas_object_resize (_candidate_0_scroll, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
3484 evas_object_move (_candidate_0_scroll, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3486 /* Create candidate table */
3487 _candidate_0_table = elm_table_add (_candidate_window);
3488 evas_object_size_hint_weight_set (_candidate_0_table, 0.0, 0.0);
3489 evas_object_size_hint_align_set (_candidate_0_table, 0.0, 0.0);
3490 elm_table_padding_set (_candidate_0_table, 0, 0);
3491 elm_object_content_set (_candidate_0_scroll, _candidate_0_table);
3492 evas_object_show (_candidate_0_table);
3493 _candidate_area_1 = _candidate_0_scroll;
3495 /* Create more button */
3496 _more_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3497 if (_ise_width == 0 && _ise_height == 0)
3498 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
3500 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
3501 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
3502 evas_object_resize (_more_btn, _more_btn_width, _more_btn_height);
3503 evas_object_event_callback_add (_more_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_more_button_cb, NULL);
3505 /* Add scroller background */
3506 _candidate_scroll_width = _candidate_scroll_width_min;
3507 _scroller_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3508 edje_object_file_set (_scroller_bg, _candidate_edje_file.c_str (), "scroller_bg");
3509 evas_object_size_hint_weight_set (_scroller_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3510 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3511 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
3513 /* Create vertical scroller */
3514 _candidate_scroll = elm_scroller_add (_candidate_window);
3515 elm_scroller_bounce_set (_candidate_scroll, 0, 1);
3516 elm_scroller_policy_set (_candidate_scroll, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
3517 evas_object_resize (_candidate_scroll, _candidate_scroll_width, _candidate_scroll_height_max);
3518 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3519 elm_scroller_page_size_set (_candidate_scroll, 0, _item_min_height+_v_padding);
3520 evas_object_move (_candidate_scroll, 0, _candidate_port_height_min);
3522 /* Create candidate table */
3523 _candidate_table = elm_table_add (_candidate_window);
3524 evas_object_size_hint_weight_set (_candidate_table, 0.0, 0.0);
3525 evas_object_size_hint_align_set (_candidate_table, 0.0, 0.0);
3526 elm_table_padding_set (_candidate_table, 0, 0);
3527 elm_object_content_set (_candidate_scroll, _candidate_table);
3528 evas_object_show (_candidate_table);
3529 _candidate_area_2 = _candidate_scroll;
3530 evas_object_smart_callback_add (_candidate_scroll, "scroll,anim,stop", ui_candidate_scroller_stop_cb, NULL);
3532 /* Create close button */
3533 _close_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3534 if (_ise_width == 0 && _ise_height == 0)
3535 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
3537 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
3538 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
3539 evas_object_resize (_close_btn, _more_btn_width, _more_btn_height);
3540 evas_object_event_callback_add (_close_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_close_button_cb, NULL);
3542 _tmp_candidate_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3543 evas_object_text_font_set (_tmp_candidate_text, _candidate_font_name.c_str (), _candidate_font_size);
3546 _aux_area = elm_scroller_add (_candidate_window);
3547 elm_scroller_bounce_set (_aux_area, 1, 0);
3548 elm_scroller_policy_set (_aux_area, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3549 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
3550 evas_object_move (_aux_area, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3552 _aux_table = elm_table_add (_candidate_window);
3553 elm_object_content_set (_aux_area, _aux_table);
3554 elm_table_padding_set (_aux_table, 0, 0);
3555 evas_object_size_hint_weight_set (_aux_table, 0.0, 0.0);
3556 evas_object_size_hint_align_set (_aux_table, 0.0, 0.0);
3557 evas_object_show (_aux_table);
3559 _aux_line = edje_object_add (evas_object_evas_get (_candidate_window));
3560 edje_object_file_set (_aux_line, _candidate_edje_file.c_str (), "popup_line");
3561 evas_object_resize (_aux_line, _candidate_port_width, 2);
3562 evas_object_move (_aux_line, 0, _aux_height + 2);
3564 _tmp_aux_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3565 evas_object_text_font_set (_tmp_aux_text, _candidate_font_name.c_str (), _aux_font_size);
3567 evas_object_hide (_candidate_window);
3574 * @brief Create candidate window.
3578 static void ui_create_candidate_window (void)
3580 check_time ("\nEnter ui_create_candidate_window");
3581 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3582 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3587 _candidate_angle = 0;
3589 ui_create_native_candidate_window ();
3592 unsigned int set = 1;
3594 ecore_x_window_prop_card32_set (elm_win_xwindow_get (_candidate_window),
3595 ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
3598 int angle = efl_get_app_window_angle ();
3599 if (_candidate_angle != angle) {
3600 _candidate_angle = angle;
3601 ui_candidate_window_rotate (angle);
3603 ui_settle_candidate_window ();
3606 candidate_expanded = false;
3608 check_time ("Exit ui_create_candidate_window");
3612 * @brief Destroy candidate window.
3616 static void ui_destroy_candidate_window (void)
3618 check_time ("Enter ui_destroy_candidate_window");
3619 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3621 /* Delete candidate items, popup lines and seperator items */
3622 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3623 if (_candidate_0 [i]) {
3624 evas_object_del (_candidate_0 [i]);
3625 _candidate_0 [i] = NULL;
3627 if (_seperate_0 [i]) {
3628 evas_object_del (_seperate_0 [i]);
3629 _seperate_0 [i] = NULL;
3631 if (_seperate_items [i]) {
3632 evas_object_del (_seperate_items [i]);
3633 _seperate_items [i] = NULL;
3636 evas_object_del (_line_0 [i]);
3639 if (_line_items [i]) {
3640 evas_object_del (_line_items [i]);
3641 _line_items [i] = NULL;
3645 _aux_items.clear ();
3646 _aux_seperates.clear ();
3647 /* Delete candidate window */
3648 if (_candidate_window) {
3649 LOGD ("calling ui_candidate_hide (true)");
3650 ui_candidate_hide (true);
3652 evas_object_del (_candidate_window);
3653 _candidate_window = NULL;
3655 _candidate_area_1 = NULL;
3656 _candidate_area_2 = NULL;
3659 if (_tts_focus_rect) {
3660 evas_object_del (_tts_focus_rect);
3661 _tts_focus_rect = NULL;
3664 if (_candidate_bg) {
3665 evas_object_del (_candidate_bg);
3666 _candidate_bg = NULL;
3670 evas_object_del (_more_btn);
3675 evas_object_del (_scroller_bg);
3676 _scroller_bg = NULL;
3680 evas_object_del (_close_btn);
3685 evas_object_del (_aux_line);
3689 if (_tmp_candidate_text) {
3690 evas_object_del (_tmp_candidate_text);
3691 _tmp_candidate_text = NULL;
3694 if (_tmp_preedit_text) {
3695 evas_object_del (_tmp_preedit_text);
3696 _tmp_preedit_text = NULL;
3699 if (_tmp_aux_text) {
3700 evas_object_del (_tmp_aux_text);
3701 _tmp_aux_text = NULL;
3704 if (_preedit_text) {
3705 evas_object_del (_preedit_text);
3706 _preedit_text = NULL;
3709 if (_preedit_window) {
3710 evas_object_hide (_preedit_window);
3711 evas_object_del (_preedit_window);
3712 _preedit_window = NULL;
3716 check_time ("Exit ui_destroy_candidate_window");
3720 * @brief Settle candidate window position.
3722 static void ui_settle_candidate_window (void)
3724 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3726 if (!_candidate_window)
3729 /* If both ISE and candidate window are going to be hidden,
3730 let's just not move our candidate window */
3731 if (_ise_state == WINDOW_STATE_WILL_HIDE && _candidate_state == WINDOW_STATE_WILL_HIDE)
3735 int x, y, width, height;
3736 int ise_width = 0, ise_height = 0;
3737 bool get_geometry_result = false;
3739 /* Get candidate window position */
3740 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
3744 int pos_x = 0, pos_y = 0;
3745 if (_candidate_angle == 90 || _candidate_angle == 270)
3746 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_height, &ise_width);
3748 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_width, &ise_height);
3753 ise_width = _ise_width;
3754 ise_height = _ise_height;
3755 get_geometry_result = true;
3757 if ((_ise_state != WINDOW_STATE_SHOW && _ise_state != WINDOW_STATE_WILL_HIDE) ||
3758 (get_geometry_result == false) || (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
3763 int height2 = ui_candidate_get_valid_height ();
3765 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
3766 if (_candidate_angle == 90) {
3767 spot_x = _screen_width - ise_height - height2;
3769 } else if (_candidate_angle == 270) {
3770 spot_x = ise_height - (_candidate_height - height2);
3772 } else if (_candidate_angle == 180) {
3774 spot_y = ise_height - (_candidate_height - height2);
3777 spot_y = _screen_height - ise_height - height2;
3780 spot_x = _spot_location_x;
3781 spot_y = _spot_location_y;
3783 rectinfo ise_rect = {0, 0, (uint32)ise_width, (uint32)ise_height};
3784 if (_candidate_angle == 90 || _candidate_angle == 270) {
3785 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32)_screen_width)
3786 ise_rect.height = ISE_DEFAULT_HEIGHT_LANDSCAPE * _width_rate;
3788 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32) _screen_height)
3789 ise_rect.height = ISE_DEFAULT_HEIGHT_PORTRAIT * _height_rate;
3792 int nOffset = _candidate_port_height_min / 3;
3793 if (_candidate_angle == 270) {
3794 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3795 spot_x = _screen_width - _spot_location_top_y - (_candidate_height - height2);
3797 spot_x = _screen_width - _spot_location_y - _candidate_height;
3799 } else if (_candidate_angle == 90) {
3800 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3801 spot_x = _spot_location_top_y - height2;
3805 } else if (_candidate_angle == 180) {
3806 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3807 spot_y = _screen_height - _spot_location_top_y - (_candidate_height - height2);
3809 spot_y = _screen_height - _spot_location_y - _candidate_height;
3812 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3813 spot_y = _spot_location_top_y - height2;
3818 if (_candidate_angle == 90) {
3819 spot_y = (_screen_height - _candidate_width) / 2;
3820 spot_x = spot_x < _indicator_height ? _indicator_height : spot_x;
3821 if (spot_x > _screen_width - _candidate_height)
3822 spot_x = _screen_width - _candidate_height;
3823 } else if (_candidate_angle == 270) {
3824 spot_y = (_screen_height - _candidate_width) / 2;
3825 spot_x = spot_x < 0 ? 0 : spot_x;
3826 if (spot_x > _screen_width - (_indicator_height+_candidate_height))
3827 spot_x = _screen_width - (_indicator_height+_candidate_height);
3828 } else if (_candidate_angle == 180) {
3829 spot_x = (_screen_width - _candidate_width) / 2;
3830 spot_y = spot_y < 0 ? 0 : spot_y;
3831 if (spot_y > _screen_height - (_indicator_height+_candidate_height))
3832 spot_y = _screen_height - (_indicator_height+_candidate_height);
3834 spot_x = (_screen_width - _candidate_width) / 2;
3835 spot_y = spot_y < _indicator_height ? _indicator_height : spot_y;
3836 if (spot_y > _screen_height - _candidate_height)
3837 spot_y = _screen_height - _candidate_height;
3840 if (spot_x != x || spot_y != y) {
3841 _candidate_x = spot_x;
3842 _candidate_y = spot_y;
3843 evas_object_move (_candidate_window, spot_x, spot_y);
3844 LOGD ("Moving candidate window to : %d %d", spot_x, spot_y);
3845 if (_preedit_window) {
3846 if (_candidate_angle == 90) {
3847 spot_x -= _preedit_height;
3848 spot_y = _screen_height - _preedit_width;
3849 } else if (_candidate_angle == 270) {
3851 } else if (_candidate_angle == 180) {
3852 spot_x = _screen_width - _preedit_width;
3855 spot_y -= _preedit_height;
3857 evas_object_move (_preedit_window, spot_x, spot_y);
3859 if (_candidate_state == WINDOW_STATE_SHOW) {
3860 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
3864 #endif /* CANDIDATE */
3867 * @brief Set soft candidate geometry.
3869 * @param x The x position in screen.
3870 * @param y The y position in screen.
3871 * @param width The candidate window width.
3872 * @param height The candidate window height.
3874 static void set_soft_candidate_geometry (int x, int y, int width, int height)
3876 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
3878 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);
3880 if ((_candidate_mode != SOFT_CANDIDATE_WINDOW) || (_info_manager->get_current_toolbar_mode () != TOOLBAR_KEYBOARD_MODE))
3883 _soft_candidate_width = width;
3884 _soft_candidate_height = height;
3886 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry());
3888 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
3891 #if ISF_BUILD_CANDIDATE_UI
3892 //////////////////////////////////////////////////////////////////////
3893 // End of Candidate Functions
3894 //////////////////////////////////////////////////////////////////////
3897 * @brief Set transient for app window.
3899 * @param window The Ecore_X_Window handler of app window.
3901 static void efl_set_transient_for_app_window (Ecore_X_Window window)
3903 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3905 /* Set a transient window for window stack */
3906 Ecore_X_Window xAppWindow = efl_get_app_window ();
3907 ecore_x_icccm_transient_for_set (window, xAppWindow);
3909 LOGD ("win : %x, forwin : %x", window, xAppWindow);
3912 static int efl_get_window_rotate_angle (Ecore_X_Window win)
3914 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3919 unsigned char *prop_data = NULL;
3921 ret = ecore_x_window_prop_property_get (win,
3922 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
3923 if (ret && prop_data) {
3924 memcpy (&angle, prop_data, sizeof (int));
3925 LOGD ("WINDOW angle of %p is %d", win, angle);
3927 std::cerr << "ecore_x_window_prop_property_get () is failed!!!\n";
3928 LOGW ("WINDOW angle of %p FAILED!", win);
3935 #endif /* HAVE_ECOREX */
3938 * @brief Get angle for app window.
3940 * @param win_obj The Evas_Object handler of application window.
3942 * @return The angle of app window.
3944 static int efl_get_app_window_angle ()
3946 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3948 return efl_get_window_rotate_angle (efl_get_app_window ());
3954 #endif /* CANDIDATE */
3957 * @brief Get angle for ise window.
3959 * @param win_obj The Evas_Object handler of ise window.
3961 * @return The angle of ise window.
3963 static int efl_get_ise_window_angle ()
3965 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3967 return efl_get_window_rotate_angle (_ise_window);
3974 #if ISF_BUILD_CANDIDATE_UI
3977 * @brief Get angle of quickpanel window.
3979 * @return The angle of quickpanel window.
3981 static int efl_get_quickpanel_window_angle ()
3983 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3984 return efl_get_window_rotate_angle (efl_get_quickpanel_window ());
3989 * @brief Set showing effect for application window.
3991 * @param win The Evas_Object handler of application window.
3992 * @param strEffect The pointer of effect string.
3994 static void efl_set_showing_effect_for_app_window (Evas_Object *win, const char* strEffect)
3996 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3998 ecore_x_icccm_name_class_set (elm_win_xwindow_get (static_cast<Evas_Object*>(win)), strEffect, "ISF");
4003 * @brief Create elementary window.
4005 * @param strWinName The window name.
4006 * @param strEffect The window effect string.
4008 * @return The window pointer
4010 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect)
4012 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4014 Evas_Object *win = elm_win_add (NULL, strWinName, ELM_WIN_UTILITY);
4015 elm_win_title_set (win, strWinName);
4017 /* set window properties */
4018 elm_win_autodel_set (win, EINA_TRUE);
4019 elm_object_focus_allow_set (win, EINA_FALSE);
4020 elm_win_borderless_set (win, EINA_TRUE);
4021 elm_win_alpha_set (win, EINA_TRUE);
4022 elm_win_prop_focus_skip_set (win, EINA_TRUE);
4023 efl_set_showing_effect_for_app_window (win, strEffect);
4027 #endif /* CANDIDATE */
4031 * @brief Create elementary control window.
4033 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
4035 static Eina_Bool efl_create_control_window (void)
4037 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4039 /* WMSYNC, #1 Creating and registering control window */
4040 if (ecore_x_display_get () == NULL)
4043 Ecore_X_Window root = ecore_x_window_root_first_get ();
4044 _control_window = ecore_x_window_input_new (root, -100, -100, 1, 1);
4045 //ecore_x_e_virtual_keyboard_control_window_set (root, _control_window, 0, EINA_TRUE);
4047 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_CONTROL_WINDOW");
4048 ecore_x_window_prop_xid_set (root, atom, ECORE_X_ATOM_WINDOW, &_control_window, 1);
4054 * @brief Get an window's x window id.
4056 * @param name the property name.
4057 * @return X window id.
4059 static Ecore_X_Window efl_get_window (const char *name)
4061 /* Gets the XID of the window from the root window property */
4065 unsigned long nitems_return;
4066 unsigned long bytes_after_return;
4067 unsigned char *data = NULL;
4068 Ecore_X_Window window = 0;
4070 ret = XGetWindowProperty ((Display *)ecore_x_display_get (),
4071 ecore_x_window_root_get (_control_window),
4072 ecore_x_atom_get (name),
4073 0, G_MAXLONG, False, XA_WINDOW, &type_return,
4074 &format_return, &nitems_return, &bytes_after_return,
4077 if (ret == Success) {
4078 if ((type_return == XA_WINDOW) && (format_return == 32) && (data)) {
4079 window = *(Window *)data;
4082 std::cerr << "XGetWindowProperty () is failed!!!\n";
4092 * @brief Get app window's x window id.
4094 * @return the X window id of application to have focus or to request to show IME.
4096 static Ecore_X_Window efl_get_app_window (void)
4098 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4100 return efl_get_window ("_ISF_ACTIVE_WINDOW");
4104 * @brief Get clipboard window's x window id.
4106 * @return the X window id of clipboard.
4108 static Ecore_X_Window efl_get_clipboard_window (void)
4110 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4112 return efl_get_window ("CBHM_ELM_WIN");
4116 * @brief Get global natigation window's x window id.
4118 * @return the X window id of global navigation.
4120 static Ecore_X_Window efl_get_global_navigation_window (void)
4122 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4124 return efl_get_window ("GNB_WIN");
4128 * @brief Get app window's x window id.
4130 * @return the X window id of quick panel.
4132 static Ecore_X_Window efl_get_quickpanel_window (void)
4134 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4136 Ecore_X_Window rootWin = ecore_x_window_root_first_get ();
4137 Ecore_X_Window qpwin;
4138 ecore_x_window_prop_xid_get (rootWin, ecore_x_atom_get ("_E_ILLUME_QUICKPANEL_WINDOW_LIST"), ECORE_X_ATOM_WINDOW, &qpwin, 1);
4144 * @brief Get default zone geometry.
4146 * @param x The zone x position.
4147 * @param y The zone y position.
4148 * @param w The zone width.
4149 * @param h The zone height.
4151 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
4153 static Eina_Bool efl_get_default_zone_geometry_info (Ecore_X_Window root, uint *x, uint *y, uint *w, uint *h)
4155 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4157 Ecore_X_Atom zone_geometry_atom;
4158 Ecore_X_Window *zone_lists;
4163 zone_geometry_atom = ecore_x_atom_get ("_E_ILLUME_ZONE_GEOMETRY");
4164 if (!zone_geometry_atom) {
4170 num_zone_lists = ecore_x_window_prop_window_list_get (root, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, &zone_lists);
4171 if (num_zone_lists > 0) {
4172 num_ret = ecore_x_window_prop_card32_get (zone_lists[0], zone_geometry_atom, geom, 4);
4174 if (x) *x = geom[0];
4175 if (y) *y = geom[1];
4176 if (w) *w = geom[2];
4177 if (h) *h = geom[3];
4183 /* if there is no zone available */
4188 /* We must free zone_lists */
4194 #endif /* HAVE_ECOREX */
4196 #if ISF_BUILD_CANDIDATE_UI
4198 * @brief Get screen resolution.
4200 * @param width The screen width.
4201 * @param height The screen height.
4203 static void efl_get_screen_resolution (int &width, int &height)
4205 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4207 static Evas_Coord scr_w = 0, scr_h = 0;
4208 if (scr_w == 0 || scr_h == 0) {
4211 if (efl_get_default_zone_geometry_info (ecore_x_window_root_first_get (), NULL, NULL, &w, &h)) {
4215 ecore_x_window_size_get (ecore_x_window_root_first_get (), &scr_w, &scr_h);
4218 ecore_wl_screen_size_get(&scr_w, &scr_h);
4225 #endif /* CANDIDATE */
4227 //////////////////////////////////////////////////////////////////////
4228 // Start of PanelAgent Functions
4229 //////////////////////////////////////////////////////////////////////
4232 * @brief Initialize panel agent.
4234 * @param config The config string for PanelAgent.
4235 * @param display The current display.
4236 * @param resident The variable indicates whether panel will be resident.
4238 * @return true if initialize is successful, otherwise return false.
4240 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident)
4242 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4244 LOGD ("initializing panel agent");
4246 _info_manager = new InfoManager ();
4248 if (!_info_manager || !_info_manager->initialize (_info_manager, config, display, resident)) {
4249 ISF_SAVE_LOG ("panel_agent initialize fail!");
4253 _info_manager->signal_connect_focus_in (slot (slot_focus_in));
4254 _info_manager->signal_connect_focus_out (slot (slot_focus_out));
4255 _info_manager->signal_connect_expand_candidate (slot (slot_expand_candidate));
4256 _info_manager->signal_connect_contract_candidate (slot (slot_contract_candidate));
4257 _info_manager->signal_connect_set_candidate_ui (slot (slot_set_candidate_style));
4258 _info_manager->signal_connect_update_factory_info (slot (slot_update_factory_info));
4259 _info_manager->signal_connect_update_spot_location (slot (slot_update_spot_location));
4260 _info_manager->signal_connect_update_input_context (slot (slot_update_input_context));
4261 _info_manager->signal_connect_update_ise_geometry (slot (slot_update_ise_geometry));
4262 _info_manager->signal_connect_show_preedit_string (slot (slot_show_preedit_string));
4263 _info_manager->signal_connect_show_aux_string (slot (slot_show_aux_string));
4264 _info_manager->signal_connect_show_lookup_table (slot (slot_show_candidate_table));
4265 _info_manager->signal_connect_hide_preedit_string (slot (slot_hide_preedit_string));
4266 _info_manager->signal_connect_hide_aux_string (slot (slot_hide_aux_string));
4267 _info_manager->signal_connect_hide_lookup_table (slot (slot_hide_candidate_table));
4268 _info_manager->signal_connect_update_preedit_string (slot (slot_update_preedit_string));
4269 _info_manager->signal_connect_update_preedit_caret (slot (slot_update_preedit_caret));
4270 _info_manager->signal_connect_update_aux_string (slot (slot_update_aux_string));
4271 _info_manager->signal_connect_update_lookup_table (slot (slot_update_candidate_table));
4272 _info_manager->signal_connect_select_candidate (slot (slot_select_candidate));
4273 _info_manager->signal_connect_get_candidate_geometry (slot (slot_get_candidate_geometry));
4274 _info_manager->signal_connect_get_input_panel_geometry (slot (slot_get_input_panel_geometry));
4275 _info_manager->signal_connect_set_active_ise_by_uuid (slot (slot_set_active_ise));
4276 _info_manager->signal_connect_get_ise_list (slot (slot_get_ise_list));
4277 _info_manager->signal_connect_get_all_helper_ise_info (slot (slot_get_all_helper_ise_info));
4278 _info_manager->signal_connect_set_has_option_helper_ise_info(slot (slot_set_has_option_helper_ise_info));
4279 _info_manager->signal_connect_set_enable_helper_ise_info (slot (slot_set_enable_helper_ise_info));
4280 _info_manager->signal_connect_show_helper_ise_list (slot (slot_show_helper_ise_list));
4281 _info_manager->signal_connect_show_helper_ise_selector (slot (slot_show_helper_ise_selector));
4282 _info_manager->signal_connect_is_helper_ise_enabled (slot (slot_is_helper_ise_enabled));
4283 _info_manager->signal_connect_get_ise_information (slot (slot_get_ise_information));
4284 _info_manager->signal_connect_get_keyboard_ise_list (slot (slot_get_keyboard_ise_list));
4285 _info_manager->signal_connect_get_language_list (slot (slot_get_language_list));
4286 _info_manager->signal_connect_get_all_language (slot (slot_get_all_language));
4287 _info_manager->signal_connect_get_ise_language (slot (slot_get_ise_language));
4288 _info_manager->signal_connect_get_ise_info_by_uuid (slot (slot_get_ise_info));
4289 _info_manager->signal_connect_set_keyboard_ise (slot (slot_set_keyboard_ise));
4290 _info_manager->signal_connect_get_keyboard_ise (slot (slot_get_keyboard_ise));
4291 _info_manager->signal_connect_accept_connection (slot (slot_accept_connection));
4292 _info_manager->signal_connect_close_connection (slot (slot_close_connection));
4293 _info_manager->signal_connect_exit (slot (slot_exit));
4295 _info_manager->signal_connect_register_helper (slot(slot_register_helper));
4296 _info_manager->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
4297 _info_manager->signal_connect_show_ise (slot (slot_show_ise));
4298 _info_manager->signal_connect_hide_ise (slot (slot_hide_ise));
4300 _info_manager->signal_connect_will_hide_ack (slot (slot_will_hide_ack));
4302 _info_manager->signal_connect_set_keyboard_mode (slot (slot_set_keyboard_mode));
4304 _info_manager->signal_connect_candidate_will_hide_ack (slot (slot_candidate_will_hide_ack));
4305 _info_manager->signal_connect_get_ise_state (slot (slot_get_ise_state));
4306 _info_manager->signal_connect_start_default_ise (slot (slot_start_default_ise));
4307 _info_manager->signal_connect_stop_default_ise (slot (slot_stop_default_ise));
4308 _info_manager->signal_connect_show_panel (slot (slot_show_helper_ise_selector));
4309 #if ENABLE_REMOTE_INPUT
4310 _info_manager->signal_connect_remoteinput_send_input_message(slot (slot_send_remote_input_message));
4311 _info_manager->signal_connect_remoteinput_send_surrounding_text(slot (slot_recv_remote_surrounding_text));
4313 _info_manager->signal_connect_get_recent_ise_geometry (slot (slot_get_recent_ise_geometry));
4314 _info_manager->signal_connect_check_privilege_by_sockfd (slot (slot_check_privilege_by_sockfd));
4316 _info_manager->signal_connect_run_helper (slot (slot_run_helper));
4317 _info_manager->signal_connect_launch_option_application (slot (slot_launch_option_application));
4319 LOGD ("initializing panel agent succeeded");
4324 static void delete_ise_hide_timer (void)
4326 LOGD ("deleting ise_hide_timer");
4327 if (_ise_hide_timer) {
4328 ecore_timer_del (_ise_hide_timer);
4329 _ise_hide_timer = NULL;
4333 static void hide_ise ()
4335 LOGD ("send request to hide helper");
4336 String uuid = _info_manager->get_current_helper_uuid ();
4337 _info_manager->hide_helper (uuid);
4339 /* Only if we are not already in HIDE state */
4340 if (_ise_state != WINDOW_STATE_HIDE) {
4341 /* From this point, slot_get_input_panel_geometry should return hidden state geometry */
4342 _ise_state = WINDOW_STATE_WILL_HIDE;
4344 _updated_hide_state_geometry = false;
4348 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
4350 #if ISF_BUILD_CANDIDATE_UI
4351 if (_candidate_window) {
4352 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)
4353 ui_candidate_hide (true, true, true);
4355 ui_candidate_hide (true, false, true);
4357 #endif /* CANDIDATE */
4360 #ifdef HAVE_NOTIFICATION
4361 delete_notification (&ise_selector_module_noti);
4366 #if ENABLE_MULTIWINDOW_SUPPORT
4367 static Eina_Bool ise_hide_timeout (void *data)
4369 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4371 delete_ise_hide_timer ();
4374 return ECORE_CALLBACK_CANCEL;
4379 * @brief Insert data to ime_info table.
4381 * @param list The list to store uuid
4383 * @return true if it is successful, otherwise return false.
4385 static bool update_ise_list (std::vector<String> &list)
4387 std::vector<String> uuids;
4388 std::vector<TOOLBAR_MODE_T> modes;
4389 std::vector<ImeInfoDB>::iterator iter;
4392 if (_ime_info.size() == 0) {
4393 if (isf_pkg_select_all_ime_info_db(_ime_info) == 0)
4397 /* Update _groups */
4399 std::vector<String> ise_langs;
4400 for (size_t i = 0; i < _ime_info.size (); ++i) {
4401 scim_split_string_list(ise_langs, _ime_info[i].languages);
4402 for (size_t j = 0; j < ise_langs.size (); j++) {
4403 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
4404 _groups[ise_langs[j]].push_back (i);
4409 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
4410 uuids.push_back(iter->appid);
4411 modes.push_back(iter->mode);
4414 if (uuids.size() > 0) {
4418 _info_manager->update_ise_list (list);
4420 if (_initial_ise_uuid.length () > 0) {
4421 String active_uuid = _initial_ise_uuid;
4422 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
4423 if (std::find (uuids.begin (), uuids.end (), default_uuid) == uuids.end ()) {
4424 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (modes[get_ise_index (_initial_ise_uuid)] != TOOLBAR_KEYBOARD_MODE)) {
4425 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4428 if (set_active_ise (active_uuid, _soft_keyboard_launched) == false) {
4429 if (_initial_ise_uuid.compare (active_uuid)) {
4430 LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
4431 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
4434 } else if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) { // Check whether keyboard engine is installed
4435 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
4436 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
4437 if (std::find (uuids.begin (), uuids.end (), keyboard_uuid) == uuids.end ()) {
4438 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4439 _info_manager->change_factory (active_uuid);
4440 _config->write (IMENGINE_KEY, active_uuid);
4447 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
4449 if (_ime_info.size () > 0 && _ime_info[0].display_lang.compare(lang_str) == 0)
4450 _locale_string = String (lang_str);
4456 LOGW ("No IME list");
4458 #ifdef HAVE_PKGMGR_INFO
4460 int ret = package_manager_create (&pkgmgr);
4461 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4462 ret = package_manager_set_event_cb (pkgmgr, _package_manager_event_cb, NULL);
4463 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4464 LOGD ("package_manager_set_event_cb succeeded.");
4467 LOGE ("package_manager_set_event_cb failed(%d)", ret);
4471 LOGE ("package_manager_create failed(%d)", ret);
4480 * @brief Focus in slot function for PanelAgent.
4482 static void slot_focus_in (void)
4484 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4487 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
4488 if (_launch_ise_on_request && !_soft_keyboard_launched) {
4489 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
4490 if (uuid.length () > 0 && (_ime_info[get_ise_index(uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
4491 LOGD ("Start helper (%s)", uuid.c_str ());
4493 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
4494 if (_info_manager->start_helper (uuid))
4495 _soft_keyboard_launched = true;
4500 #if ISF_BUILD_CANDIDATE_UI
4501 ui_candidate_delete_destroy_timer ();
4502 #endif /* CANDIDATE */
4506 * @brief Focus out slot function for PanelAgent.
4508 static void slot_focus_out (void)
4510 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4514 #if ISF_BUILD_CANDIDATE_UI
4515 ui_candidate_delete_destroy_timer ();
4516 _destroy_timer = ecore_timer_add (ISF_CANDIDATE_DESTROY_DELAY, ui_candidate_destroy_timeout, NULL);
4517 #endif /* CANDIDATE */
4521 * @brief Expand candidate slot function for PanelAgent.
4523 static void slot_expand_candidate (void)
4525 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4526 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4529 #if ISF_BUILD_CANDIDATE_UI
4530 if (_candidate_area_2 && !_candidate_area_2_visible)
4531 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
4532 #endif /* CANDIDATE */
4536 * @brief Contract candidate slot function for PanelAgent.
4538 static void slot_contract_candidate (void)
4540 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4542 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4545 #if ISF_BUILD_CANDIDATE_UI
4546 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
4547 #endif /* CANDIDATE */
4551 * @brief Set candidate style slot function for PanelAgent.
4553 * @param portrait_line The displayed line number for portrait.
4554 * @param mode The candidate mode.
4556 static void slot_set_candidate_style (int portrait_line, int mode)
4558 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " display_line:" << portrait_line << " mode:" << mode << "\n";
4559 #if ISF_BUILD_CANDIDATE_UI
4560 if ((portrait_line != _candidate_port_line) || (mode != _candidate_mode)) {
4561 _candidate_mode = (ISF_CANDIDATE_MODE_T)mode;
4562 _candidate_port_line = (ISF_CANDIDATE_PORTRAIT_LINE_T)portrait_line;
4563 _soft_candidate_width = 0;
4564 _soft_candidate_height = 0;
4566 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4567 if (_candidate_window)
4568 ui_destroy_candidate_window ();
4573 if (_candidate_window)
4574 ui_create_candidate_window ();
4576 #endif /* CANDIDATE */
4579 #if defined(HAVE_NOTIFICATION) || defined(HAVE_ECOREX)
4580 static unsigned int get_ise_count (TOOLBAR_MODE_T mode, bool valid_helper)
4582 unsigned int ise_count = 0;
4583 for (unsigned int i = 0; i < _ime_info.size (); i++) {
4584 if (mode == _ime_info[i].mode) {
4585 if (mode == TOOLBAR_KEYBOARD_MODE || !valid_helper)
4587 else if (_ime_info[i].is_enabled)
4597 * @brief Update keyboard ISE information slot function for PanelAgent.
4599 * @param info The information of current Keyboard ISE.
4601 static void slot_update_factory_info (const PanelFactoryInfo &info)
4603 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4605 String ise_name = info.name;
4607 String old_ise = _info_manager->get_current_ise_name ();
4608 #if ISF_BUILD_CANDIDATE_UI
4609 if (old_ise != ise_name) {
4610 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && _candidate_window) {
4611 ui_destroy_candidate_window ();
4614 #endif /* CANDIDATE */
4616 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
4618 if (TOOLBAR_HELPER_MODE == mode)
4619 ise_name = _ime_info[get_ise_index (_info_manager->get_current_helper_uuid())].label;
4621 if (ise_name.length () > 0)
4622 _info_manager->set_current_ise_name (ise_name);
4624 #ifdef HAVE_NOTIFICATION
4626 if (old_ise != ise_name) {
4627 if (TOOLBAR_KEYBOARD_MODE == mode) {
4628 char noti_msg[256] = {0};
4629 unsigned int keyboard_ise_count = get_ise_count (TOOLBAR_KEYBOARD_MODE, false);
4630 if (keyboard_ise_count == 0) {
4631 LOGD ("the number of keyboard ise is %d", keyboard_ise_count);
4634 else if (keyboard_ise_count >= 2) {
4635 snprintf (noti_msg, sizeof (noti_msg), _("%s selected"), ise_name.c_str ());
4637 else if (keyboard_ise_count == 1) {
4638 snprintf (noti_msg, sizeof (noti_msg), _("Only %s available"), ise_name.c_str ());
4641 notification_status_message_post (noti_msg);
4642 LOGD ("%s", noti_msg);
4650 * @brief Update cursor position slot function for PanelAgent.
4652 * @param x The x position of current cursor.
4653 * @param y The bottom y position of current cursor.
4654 * @param top_y The top y position of current cursor.
4656 static void slot_update_spot_location (int x, int y, int top_y)
4658 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4660 #if ISF_BUILD_CANDIDATE_UI
4661 if (x >= 0 && x < _screen_height && y >= 0 && y < _screen_height) {
4662 _spot_location_x = x;
4663 _spot_location_y = y;
4664 _spot_location_top_y = top_y;
4666 ui_settle_candidate_window ();
4668 #endif /* CANDIDATE */
4672 * @brief The input context of ISE is changed.
4674 * @param type The event type.
4675 * @param value The event value.
4677 static void slot_update_input_context (int type, int value)
4682 * @brief Update ise geometry.
4684 * @param x The x position in screen.
4685 * @param y The y position in screen.
4686 * @param width The ISE window width.
4687 * @param height The ISE window height.
4689 static void slot_update_ise_geometry (int x, int y, int width, int height)
4691 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
4693 LOGD ("x : %d , y : %d , width : %d , height : %d, _ise_state : %d", x, y, width, height, _ise_state);
4695 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
4696 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4697 /*IF ISE sent the ise_geometry information when the current_keyboard_mode is H/W mode and candidate_mode is SOFT_CANDIDATE,
4698 It means that given geometry information is for the candidate window */
4699 set_soft_candidate_geometry (x, y, width, height);
4707 _ise_height = height;
4709 #if ISF_BUILD_CANDIDATE_UI
4710 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
4711 ui_settle_candidate_window ();
4713 #endif /* CANDIDATE */
4715 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
4716 _ise_reported_geometry.valid = true;
4717 _ise_reported_geometry.angle = efl_get_ise_window_angle ();
4718 _ise_reported_geometry.geometry.pos_x = x;
4719 _ise_reported_geometry.geometry.pos_y = y;
4720 _ise_reported_geometry.geometry.width = width;
4721 _ise_reported_geometry.geometry.height = height;
4722 if (_ise_state == WINDOW_STATE_SHOW) {
4724 set_keyboard_geometry_atom_info (_app_window, _ise_reported_geometry.geometry);
4726 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
4732 * @brief Show preedit slot function for PanelAgent.
4734 static void slot_show_preedit_string (void)
4736 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4738 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4741 #if ISF_BUILD_CANDIDATE_UI
4742 if (_preedit_window == NULL) {
4743 ui_create_preedit_window ();
4745 /* Move preedit window according to candidate window position */
4746 if (_candidate_window) {
4747 /* Get candidate window position */
4748 int x, y, width, height;
4749 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
4751 int height2 = ui_candidate_get_valid_height ();
4752 int angle = efl_get_app_window_angle ();
4755 x -= _preedit_height;
4756 y = _screen_height - _preedit_width;
4757 } else if (_candidate_angle == 270) {
4759 } else if (_candidate_angle == 180) {
4760 x = _screen_width - _preedit_width;
4763 y -= _preedit_height;
4766 if (_preedit_window)
4767 evas_object_move (_preedit_window, x, y);
4771 if (_preedit_window && evas_object_visible_get (_preedit_window))
4774 slot_show_candidate_table ();
4776 if (_preedit_window)
4777 evas_object_show (_preedit_window);
4778 #endif /* CANDIDATE */
4782 * @brief Show aux slot function for PanelAgent.
4784 static void slot_show_aux_string (void)
4786 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4788 #if ISF_BUILD_CANDIDATE_UI
4789 if (_candidate_window == NULL)
4790 ui_create_candidate_window ();
4792 if (_aux_area == NULL || _aux_area_visible)
4795 evas_object_show (_aux_area);
4796 _aux_area_visible = true;
4797 ui_candidate_window_adjust ();
4799 LOGD ("calling ui_candidate_show ()");
4800 ui_candidate_show ();
4801 ui_settle_candidate_window ();
4802 ui_candidate_delete_destroy_timer ();
4803 #endif /* CANDIDATE */
4807 * @brief Show candidate table slot function for PanelAgent.
4809 static void slot_show_candidate_table (void)
4811 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4812 _info_manager->helper_candidate_show ();
4816 #if ISF_BUILD_CANDIDATE_UI
4817 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4818 if (_candidate_window == NULL)
4819 ui_create_candidate_window ();
4822 if (_candidate_state == WINDOW_STATE_SHOW &&
4823 (_candidate_area_1_visible || _candidate_area_2_visible)) {
4824 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
4829 evas_object_show (_candidate_area_1);
4830 _candidate_area_1_visible = true;
4831 ui_candidate_window_adjust ();
4833 LOGD ("calling ui_candidate_show ()");
4834 ui_candidate_show ();
4835 ui_settle_candidate_window ();
4836 ui_candidate_delete_destroy_timer ();
4838 #ifdef HAVE_FEEDBACK
4839 int feedback_result = feedback_initialize ();
4841 if (FEEDBACK_ERROR_NONE == feedback_result) {
4842 LOGD ("Feedback initialize successful");
4843 feedback_initialized = true;
4845 LOGW ("Feedback initialize fail : %d", feedback_result);
4846 feedback_initialized = false;
4848 #endif /* HAVE_FEEDBACK */
4849 #endif /* CANDIDATE */
4853 * @brief Hide preedit slot function for PanelAgent.
4855 static void slot_hide_preedit_string (void)
4857 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4859 #if ISF_BUILD_CANDIDATE_UI
4860 if (!_preedit_window || !evas_object_visible_get (_preedit_window))
4863 evas_object_hide (_preedit_window);
4864 #endif /* CANDIDATE */
4868 * @brief Hide aux slot function for PanelAgent.
4870 static void slot_hide_aux_string (void)
4872 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4874 #if ISF_BUILD_CANDIDATE_UI
4875 if (!_aux_area || !_aux_area_visible)
4878 evas_object_hide (_aux_area);
4879 _aux_area_visible = false;
4880 elm_scroller_region_show (_aux_area, 0, 0, 10, 10);
4881 ui_candidate_window_adjust ();
4883 LOGD ("calling ui_candidate_hide (false, true, true)");
4884 ui_candidate_hide (false, true, true);
4885 ui_settle_candidate_window ();
4887 if (ui_candidate_can_be_hide ()) {
4888 _candidate_show_requested = false;
4889 LOGD ("setting _show_candidate_requested to FALSE");
4891 #endif /* CANDIDATE */
4895 * @brief Hide candidate table slot function for PanelAgent.
4897 static void slot_hide_candidate_table (void)
4899 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4901 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4902 _info_manager->helper_candidate_hide ();
4906 #if ISF_BUILD_CANDIDATE_UI
4907 if (!_candidate_area_1 || _candidate_state == WINDOW_STATE_WILL_HIDE)
4910 if (_candidate_area_1_visible || _candidate_area_2_visible) {
4911 bool bForce = false;
4912 if (_candidate_area_1_visible) {
4913 if (_aux_area_visible) {
4914 evas_object_hide (_candidate_area_1);
4915 _candidate_area_1_visible = false;
4916 evas_object_hide (_more_btn);
4918 /* Let's not actually hide the _candidate_area_1 object, for the case that
4919 even if the application replies CANDIDATE_WILL_HIDE_ACK a little late,
4920 it is better to display the previous candidates instead of blank screen */
4921 _candidate_area_1_visible = false;
4925 if (_candidate_area_2_visible) {
4926 evas_object_hide (_candidate_area_2);
4927 _candidate_area_2_visible = false;
4928 evas_object_hide (_scroller_bg);
4929 evas_object_hide (_close_btn);
4930 _info_manager->candidate_more_window_hide ();
4932 ui_candidate_window_adjust ();
4934 LOGD ("calling ui_candidate_hide (%d, true, true)", bForce);
4935 ui_candidate_hide (bForce, true, true);
4936 ui_settle_candidate_window ();
4939 #ifdef HAVE_FEEDBACK
4940 int feedback_result = feedback_deinitialize ();
4942 if (FEEDBACK_ERROR_NONE == feedback_result)
4943 LOGD ("Feedback deinitialize successful");
4945 LOGW ("Feedback deinitialize fail : %d", feedback_result);
4947 feedback_initialized = false;
4950 if (ui_candidate_can_be_hide ()) {
4951 _candidate_show_requested = false;
4952 LOGD ("setting _show_candidate_requested to FALSE");
4954 #endif /* CANDIDATE */
4958 * @brief Update preedit slot function for PanelAgent.
4960 * @param str The new preedit string.
4961 * @param attrs The attribute list of new preedit string.
4963 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret)
4965 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " string=" << str << "\n";
4967 #if ISF_BUILD_CANDIDATE_UI
4968 if (str.length () <= 0)
4971 if (_preedit_window == NULL || !evas_object_visible_get (_preedit_window)) {
4972 slot_show_preedit_string ();
4975 int x, y, width, height, candidate_width;
4976 evas_object_text_text_set (_tmp_preedit_text, str.c_str ());
4977 evas_object_geometry_get (_tmp_preedit_text, &x, &y, &width, &height);
4978 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &candidate_width, &height);
4979 _preedit_width = (width + ISF_PREEDIT_BORDER * 2) < candidate_width ? (width + ISF_PREEDIT_BORDER * 2) : candidate_width;
4981 /* Resize preedit window and avoid text blink */
4982 int old_width, old_height;
4983 evas_object_geometry_get (_preedit_window, &x, &y, &old_width, &old_height);
4984 if (old_width < _preedit_width) {
4985 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4986 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4988 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4989 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4992 /* Move preedit window */
4993 if (_candidate_angle == 90 || _candidate_angle == 180) {
4994 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_preedit_window)), &x, &y, &width, &height);
4995 if (_candidate_angle == 90) {
4996 y = _screen_height - _preedit_width;
4997 } else if (_candidate_angle == 180) {
4998 x = _screen_width - _preedit_width;
5000 evas_object_move (_preedit_window, x, y);
5002 #endif /* CANDIDATE */
5006 * @brief Update caret slot function for PanelAgent.
5008 * @param caret The caret position.
5010 static void slot_update_preedit_caret (int caret)
5012 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " caret=" << caret << "\n";
5015 #if ISF_BUILD_CANDIDATE_UI
5017 * @brief Set highlight text color and background color for edje object.
5019 * @param item The edje object pointer.
5020 * @param nForeGround The text color.
5021 * @param nBackGround The background color.
5022 * @param bSetBack The flag for background color.
5024 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack)
5026 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5028 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
5029 if (edje_object_color_class_get (item, "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
5030 r = SCIM_RGB_COLOR_RED (nForeGround);
5031 g = SCIM_RGB_COLOR_GREEN (nForeGround);
5032 b = SCIM_RGB_COLOR_BLUE (nForeGround);
5033 edje_object_color_class_set (item, "text_color", r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
5035 if (bSetBack && edje_object_color_class_get (item, "rect_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
5036 r = SCIM_RGB_COLOR_RED (nBackGround);
5037 g = SCIM_RGB_COLOR_GREEN (nBackGround);
5038 b = SCIM_RGB_COLOR_BLUE (nBackGround);
5039 edje_object_color_class_set (item, "rect_color", r, g, b, 255, r2, g2, b2, a2, r3, g3, b3, a3);
5042 #endif /* CANDIDATE */
5045 * @brief Update aux slot function for PanelAgent.
5047 * @param str The new aux string.
5048 * @param attrs The attribute list of new aux string.
5050 static void slot_update_aux_string (const String &str, const AttributeList &attrs)
5052 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5053 #if ISF_BUILD_CANDIDATE_UI
5054 if (_candidate_window == NULL)
5055 ui_create_candidate_window ();
5057 if (!_aux_area || (str.length () <= 0))
5060 if (!_aux_area_visible) {
5061 LOGD ("calling ui_candidate_show ()");
5062 ui_candidate_show ();
5063 slot_show_aux_string ();
5066 int x, y, width, height, item_width = 0;
5067 unsigned int window_width = 0, count = 0, i;
5069 Evas_Object *aux_edje = NULL;
5071 /* Get highlight item index */
5072 int aux_index = -1, aux_start = 0, aux_end = 0;
5073 String strAux = str;
5074 bool bSetBack = false;
5075 uint32 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
5076 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
5077 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5078 if (aux_index == -1 && ait->get_type () == SCIM_ATTR_DECORATE) {
5079 aux_index = ait->get_value ();
5080 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
5081 nForeGround = ait->get_value ();
5082 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
5083 nBackGround = ait->get_value ();
5088 std::vector<String> aux_list;
5089 scim_split_string_list (aux_list, strAux, '|');
5091 if (_aux_items.size () > 0) {
5092 for (i = 0; i < _aux_items.size (); i++)
5093 evas_object_del (_aux_items [i]);
5094 _aux_items.clear ();
5096 if (_aux_seperates.size () > 0) {
5097 for (i = 0; i < _aux_seperates.size (); i++)
5098 evas_object_del (_aux_seperates [i]);
5099 _aux_seperates.clear ();
5102 int seperate_width = 4;
5103 int seperate_height = 52 * _height_rate;
5104 Evas *evas = evas_object_evas_get (_candidate_window);
5105 for (i = 0; i < aux_list.size (); i++) {
5107 Evas_Object *seperate_item = edje_object_add (evas);
5108 edje_object_file_set (seperate_item, _candidate_edje_file.c_str (), "seperate_line");
5109 evas_object_size_hint_min_set (seperate_item, seperate_width, seperate_height);
5110 elm_table_pack (_aux_table, seperate_item, 2 * i - 1, 0, 1, 1);
5111 evas_object_show (seperate_item);
5112 _aux_seperates.push_back (seperate_item);
5116 aux_edje = edje_object_add (evas);
5117 edje_object_file_set (aux_edje, _candidate_edje_file.c_str (), "aux");
5118 edje_object_part_text_set (aux_edje, "aux", aux_list [i].c_str ());
5119 edje_object_text_class_set (aux_edje, "tizen", _candidate_font_name.c_str (), _aux_font_size);
5120 elm_table_pack (_aux_table, aux_edje, 2 * i, 0, 1, 1);
5121 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_AUX));
5122 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5123 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_AUX));
5124 evas_object_show (aux_edje);
5125 _aux_items.push_back (aux_edje);
5126 /* if (i == (unsigned int)aux_index)
5127 edje_object_signal_emit (aux_edje, "aux,state,selected", "aux");
5129 edje_object_signal_emit (aux_edje, "aux,state,unselected", "aux");
5131 evas_object_text_text_set (_tmp_aux_text, aux_list [i].c_str ());
5132 evas_object_geometry_get (_tmp_aux_text, &x, &y, &width, &height);
5133 item_width = width + 2*_blank_width;
5134 item_width = item_width > _item_min_width ? item_width : _item_min_width;
5135 evas_object_size_hint_min_set (aux_edje, item_width, _aux_height);
5136 if (aux_index == (int)i || (aux_index == -1 && i == 0)) {
5137 aux_start = window_width;
5138 aux_end = window_width + item_width;
5140 window_width = window_width + item_width + 4;
5143 // Set highlight item
5144 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5145 if (ait->get_type () == SCIM_ATTR_DECORATE) {
5146 unsigned int index = ait->get_value ();
5147 if (index < _aux_items.size ())
5148 set_highlight_color (_aux_items [index], nForeGround, nBackGround, bSetBack);
5153 elm_scroller_region_get (_aux_area, &x, &y, &w, &h);
5154 item_width = aux_end - aux_start;
5155 if (item_width > 0) {
5156 if (item_width >= w)
5157 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
5158 else if (aux_end > x + w)
5159 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
5160 else if (aux_start < x)
5161 elm_scroller_region_show (_aux_area, aux_start, y, w, h);
5164 #endif /* CANDIDATE */
5167 #if ISF_BUILD_CANDIDATE_UI
5169 * @brief Update candidate/associate table.
5171 * @param table_type The table type.
5172 * @param table The lookup table for candidate or associate.
5174 static void update_table (int table_type, const LookupTable &table)
5176 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << table.get_current_page_size () << ")\n";
5178 int item_num = table.get_current_page_size ();
5185 AttributeList attrs;
5186 int i, x, y, item_0_width = 0;
5190 int seperate_width = 2;
5191 int seperate_height = 52 * _height_rate;
5192 int line_width = _candidate_scroll_width;
5193 int line_height = _v_padding;
5194 int total_width = 0;
5195 int current_width = 0;
5198 int more_item_count = 0;
5199 int scroll_0_width = _candidate_scroll_0_width_min;
5200 int cursor_pos = table.get_cursor_pos ();
5201 int cursor_line = 0;
5203 if (_candidate_angle == 90 || _candidate_angle == 270)
5204 scroll_0_width = _screen_height - _more_btn_width - _h_padding;
5206 scroll_0_width = _screen_width - _more_btn_width - _h_padding;
5208 _candidate_image_count = 0;
5209 _candidate_text_count = 0;
5210 _candidate_pop_image_count = 0;
5211 _candidate_display_number = 0;
5212 _candidate_row_items.clear ();
5214 Evas *evas = evas_object_evas_get (_candidate_window);
5215 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
5216 if (_candidate_0 [i]) {
5217 evas_object_del (_candidate_0 [i]);
5218 _candidate_0 [i] = NULL;
5220 if (_seperate_0 [i]) {
5221 evas_object_del (_seperate_0 [i]);
5222 _seperate_0 [i] = NULL;
5224 if (_seperate_items [i]) {
5225 evas_object_del (_seperate_items [i]);
5226 _seperate_items [i] = NULL;
5229 evas_object_del (_line_0 [i]);
5232 if (_line_items [i]) {
5233 evas_object_del (_line_items [i]);
5234 _line_items [i] = NULL;
5238 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
5240 bool bHighLight = false;
5241 bool bSetBack = false;
5242 uint32 nForeGround = SCIM_RGB_COLOR (249, 249, 249);
5243 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
5244 attrs = table.get_attributes_in_current_page (i);
5245 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5246 if (ait->get_type () == SCIM_ATTR_DECORATE && ait->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
5248 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
5249 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
5251 nForeGround = ait->get_value ();
5252 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
5254 nBackGround = ait->get_value ();
5258 wcs = table.get_candidate_in_current_page (i);
5259 mbs = utf8_wcstombs (wcs);
5261 if (!_candidate_0 [i] && total_width <= scroll_0_width) {
5262 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5263 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));
5264 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5265 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_0));
5267 /* Check whether this item is the last one */
5268 if (i == item_num - 1) {
5269 if (_candidate_angle == 90 || _candidate_angle == 270)
5270 scroll_0_width = _candidate_land_width;
5272 scroll_0_width = _candidate_port_width;
5275 /* Add first item */
5277 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5278 evas_object_show (_candidate_0 [i]);
5279 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5280 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, 0, item_0_width, _item_min_height);
5281 total_width += item_0_width;
5282 _candidate_display_number++;
5285 total_width += (item_0_width + seperate_width);
5286 if (total_width <= scroll_0_width) {
5287 _seperate_0 [i] = edje_object_add (evas);
5288 edje_object_file_set (_seperate_0 [i], _candidate_edje_file.c_str (), "seperate_line");
5289 evas_object_size_hint_min_set (_seperate_0 [i], seperate_width, seperate_height);
5290 elm_table_pack (_candidate_0_table, _seperate_0 [i],
5291 total_width - item_0_width - seperate_width,
5292 line_0*(_item_min_height+line_height) + (_item_min_height - seperate_height)/2,
5293 seperate_width, seperate_height);
5294 evas_object_show (_seperate_0 [i]);
5295 evas_object_show (_candidate_0 [i]);
5296 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5297 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);
5298 _candidate_display_number++;
5300 } else if ((_candidate_angle == 0 || _candidate_angle == 180) &&
5301 (_candidate_port_line > 1 && (line_0 + 1) < _candidate_port_line)) {
5303 scroll_0_width = _candidate_scroll_0_width_min;
5304 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5305 evas_object_show (_candidate_0 [i]);
5306 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5307 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
5308 total_width = item_0_width;
5309 _candidate_display_number++;
5311 _candidate_row_items.push_back (i - nLast);
5315 _candidate_row_items.push_back (i - nLast);
5321 if (!_candidate_0 [i]) {
5322 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5323 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));
5324 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5325 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_ITEMS));
5327 if (current_width > 0 && current_width + item_0_width > _candidate_scroll_width) {
5331 _candidate_row_items.push_back (i - nLast);
5333 if (cursor_pos >= i)
5336 if (current_width == 0 && !_line_items [i]) {
5337 _line_items [i] = edje_object_add (evas);
5338 edje_object_file_set (_line_items [i], _candidate_edje_file.c_str (), "popup_line");
5339 evas_object_size_hint_min_set (_line_items [i], line_width, line_height);
5341 y = line_count*(_item_min_height+line_height);
5342 elm_table_pack (_candidate_table, _line_items [i], x, y, line_width, line_height);
5343 evas_object_show (_line_items [i]);
5345 if (current_width != 0 && !_seperate_items [i]) {
5346 _seperate_items [i] = edje_object_add (evas);
5347 edje_object_file_set (_seperate_items [i], _candidate_edje_file.c_str (), "seperate_line");
5348 evas_object_size_hint_min_set (_seperate_items [i], seperate_width, seperate_height);
5350 y = line_count*(_item_min_height+line_height) + line_height + (_item_min_height - seperate_height)/2;
5351 elm_table_pack (_candidate_table, _seperate_items [i], x, y, seperate_width, seperate_height);
5352 evas_object_show (_seperate_items [i]);
5353 current_width += seperate_width;
5356 y = line_count*(_item_min_height+line_height) + line_height;
5357 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5358 evas_object_show (_candidate_0 [i]);
5359 elm_table_pack (_candidate_table, _candidate_0 [i], x, y, item_0_width, _item_min_height);
5360 current_width += item_0_width;
5362 if (candidate_expanded == false && !bHighLight)
5365 candidate_expanded = true;
5369 for (i = 1; i < _candidate_port_line; i++) {
5370 if ((_candidate_angle == 0 || _candidate_angle == 180)) {
5371 if (_line_0 [i] == NULL) {
5372 _line_0 [i] = edje_object_add (evas);
5373 edje_object_file_set (_line_0 [i], _candidate_edje_file.c_str (), "popup_line");
5374 evas_object_size_hint_min_set (_line_0 [i], line_width, line_height);
5376 y = i * (_item_min_height + line_height) - line_height;
5377 elm_table_pack (_candidate_0_table, _line_0 [i], x, y, line_width, line_height);
5378 evas_object_show (_line_0 [i]);
5381 // Create blank line
5382 if (line_0 + 1 < _candidate_port_line && i > line_0) {
5383 int nIndex = item_num + i;
5384 nIndex = nIndex < SCIM_LOOKUP_TABLE_MAX_PAGESIZE ? nIndex : SCIM_LOOKUP_TABLE_MAX_PAGESIZE - 1;
5385 _seperate_0 [nIndex] = edje_object_add (evas);
5386 edje_object_file_set (_seperate_0 [nIndex], _candidate_edje_file.c_str (), "seperate_line");
5387 evas_object_size_hint_min_set (_seperate_0 [nIndex], seperate_width, _item_min_height);
5388 elm_table_pack (_candidate_0_table, _seperate_0 [nIndex],
5389 0, i*(_item_min_height+line_height), seperate_width, _item_min_height);
5391 } else if (_line_0 [i]) {
5392 evas_object_del (_line_0 [i]);
5397 _candidate_row_items.push_back (item_num - nLast); /* Add the number of last row */
5398 _info_manager->update_displayed_candidate_number (_candidate_display_number);
5399 _info_manager->update_candidate_item_layout (_candidate_row_items);
5400 if (more_item_count == 0) {
5401 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
5402 evas_object_hide (_more_btn);
5403 evas_object_hide (_close_btn);
5404 } else if (!_candidate_area_2_visible) {
5405 evas_object_show (_more_btn);
5406 evas_object_hide (_close_btn);
5408 evas_object_hide (_more_btn);
5409 evas_object_show (_close_btn);
5413 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
5415 int line_h = _item_min_height + _v_padding;
5416 int cursor_y = cursor_line * line_h;
5418 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
5419 } else if (cursor_y >= y + h) {
5420 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
5425 #endif /* CANDIDATE */
5428 * @brief Update candidate table slot function for PanelAgent.
5430 * @param table The lookup table for candidate.
5432 static void slot_update_candidate_table (const LookupTable &table)
5434 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5436 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5437 _info_manager->update_helper_lookup_table (table);
5441 #if ISF_BUILD_CANDIDATE_UI
5442 if (_candidate_window == NULL)
5443 ui_create_candidate_window ();
5445 if (!_candidate_window || table.get_current_page_size () < 0)
5448 if (evas_object_visible_get (_candidate_area_2)) {
5449 candidate_expanded = true;
5451 candidate_expanded = false;
5454 update_table (ISF_CANDIDATE_TABLE, table);
5455 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
5456 ui_tts_focus_rect_hide ();
5457 #endif /* CANDIDATE */
5461 * @brief Send selected candidate index.
5463 * @param selected candidate string index number.
5465 static void slot_select_candidate (int index)
5467 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5468 _info_manager->select_candidate (index);
5472 * @brief Get candidate geometry slot function for PanelAgent.
5474 * @param info The data is used to store candidate position and size.
5476 static void slot_get_candidate_geometry (struct rectinfo &info)
5483 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5487 info.height = height;
5491 #if ISF_BUILD_CANDIDATE_UI
5492 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5493 /* Get candidate window position */
5494 /*ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);*/
5495 /* Get exact candidate window size */
5497 evas_object_geometry_get (_candidate_window, &x2, &y2, &width, &height);*/
5501 width = _candidate_width;
5502 height = _candidate_height;
5504 #endif /* CANDIDATE */
5509 info.height = height;
5511 LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5512 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5513 << " width:" << info.width << " height:" << info.height << "\n";
5517 * @brief Get input panel geometry slot function for PanelAgent.
5519 * @param info The data is used to store input panel position and size.
5521 static void slot_get_input_panel_geometry (struct rectinfo &info)
5523 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
5528 #if ISF_BUILD_CANDIDATE_UI
5529 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5530 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5531 info.width = _candidate_width;
5532 info.height = _candidate_height;
5534 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5535 info.width = _soft_candidate_width;
5536 info.height = _soft_candidate_height;
5538 int angle = efl_get_app_window_angle ();
5539 if (angle == 90 || angle == 270)
5540 info.pos_y = _screen_width - info.height;
5542 info.pos_y = _screen_height - info.height;
5544 info = get_ise_geometry ();
5545 if (_ise_state != WINDOW_STATE_SHOW) {
5549 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5550 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5551 int height = ui_candidate_get_valid_height ();
5553 if ((_candidate_height - height) > _ise_height) {
5554 info.pos_y = info.pos_y + info.height - _candidate_height;
5555 info.height = _candidate_height;
5557 info.pos_y -= height;
5558 info.height += height;
5563 #endif /* CANDIDATE */
5566 LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5567 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5568 << " width:" << info.width << " height:" << info.height << "\n";
5572 * @brief Get the recent input panel geometry slot function for PanelAgent.
5574 * @param angle the rotation angle of application window.
5575 * @param info The data is used to store input panel position and size.
5577 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info)
5579 LOGD ("slot_get_recent_ise_geometry");
5581 /* If we have geometry reported by ISE, use the geometry information */
5586 if (angle == 0 || angle == 180) {
5587 if (_portrait_recent_ise_geometry.valid) {
5588 info = _portrait_recent_ise_geometry.geometry;
5593 if (_landscape_recent_ise_geometry.valid) {
5594 info = _landscape_recent_ise_geometry.geometry;
5605 static bool slot_check_privilege_by_sockfd (int client_id, String privilege)
5607 PrivilegeChecker privilegeChecker (client_id);
5609 bool priv_ret = privilegeChecker.checkPrivilege (privilege.c_str ());
5611 if (priv_ret == false)
5612 LOGW ("Failed to check privilege (%s)", privilege.c_str ());
5614 LOGD ("Succeeded to check privilege (%s)", privilege.c_str ());
5620 * @brief Set active ISE slot function for PanelAgent.
5622 * @param uuid The active ISE's uuid.
5623 * @param changeDefault The flag for changing default ISE.
5625 static void slot_set_active_ise (const String &uuid, bool changeDefault)
5627 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << uuid << ")\n";
5629 bool invalid = false;
5631 #ifdef HAVE_PKGMGR_INFO
5632 /* When changing the active (default) keyboard, initialize ime_info DB if appid is invalid.
5633 This may be necessary if IME packages are changed while panel process is terminated. */
5634 pkgmgrinfo_appinfo_h handle = NULL;
5635 /* Try to get in global packages */
5636 int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
5637 if (ret != PMINFO_R_OK) {
5638 LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
5639 /* This might happen if IME is uninstalled while the panel process is inactive.
5640 The variable uuid would be invalid, so set_active_ise() would return false. */
5645 pkgmgrinfo_appinfo_destroy_appinfo (handle);
5649 _initialize_ime_info ();
5650 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5652 else if (set_active_ise (uuid, _soft_keyboard_launched) == false) {
5653 if (_initial_ise_uuid.compare (uuid))
5654 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5659 * @brief Get all ISEs list slot function for PanelAgent.
5661 * @param list The list is used to store all ISEs.
5663 * @return true if this operation is successful, otherwise return false.
5665 static bool slot_get_ise_list (std::vector<String> &list)
5667 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5669 bool result = false;
5671 std::vector<String> uuids;
5672 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5673 uuids.push_back(iter->appid);
5675 if (_ime_info.size () > 0) {
5680 result = update_ise_list (list);
5687 * @brief Get all Helper ISE information from ime_info DB.
5689 * @param info This is used to store all Helper ISE information.
5691 * @return true if this operation is successful, otherwise return false.
5693 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info)
5695 bool result = false;
5696 String active_ime_appid;
5698 info.appid.clear ();
5699 info.label.clear ();
5700 info.is_enabled.clear ();
5701 info.is_preinstalled.clear ();
5702 info.has_option.clear ();
5704 if (_ime_info.size() == 0)
5705 isf_pkg_select_all_ime_info_db (_ime_info);
5707 //active_ime_appid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5708 if (_info_manager) {
5709 active_ime_appid = _info_manager->get_current_helper_uuid ();
5712 if (_ime_info.size () > 0) {
5713 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
5714 if (iter->mode == TOOLBAR_HELPER_MODE) {
5715 info.appid.push_back (iter->appid);
5716 info.label.push_back (iter->label);
5717 info.is_enabled.push_back (iter->is_enabled);
5718 info.is_preinstalled.push_back (iter->is_preinstalled);
5719 info.has_option.push_back (static_cast<uint32>(iter->has_option));
5729 * @brief Update "has_option" column of ime_info DB by Application ID
5731 * @param[in] appid Application ID of IME to enable or disable
5732 * @param[in] has_option @c true to have IME option(setting), otherwise @c false
5734 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option)
5736 if (appid.length() == 0) {
5737 LOGW ("Invalid appid");
5741 if (_ime_info.size() == 0)
5742 isf_pkg_select_all_ime_info_db(_ime_info);
5744 if (isf_db_update_has_option_by_appid(appid.c_str(), has_option)) { // Update ime_info DB
5745 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5746 if (appid == _ime_info[i].appid) {
5747 _ime_info[i].has_option = static_cast<uint32>(has_option); // Update global variable
5754 * @brief Update "is_enable" column of ime_info DB by Application ID
5756 * @param[in] appid Application ID of IME to enable or disable
5757 * @param[in] is_enabled @c true to enable the IME, otherwise @c false
5759 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled)
5761 if (appid.length() == 0) {
5762 LOGW ("Invalid appid");
5766 if (_ime_info.size() == 0)
5767 isf_pkg_select_all_ime_info_db(_ime_info);
5769 if (isf_db_update_is_enabled_by_appid(appid.c_str(), is_enabled)) { // Update ime_info DB
5770 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5771 if (appid == _ime_info[i].appid) {
5772 _ime_info[i].is_enabled = static_cast<uint32>(is_enabled); // Update global variable
5778 #ifdef HAVE_PKGMGR_INFO
5780 * @brief Finds appid with specific category
5782 * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative
5784 static int _find_appid_from_category (const pkgmgrinfo_appinfo_h handle, void *user_data)
5787 char **result = static_cast<char **>(user_data);
5792 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
5793 if (ret == PMINFO_R_OK) {
5794 *result = strdup (appid);
5797 LOGW ("pkgmgrinfo_appinfo_get_appid failed!");
5801 LOGW ("user_data is null!");
5804 return -1; // This callback is no longer called.
5809 * @brief Requests to open the installed IME list application.
5811 static void slot_show_helper_ise_list (void)
5813 // Launch IME List application; e.g., org.tizen.inputmethod-setting-list
5814 char *app_id = NULL;
5815 #ifdef HAVE_PKGMGR_INFO
5816 pkgmgrinfo_appinfo_filter_h handle;
5819 if (ime_list_app.length() < 1) {
5820 ret = pkgmgrinfo_appinfo_filter_create (&handle);
5821 if (ret == PMINFO_R_OK) {
5822 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-list");
5823 if (ret == PMINFO_R_OK) {
5824 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
5826 pkgmgrinfo_appinfo_filter_destroy (handle);
5829 ime_list_app = String (app_id);
5833 app_id = strdup (ime_list_app.c_str());
5837 app_control_launch (app_id);
5841 SECURE_LOGW ("AppID with http://tizen.org/category/ime-list category is not available.");
5846 * @brief Requests to open the installed IME selector application.
5848 static void slot_show_helper_ise_selector (void)
5850 // Launch IME Selector application; e.g., org.tizen.inputmethod-setting-selector
5851 char *app_id = NULL;
5852 #ifdef HAVE_PKGMGR_INFO
5853 pkgmgrinfo_appinfo_filter_h handle;
5856 if (ime_selector_app.length() < 1) {
5857 ret = pkgmgrinfo_appinfo_filter_create(&handle);
5858 if (ret == PMINFO_R_OK) {
5859 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
5860 if (ret == PMINFO_R_OK) {
5861 pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, _find_appid_from_category, &app_id);
5863 pkgmgrinfo_appinfo_filter_destroy(handle);
5866 ime_selector_app = String(app_id);
5870 app_id = strdup(ime_selector_app.c_str());
5874 app_control_launch (app_id);
5878 SECURE_LOGW ("AppID with http://tizen.org/category/ime-selector category is not available.");
5882 static bool slot_is_helper_ise_enabled (String appid, int &enabled)
5884 bool is_enabled = false;
5886 if (appid.length() == 0) {
5887 LOGW ("Invalid appid.");
5891 if (_ime_info.size() == 0)
5892 isf_pkg_select_all_ime_info_db(_ime_info);
5894 if (isf_db_select_is_enabled_by_appid(appid.c_str(), &is_enabled)) {
5895 enabled = static_cast<int>(is_enabled);
5904 * @brief Get the ISE's information.
5906 * @param uuid The ISE's uuid.
5907 * @param name The ISE's name.
5908 * @param language The ISE's language.
5909 * @param type The ISE's type.
5910 * @param option The ISE's option.
5912 * @return true if this operation is successful, otherwise return false.
5914 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name)
5916 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5918 if (uuid.length () > 0) {
5919 // update all ISE names according to the display languages
5920 // sometimes get_ise_information is called before vconf display language changed callback is called.
5921 update_ise_locale ();
5923 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5924 if (uuid == _ime_info[i].appid) {
5925 name = _ime_info[i].label;
5926 language = _ime_info[i].languages;
5927 type = _ime_info[i].mode;
5928 option = _ime_info[i].options;
5929 module_name = _ime_info[i].module_name;
5935 std::cerr << __func__ << " is failed!!!\n";
5940 * @brief Get keyboard ISEs list slot function for PanelAgent.
5942 * @param name_list The list is used to store keyboard ISEs.
5944 * @return true if this operation is successful, otherwise return false.
5946 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list)
5948 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5950 isf_load_ise_information (ALL_ISE, _config);
5952 std::vector<String> lang_list, uuid_list;
5953 isf_get_all_languages (lang_list);
5954 isf_get_keyboard_ises_in_languages (lang_list, uuid_list, name_list, false);
5956 _info_manager->update_ise_list (uuid_list);
5961 * @brief Get enable languages list slot function for PanelAgent.
5963 * @param list The list is used to store languages.
5965 static void slot_get_language_list (std::vector<String> &list)
5967 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5970 MapStringVectorSizeT::iterator iter = _groups.begin ();
5972 for (; iter != _groups.end (); iter++) {
5973 lang_name = scim_get_language_name (iter->first);
5974 list.push_back (lang_name);
5979 * @brief Get all languages list slot function for PanelAgent.
5981 * @param lang The list is used to store languages.
5983 static void slot_get_all_language (std::vector<String> &lang)
5985 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5987 isf_get_all_languages (lang);
5991 * @brief Get specific ISE language list slot function for PanelAgent.
5993 * @param name The ISE name.
5994 * @param list The list is used to store ISE languages.
5996 static void slot_get_ise_language (char *name, std::vector<String> &list)
5998 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6003 std::vector<String> list_tmp;
6005 for (unsigned int i = 0; i < _ime_info.size(); i++) {
6006 if (!strcmp (_ime_info[i].label.c_str (), name)) {
6007 scim_split_string_list (list_tmp, _ime_info[i].languages, ',');
6008 for (i = 0; i < list_tmp.size (); i++)
6009 list.push_back (scim_get_language_name (list_tmp[i]));
6016 * @brief Get ISE information slot function for PanelAgent.
6018 * @param uuid The ISE uuid.
6019 * @param info The variable is used to store ISE information.
6021 * @return true if this operation is successful, otherwise return false.
6023 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info)
6025 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6027 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6028 if (!uuid.compare (_ime_info[i].appid)) {
6029 info.uuid = _ime_info[i].appid;
6030 info.name = _ime_info[i].label;
6031 info.icon = _ime_info[i].iconpath;
6032 info.lang = _ime_info[i].languages;
6033 info.option = _ime_info[i].options;
6034 info.type = _ime_info[i].mode;
6043 * @brief Set keyboard ISE slot function for PanelAgent.
6045 * @param uuid The variable is ISE uuid.
6047 static void slot_set_keyboard_ise (const String &uuid)
6049 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << uuid << "\n";
6051 std::vector<String> uuids;
6052 std::vector<ImeInfoDB>::iterator iter;
6053 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
6054 uuids.push_back(iter->appid);
6057 if (uuid.length () <= 0 || std::find (uuids.begin (), uuids.end (), uuid) == uuids.end ())
6060 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6061 if (_ime_info[get_ise_index (default_uuid)].mode == TOOLBAR_KEYBOARD_MODE)
6064 uint32 ise_option = 0;
6065 String ise_uuid, ise_name;
6066 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
6067 if (ise_uuid == uuid)
6070 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
6071 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
6075 _info_manager->change_factory (uuid);
6079 * @brief Get current keyboard ISE name and uuid slot function for PanelAgent.
6081 * @param ise_name The variable is used to store ISE name.
6082 * @param ise_uuid The variable is used to store ISE uuid.
6084 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid)
6086 uint32 ise_option = 0;
6087 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
6089 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << ise_uuid << "\n";
6093 * @brief Accept connection slot function for PanelAgent.
6095 * @param fd The file descriptor to connect.
6097 static void slot_accept_connection (int fd)
6099 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6102 get_input_window ();
6107 * @brief Close connection slot function for PanelAgent.
6109 * @param fd The file descriptor to connect.
6111 static void slot_close_connection (int fd)
6113 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6117 * @brief Exit panel process slot function for PanelAgent.
6119 static void slot_exit (void)
6121 std::cerr << __FUNCTION__ << "...\n";
6122 ISF_SAVE_LOG ("exit");
6124 #if ISF_BUILD_CANDIDATE_UI
6127 ecore_main_loop_quit ();
6128 #endif /* CANDIDATE */
6131 static void delete_ise_check_pid_alive_timer(void)
6133 LOGD("deleting ise_check_alive_timer");
6134 if (_ise_check_pid_alive_timer) {
6135 ecore_timer_del(_ise_check_pid_alive_timer);
6136 _ise_check_pid_alive_timer = NULL;
6140 static Eina_Bool ise_check_pid_alive_timer(void *data)
6142 Eina_Bool ret = ECORE_CALLBACK_RENEW;
6143 long int ime_pid = (long int)data;
6145 int status = aul_app_get_status_bypid(ime_pid);
6146 LOGD("STATUS : %d %d", status, (int)ime_pid);
6148 /* If the status is not one of STATUS_LAUNCHING, STATUS_VISIBLE, STATUS_BG */
6149 if (status >= STATUS_DYING || status == -1) {
6150 _soft_keyboard_launched = false;
6152 String uuid = _config->read(SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
6153 /* The start_helper() function below will going to call slot_run_helper,
6154 which will going to assign a new timer handle to the _ise_check_pid_alive_timer variable.
6156 LOGW("The previous attempt to launch %s seems to be failed, restarting", uuid.c_str());
6157 if (_info_manager->start_helper(uuid))
6158 _soft_keyboard_launched = true;
6160 ret = ECORE_CALLBACK_CANCEL;
6166 static void slot_register_helper(int id, const HelperInfo& info)
6168 LOGD ("app id : %s", info.uuid.c_str ());
6169 /* Do we need to check whether the pid of this helper is the one we are watching? */
6170 if (info.uuid.compare(_ise_check_pid_alive_uuid) == 0) {
6171 delete_ise_check_pid_alive_timer();
6175 static void slot_register_helper_properties (int id, const PropertyList &props)
6177 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6179 /* WMSYNC, #2 Receiving X window ID from ISE */
6180 /* FIXME : We should add an API to set window id of ISE */
6181 Property prop = props[0];
6182 if (prop.get_label ().compare ("XID") == 0) {
6183 Ecore_X_Window xwindow = atoi (prop.get_key ().c_str ());
6184 _ise_window = xwindow;
6185 LOGD ("ISE XID : %x", _ise_window);
6187 /* Just in case for the helper sent this message later than show_ise request */
6188 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
6189 efl_set_transient_for_app_window (_ise_window);
6192 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_ISE_WINDOW");
6193 if (atom && _control_window && _ise_window) {
6194 ecore_x_window_prop_xid_set (_control_window, atom, ECORE_X_ATOM_WINDOW, &_ise_window, 1);
6196 #ifdef HAVE_NOTIFICATION
6197 delete_notification (&ise_selector_module_noti);
6203 #if ENABLE_REMOTE_INPUT
6204 static void slot_send_remote_input_message (const String &msg, bool len)
6206 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6208 String con = msg.c_str ();
6209 ISE_MESSAGE message = CISEMessageSerializer::deserialize(con);
6211 if (remote_input_impl == NULL) {
6212 remote_input_impl = Remote_Input::get_instance();
6215 if (remote_input_impl)
6216 remote_input_impl->handle_websocket_message(message);
6219 static void slot_recv_remote_surrounding_text (int cursor, const String &text)
6221 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6223 if (remote_input_impl == NULL) {
6224 remote_input_impl = Remote_Input::get_instance();
6227 if (remote_input_impl)
6228 remote_input_impl->handle_recv_panel_message(3, text.c_str (), cursor);
6232 static void slot_show_ise (void)
6234 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6236 /* If the current toolbar mode is not HELPER_MODE, do not proceed */
6237 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
6238 LOGD ("Current toolbar mode should be TOOLBAR_HELPER_MODE but is %d, returning",
6239 _info_manager->get_current_toolbar_mode ());
6243 LOGD ("slot_show_ise ()");
6245 delete_ise_hide_timer ();
6247 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
6248 // Unset conformant area
6249 Ecore_X_Window current_app_window = efl_get_app_window ();
6250 if (_app_window != current_app_window) {
6251 struct rectinfo info = {0, 0, 0, 0};
6252 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
6253 set_keyboard_geometry_atom_info (_app_window, info);
6254 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6255 LOGD ("Conformant reset for window %x", _app_window);
6256 _app_window = current_app_window;
6258 /* If the target window has changed but our ISE is still in visible state,
6259 update the keyboard geometry information */
6260 if (_ise_state == WINDOW_STATE_SHOW) {
6261 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6265 /* If the candidate was already in SHOW state, respect the current angle */
6266 if (_candidate_state != WINDOW_STATE_SHOW) {
6267 /* FIXME : Need to check if candidate_angle and window_angle should be left as separated */
6268 _candidate_angle = efl_get_app_window_angle ();
6270 /* If the ise was already in SHOW state, respect the current angle */
6271 if (_ise_state != WINDOW_STATE_SHOW) {
6272 _ise_angle = efl_get_app_window_angle ();
6275 ecore_x_event_mask_set (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6276 efl_set_transient_for_app_window (_ise_window);
6278 /* Make clipboard window to have transient_for information on ISE window,
6279 so that the clipboard window will always be above ISE window */
6280 Ecore_X_Window clipboard_window = efl_get_clipboard_window ();
6281 if (_ise_window && clipboard_window) {
6282 ecore_x_icccm_transient_for_set (clipboard_window, _ise_window);
6285 /* If our ISE was already in SHOW state, skip state transition to WILL_SHOW */
6286 if (_ise_state != WINDOW_STATE_SHOW) {
6287 _ise_state = WINDOW_STATE_WILL_SHOW;
6291 #if ISF_BUILD_CANDIDATE_UI
6292 _candidate_angle = 0;
6293 #endif /* CANDIDATE */
6294 _ise_state = WINDOW_STATE_SHOW;
6296 #ifdef HAVE_NOTIFICATION
6297 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6298 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6299 show_ime_selector_notification ();
6306 static void slot_hide_ise (void)
6308 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6310 LOGD ("slot_hide_ise ()");
6312 if (!_ise_hide_timer)
6316 static void slot_will_hide_ack (void)
6318 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6320 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
6321 // WILL_HIDE_REQUEST_DONE Ack to WM
6322 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6323 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
6324 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
6325 root_window, _control_window);
6326 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6327 LOGD ("calling ui_candidate_hide (true, false)");
6328 ui_candidate_hide (true, false);
6331 /* WILL_HIDE_ACK means that the application finished redrawing the autoscroll area,
6332 now hide the candidate window right away if it is also in WILL_HIDE state */
6333 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6334 candidate_window_hide ();
6337 if (_off_prepare_done_timer) {
6338 ecore_timer_del (_off_prepare_done_timer);
6339 _off_prepare_done_timer = NULL;
6344 static void slot_candidate_will_hide_ack (void)
6346 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6348 LOGD ("candidate_will_hide_ack");
6349 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6350 candidate_window_hide ();
6355 static void slot_set_keyboard_mode (int mode)
6357 LOGD ("slot_set_keyboard_mode called (TOOLBAR_MODE : %d)", mode);
6359 change_keyboard_mode ((TOOLBAR_MODE_T)mode);
6362 static void slot_get_ise_state (int &state)
6364 if (_ise_state == WINDOW_STATE_SHOW ||
6365 ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (_candidate_state == WINDOW_STATE_SHOW))) {
6366 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6368 /* Currently we don't have WILL_HIDE / HIDE state distinction in Ecore_IMF */
6369 switch (_ise_state) {
6370 case WINDOW_STATE_SHOW :
6371 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6373 case WINDOW_STATE_WILL_SHOW :
6374 state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
6376 case WINDOW_STATE_WILL_HIDE :
6377 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6379 case WINDOW_STATE_HIDE :
6380 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6383 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6386 LOGD ("state = %d", state);
6387 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " state = " << state << "\n";
6390 static void slot_start_default_ise (void)
6392 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6393 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE)) {
6394 if (_launch_ise_on_request && !_soft_keyboard_launched) {
6395 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6397 LOGD ("Start helper (%s)", uuid.c_str ());
6399 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
6400 if (_info_manager->start_helper (uuid))
6401 _soft_keyboard_launched = true;
6403 LOGW ("Failed to start helper (%s)", uuid.c_str ());
6408 static void slot_stop_default_ise (void)
6410 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6412 if (_launch_ise_on_request && _soft_keyboard_launched) {
6413 String uuid = _info_manager->get_current_helper_uuid ();
6415 if (uuid.length () > 0) {
6416 _info_manager->hide_helper (uuid);
6417 _info_manager->stop_helper (uuid);
6418 _soft_keyboard_launched = false;
6419 LOGD ("stop helper (%s)", uuid.c_str ());
6424 static void launch_helper (const char* exec, const char *name, const char *appid, const char *config, const char *display)
6430 if (pid < 0) return;
6433 const char *argv [] = { exec,
6436 "--display", display,
6437 const_cast<char*> (name),
6438 const_cast<char*> (appid),
6441 SCIM_DEBUG_MAIN (2) << " Call scim-helper-launcher.\n";
6442 ISF_SAVE_LOG ("Exec scim_helper_launcher(%s %s)", name, appid);
6444 unsetenv ("ELM_THEME");
6445 unsetenv ("ELM_SCALE");
6448 LOGD ("launch execpath : %s", exec);
6449 execv (exec, const_cast<char **>(argv));
6450 #if ISF_BUILD_CANDIDATE_UI
6453 ecore_main_loop_quit ();
6454 #endif /* CANDIDATE */
6458 static bool app_control_launch (const char *app_id)
6460 app_control_h app_control;
6463 ret = app_control_create (&app_control);
6464 if (ret != APP_CONTROL_ERROR_NONE) {
6465 LOGW ("app_control_create returned %08x", ret);
6469 ret = app_control_set_operation (app_control, APP_CONTROL_OPERATION_DEFAULT);
6470 if (ret != APP_CONTROL_ERROR_NONE) {
6471 LOGW ("app_control_set_operation returned %08x", ret);
6472 app_control_destroy (app_control);
6476 ret = app_control_set_app_id (app_control, app_id);
6477 if (ret != APP_CONTROL_ERROR_NONE) {
6478 LOGW ("app_control_set_app_id returned %08x", ret);
6479 app_control_destroy (app_control);
6485 if (tries != 0) usleep(1000000); /* If we are retrying to launch, pause for a while */
6486 ret = app_control_send_launch_request(app_control, NULL, NULL);
6487 LOGW ("app_control_send_launch_request returned %08x, app_id=%s", ret, app_id);
6488 } while (ret != APP_CONTROL_ERROR_NONE && (++tries) < 3);
6490 app_control_destroy (app_control);
6492 if (ret != APP_CONTROL_ERROR_NONE) {
6493 LOGW ("Failed to launch IME (%s)", app_id);
6495 LOGD ("Succeeded to launch IME (%s)", app_id);
6498 return (ret == APP_CONTROL_ERROR_NONE);
6501 static void slot_run_helper (const String &uuid, const String &config, const String &display)
6503 ISF_SAVE_LOG ("time:%ld pid:%d %s %s uuid(%s)",
6504 time (0), getpid (), __FILE__, __func__, uuid.c_str ());
6506 String scim_helper_path;
6508 delete_ise_check_pid_alive_timer();
6510 #ifdef HAVE_PKGMGR_INFO
6511 char *execpath = NULL;
6513 pkgmgrinfo_appinfo_h appinfo_handle;
6515 /* get app info handle */
6516 /* Try to get in global packages */
6517 ret = pkgmgr_get_appinfo (uuid.c_str (), &appinfo_handle);
6518 if (ret != PMINFO_R_OK) {
6519 LOGW ("pkgmgrinfo_appinfo_get_appinfo () & get_usr_appinfo () failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6524 ret = pkgmgrinfo_appinfo_get_exec (appinfo_handle, &execpath);
6525 if (ret != PMINFO_R_OK) {
6526 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6530 LOGD ("exec path : %s", execpath);
6531 scim_helper_path = String (execpath);
6533 if (appinfo_handle) {
6534 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6535 appinfo_handle = NULL;
6538 scim_helper_path = String (SCIM_HELPER_LAUNCHER_PROGRAM);
6541 for (size_t i = 0; i < _ime_info.size (); ++i) {
6542 if (_ime_info[i].appid == uuid && _ime_info[i].module_name.length ()) {
6543 if (scim_helper_path != String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
6544 /* Check if IME with the same AppID is alive */
6545 int status_ret = aul_app_get_status (uuid.c_str ());
6546 if (status_ret >= STATUS_LAUNCHING) {
6547 /* Request to terminate IME */
6548 int ime_pid = aul_app_get_pid (uuid.c_str ());
6549 status_ret = aul_terminate_pid (ime_pid);
6550 if (status_ret < AUL_R_OK) {
6551 LOGE ("aul_terminate_pid(%d) failed: %d", ime_pid, status_ret);
6554 LOGD ("Requested to terminate IME(%s)", uuid.c_str ());
6558 /* execute type IME */
6559 LOGD ("Try to launch IME (%s)", uuid.c_str ());
6560 bool launched = app_control_launch (uuid.c_str ());
6563 long int ime_pid = aul_app_get_pid(uuid.c_str());
6565 LOGD ("Register check_alive timer for pid : %d", (int)ime_pid);
6566 _ise_check_pid_alive_uuid = uuid;
6567 _ise_check_pid_alive_timer = ecore_timer_add (_ise_check_pid_alive_time,
6568 ise_check_pid_alive_timer, (void*)ime_pid);
6573 /* shared object (so) type IME */
6574 launch_helper (scim_helper_path.c_str(), _ime_info[i].module_name.c_str (), uuid.c_str (), config.c_str (), display.c_str ());
6581 SCIM_DEBUG_MAIN (2) << " exit run_helper ().\n";
6584 static bool slot_launch_option_application (String ime_appid)
6586 String ime_setting_app = isf_pkg_get_setting_app (ime_appid);
6588 LOGD ("IME appid : %s, IME setting app id : %s", ime_appid.c_str (), ime_setting_app.c_str ());
6590 if (ime_setting_app.length () > 0) {
6591 app_control_launch (ime_setting_app.c_str ());
6598 //////////////////////////////////////////////////////////////////////
6599 // End of PanelAgent-Functions
6600 //////////////////////////////////////////////////////////////////////
6604 * @brief Callback function for abnormal signal.
6606 * @param sig The signal.
6608 static void signalhandler (int sig)
6610 std::cerr << __FUNCTION__ << " Signal=" << sig << "\n";
6611 ISF_SAVE_LOG ("Signal=%d", sig);
6613 #if ISF_BUILD_CANDIDATE_UI
6616 ecore_main_loop_quit ();
6617 #endif /* CANDIDATE */
6621 static void update_ise_locale (const char *language)
6626 strLang = String (language);
6629 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
6631 if (_locale_string.compare(lang_str) == 0) {
6636 strLang = String (lang_str);
6642 LOGD ("update all ISE names according to display language : %s", strLang.c_str ());
6643 set_language_and_locale (strLang.c_str ());
6645 bool need_to_init_db = false;
6646 #ifdef HAVE_PKGMGR_INFO
6650 pkgmgrinfo_appinfo_h handle = NULL;
6652 /* Read DB from ime_info table */
6653 isf_load_ise_information(ALL_ISE, _config);
6655 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6656 ret = pkgmgr_get_appinfo (_ime_info[i].appid.c_str(), &handle);
6658 if (ret == PMINFO_R_OK) {
6659 ret = pkgmgrinfo_appinfo_is_category_exist(handle, "http://tizen.org/category/ime", &exist);
6660 if (ret == PMINFO_R_OK && exist) {
6661 ret = pkgmgrinfo_appinfo_get_label(handle, &label);
6662 if (ret == PMINFO_R_OK && label) {
6663 _ime_info[i].label = String(label);
6664 /* Update label column in ime_info db table */
6665 if (isf_db_update_label_by_appid(_ime_info[i].appid.c_str(), label)) {
6666 _ime_info[i].label = label;
6671 // The appid is invalid.. Need to initialize ime_info DB.
6672 need_to_init_db = true;
6674 pkgmgrinfo_appinfo_destroy_appinfo(handle);
6677 // The appid is invalid.. Need to initialize ime_info DB.
6678 need_to_init_db = true;
6683 if (need_to_init_db) {
6684 _initialize_ime_info ();
6687 if (strLang.length () > 0) {
6688 isf_db_update_disp_lang (strLang.c_str ());
6689 _locale_string = strLang;
6694 * @brief Set language and locale.
6698 static void set_language_and_locale (const char *lang_str)
6700 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6705 LOGD ("language : %s", lang_str);
6706 #if ISF_BUILD_CANDIDATE_UI
6707 elm_language_set (lang_str);
6708 #endif /* CANDIDATE */
6710 snprintf (language, sizeof (language), "%s:en_US:en_GB:en", lang_str);
6711 setenv ("LANGUAGE", language, 1);
6712 setenv ("LANG", lang_str, 1);
6713 setlocale (LC_MESSAGES, lang_str);
6715 setenv ("LANG", "en_US.utf8", 1);
6716 setlocale (LC_MESSAGES, "en_US.utf8");
6721 * @brief Callback function for display language change.
6723 * @param key The key node.
6724 * @param data The data to pass to this callback.
6728 static void display_language_changed_cb (keynode_t *key, void* data)
6730 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6732 char *lang_str = vconf_keynode_get_str (key);
6733 LOGD ("lang : %s", lang_str);
6734 set_language_and_locale (lang_str);
6736 /* Update all ISE names according to display language */
6737 update_ise_locale ();
6739 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
6740 unsigned int ise_idx = get_ise_index (default_uuid);
6742 if (ise_idx < _ime_info.size ()) {
6743 String default_name = _ime_info[ise_idx].label;
6744 _info_manager->set_current_ise_name (default_name);
6750 * @brief Callback function for keyboard mode change.
6752 * @param key The key node.
6753 * @param data The data to pass to this callback.
6757 static void keyboard_mode_changed_cb (keynode_t *key, void* data)
6759 bool val = vconf_keynode_get_bool (key);
6762 _info_manager->reset_keyboard_ise ();
6763 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6764 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6770 * @brief Change keyboard mode.
6772 * @param mode The keyboard mode.
6776 static void change_keyboard_mode (TOOLBAR_MODE_T mode)
6778 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6781 bool _support_hw_keyboard_mode = false;
6783 unsigned int val = 0;
6787 int input_detect = false;
6790 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6791 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6792 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
6794 if (mode == TOOLBAR_KEYBOARD_MODE && _support_hw_keyboard_mode) {
6795 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6796 LOGD ("HARDWARE_KEYBOARD_MODE return");
6800 LOGD ("HARDWARE KEYBOARD MODE");
6801 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 1);
6804 if (_ime_info[get_ise_index(default_uuid)].mode == TOOLBAR_HELPER_MODE) {
6805 /* Get the keyboard ISE */
6806 isf_get_keyboard_ise (_config, uuid, name, option);
6807 if (option & SCIM_IME_NOT_SUPPORT_HARDWARE_KEYBOARD) {
6808 uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
6809 std::cerr << __FUNCTION__ << ": Keyboard ISE (" << name << ") can not support hardware keyboard!!!\n";
6811 /* Try to find reasonable keyboard ISE according to helper ISE language */
6812 if (uuid == String (SCIM_COMPOSE_KEY_FACTORY_UUID)) {
6813 String helper_language = _ime_info[get_ise_index(default_uuid)].languages;
6814 if (helper_language.length () > 0) {
6815 std::vector<String> ise_langs;
6816 scim_split_string_list (ise_langs, helper_language);
6817 for (size_t i = 0; i < _groups[ise_langs[0]].size (); ++i) {
6818 int j = _groups[ise_langs[0]][i];
6819 if (_ime_info[j].appid != uuid && _ime_info[j].mode == TOOLBAR_KEYBOARD_MODE) {
6820 uuid = _ime_info[j].appid;
6828 uuid = default_uuid;
6830 #if ISF_BUILD_CANDIDATE_UI
6831 _soft_candidate_width = 0;
6832 _soft_candidate_height = 0;
6833 #endif /* CANDIDATE */
6834 _ise_state = WINDOW_STATE_HIDE;
6835 _info_manager->set_current_toolbar_mode (TOOLBAR_KEYBOARD_MODE);
6836 _info_manager->hide_helper (helper_uuid);
6838 /* Check whether stop soft keyboard */
6839 if (_focus_in && (_ime_info[get_ise_index (helper_uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
6840 /* If focus in and soft keyboard can support hardware key event, then don't stop it */
6842 } else if (_launch_ise_on_request && _soft_keyboard_launched) {
6843 _info_manager->stop_helper (helper_uuid);
6844 _soft_keyboard_launched = false;
6847 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6850 #ifdef HAVE_NOTIFICATION
6852 notification_status_message_post (_("Input detected from hardware keyboard"));
6854 /* Read configuations for notification app (isf-kbd-mode-changer) */
6855 String kbd_mode_changer = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_KBD_MODE_CHANGER_PROGRAM), String (""));
6856 hwkbd_module_noti.launch_app = kbd_mode_changer;
6857 LOGD ("Create kbd_mode_changer notification with : %s", kbd_mode_changer.c_str ());
6858 create_notification (&hwkbd_module_noti);
6863 vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect);
6865 if (!input_detect) {
6866 if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 1) != 0)
6867 LOGW ("Failed to set vconf key");
6869 LOGD ("Succeeded to set vconf key");
6872 } else if (mode == TOOLBAR_HELPER_MODE) {
6873 LOGD ("SOFTWARE KEYBOARD MODE");
6874 /* When switching back to S/W keyboard mode, let's hide candidate window first */
6875 #if ISF_BUILD_CANDIDATE_UI
6876 LOGD ("calling ui_candidate_hide (true, true, true)");
6877 ui_candidate_hide (true, true, true);
6878 #endif /* CANDIDATE */
6879 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
6881 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6882 uuid = helper_uuid.length () > 0 ? helper_uuid : _initial_ise_uuid;
6883 if (_launch_ise_on_request) {
6884 if (set_active_ise (uuid, false) == false) {
6885 if (_initial_ise_uuid.compare(uuid))
6886 set_active_ise (_initial_ise_uuid, false);
6890 if (set_active_ise (uuid, true) == false) {
6891 if (_initial_ise_uuid.compare(uuid)) {
6892 LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
6893 set_active_ise (_initial_ise_uuid, true);
6899 #ifdef HAVE_NOTIFICATION
6900 delete_notification (&hwkbd_module_noti);
6904 vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect);
6907 if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0) != 0)
6908 LOGW ("Failed to set vconf key");
6910 LOGD ("Succeeded to set vconf key");
6917 #ifdef HAVE_BLUETOOTH
6919 * @brief Callback function for the connection state of Bluetooth Keyboard
6921 * @param result The result of changing the connection state
6922 * @param connected The state to be changed. true means connected state, Otherwise, false.
6923 * @param remote_address The remote address
6924 * @param user_data The user data passed from the callback registration function
6928 static void _bt_cb_hid_state_changed (int result, bool connected, const char *remote_address, void *user_data)
6930 if (connected == false) {
6931 LOGD ("Bluetooth keyboard disconnected");
6932 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6933 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6939 #ifdef HAVE_NOTIFICATION
6940 static void show_ime_selector_notification ()
6944 if (!_MOBILE) return;
6946 unsigned int idx = get_ise_index (_info_manager->get_current_helper_uuid ());
6947 if (idx < _ime_info.size ())
6948 ise_name = _ime_info[idx].label;
6950 String noti_icon_path = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_QUICK_PANEL_ICON_PATH), String (SCIM_ICONDIR));
6951 noti_icon_path += ISF_ISE_SELECTOR_ICON_FILE;
6953 LOGD("IME selector icon path : %s", noti_icon_path.c_str ());
6955 ise_selector_module_noti.icon = noti_icon_path.c_str ();
6956 ise_selector_module_noti.content = ise_name.c_str ();
6958 /* Find IME Selector appid for notification */
6959 if (ime_selector_app.length () < 1) {
6960 char *app_id = NULL;
6961 pkgmgrinfo_appinfo_filter_h handle;
6962 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
6963 if (ret == PMINFO_R_OK) {
6964 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
6965 if (ret == PMINFO_R_OK) {
6966 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
6968 pkgmgrinfo_appinfo_filter_destroy (handle);
6971 ime_selector_app = String (app_id);
6978 if (ime_selector_app.length () > 0) {
6979 ise_selector_module_noti.launch_app = ime_selector_app;
6980 LOGD ("Create ise_selector notification with : %s", ime_selector_app.c_str ());
6981 create_notification (&ise_selector_module_noti);
6984 LOGW ("AppID with http://tizen.org/category/ime-selector category is not available");
6990 * @brief Callback function for ECORE_X_EVENT_WINDOW_PROPERTY.
6992 * @param data Data to pass when it is called.
6993 * @param ev_type The event type.
6994 * @param ev The information for current message.
6996 * @return ECORE_CALLBACK_PASS_ON
6998 static Eina_Bool x_event_window_property_cb (void *data, int ev_type, void *event)
7000 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7002 Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property *)event;
7005 return ECORE_CALLBACK_PASS_ON;
7007 if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
7008 if (ev->win == _control_window) {
7009 /* WMSYNC, #6 The keyboard window is displayed fully so set the conformant geometry */
7010 LOGD ("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE : win : %p, atom : %d", ev->win, ev->atom);
7011 Ecore_X_Virtual_Keyboard_State state;
7012 state = ecore_x_e_virtual_keyboard_state_get (ev->win);
7013 if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON) {
7014 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_ON");
7015 _ise_state = WINDOW_STATE_SHOW;
7017 /* Make sure that we have the same rotation angle with the keyboard window */
7019 _candidate_angle = efl_get_ise_window_angle ();
7020 _ise_angle = efl_get_ise_window_angle ();
7023 if (_candidate_show_requested) {
7024 LOGD ("calling ui_candidate_show (true)");
7025 ui_candidate_show (true);
7027 if (_candidate_area_1_visible) {
7028 LOGD ("calling ui_candidate_show (false)");
7029 ui_candidate_show (false);
7033 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7034 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7035 _info_manager->update_input_panel_event (
7036 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_SHOW);
7039 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW);
7042 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7043 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
7044 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
7046 #ifdef HAVE_NOTIFICATION
7047 show_ime_selector_notification ();
7052 _updated_hide_state_geometry = false;
7054 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
7055 } else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) {
7056 /* WMSYNC, #9 The keyboard window is hidden fully so send HIDE state */
7057 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF");
7058 // For now don't send HIDE signal here
7059 //_info_manager->update_input_panel_event (
7060 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
7061 _ise_state = WINDOW_STATE_HIDE;
7063 if (!_updated_hide_state_geometry) {
7064 /* When the ISE gets hidden by the window manager forcefully without OFF_PREPARE,
7065 the application might not have updated its autoscroll area */
7066 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7067 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7068 _info_manager->update_input_panel_event (
7069 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
7071 _updated_hide_state_geometry = true;
7073 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7074 LOGD ("calling ui_candidate_hide (true, false)");
7075 ui_candidate_hide (true, false);
7077 ui_settle_candidate_window ();
7081 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
7084 #ifdef HAVE_NOTIFICATION
7085 delete_notification (&ise_selector_module_noti);
7088 _ise_reported_geometry.valid = false;
7090 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
7092 ui_settle_candidate_window ();
7094 } else if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
7095 if (ev->win == efl_get_quickpanel_window ()) {
7096 int angle = efl_get_quickpanel_window_angle ();
7097 LOGD ("ev->win : %p, change window angle : %d", ev->win, angle);
7101 return ECORE_CALLBACK_PASS_ON;
7105 * @brief Callback function for X event client message.
7107 * @param data Data to pass when it is called.
7108 * @param type The event type.
7109 * @param event The information for current message.
7111 * @return ECORE_CALLBACK_RENEW
7113 static Eina_Bool x_event_client_message_cb (void *data, int type, void *event)
7115 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7117 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
7120 return ECORE_CALLBACK_RENEW;
7123 if ((ev->win == _control_window)) {
7124 if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST) {
7125 /* WMSYNC, #4 Send WILL_SHOW event when the keyboard window is about to displayed */
7126 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST");
7128 /* WMSYNC, #5 Let the Window Manager to actually show keyboard window */
7129 // WILL_SHOW_REQUEST_DONE Ack to WM
7130 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
7131 ecore_x_e_virtual_keyboard_on_prepare_done_send (root_window, _control_window);
7132 LOGD ("_ecore_x_e_virtual_keyboard_on_prepare_done_send (%x, %x)",
7133 root_window, _control_window);
7135 _info_manager->update_input_panel_event (
7136 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
7137 ui_create_candidate_window ();
7139 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_SHOW);
7140 } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST) {
7141 _ise_state = WINDOW_STATE_WILL_HIDE;
7142 /* WMSYNC, #7 Send WILL_HIDE event when the keyboard window is about to hidden */
7143 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST");
7144 // Clear conformant geometry information first
7146 if (_off_prepare_done_timer) {
7147 ecore_timer_del (_off_prepare_done_timer);
7148 _off_prepare_done_timer = NULL;
7150 _off_prepare_done_timer = ecore_timer_add (1.0, off_prepare_done_timeout, NULL);
7152 _ise_reported_geometry.valid = false;
7153 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7154 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7155 _updated_hide_state_geometry = true;
7157 /* If the input panel is getting hidden because of hw keyboard mode while
7158 the candidate window is still opened, it is considered to be an
7159 "input panel being resized" event instead of "input panel being hidden",
7160 since the candidate window will work as an "input panel" afterwards */
7161 bool send_input_panel_hide_event = true;
7162 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
7163 LOGD ("_candidate_state : %d", _candidate_state);
7164 if (_candidate_state == WINDOW_STATE_SHOW) {
7165 send_input_panel_hide_event = false;
7168 if (send_input_panel_hide_event) {
7169 _info_manager->update_input_panel_event (
7170 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
7172 // For now don't send WILL_HIDE signal here
7173 //_info_manager->update_input_panel_event (
7174 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_HIDE);
7175 // Instead send HIDE signal
7176 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_HIDE);
7177 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE) {
7178 /* WMSYNC, #10 Register size hints for candidate window and set conformant geometry */
7179 // PRE_ROTATE_DONE Ack to WM
7180 _candidate_angle = ev->data.l[1];
7181 _ise_angle = ev->data.l[1];
7182 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE : %d", _candidate_angle);
7184 if (_candidate_angle == 90 || _candidate_angle == 270) {
7185 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
7187 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
7189 if (_ise_state == WINDOW_STATE_SHOW) {
7190 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7191 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7193 ui_settle_candidate_window ();
7194 ui_candidate_window_rotate (_candidate_angle);
7195 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
7196 LOGD ("ecore_x_e_window_rotation_change_prepare_done_send (%d)", _candidate_angle);
7197 ecore_x_e_window_rotation_change_prepare_done_send (root_window,
7198 _control_window, _candidate_angle);
7199 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7200 int ise_angle = (int)ev->data.l[1];
7201 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST for ISE WINDOW : ISE angle : %d, Candidate angle : %d", ise_angle, _candidate_angle);
7202 _candidate_angle = ise_angle;
7203 _ise_angle = ise_angle;
7204 if (_ise_state == WINDOW_STATE_SHOW) {
7205 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7206 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7207 ui_settle_candidate_window ();
7210 } else if (ev->win == elm_win_xwindow_get (_candidate_window)) {
7211 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST || ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE) {
7212 /* WMSYNC, #11 Actual rotate the candidate window */
7213 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7214 _candidate_angle = (int)ev->data.l[1];
7215 ui_candidate_window_rotate (_candidate_angle);
7216 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST : %d", _candidate_angle);
7217 } else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE &&
7218 _ise_state != WINDOW_STATE_SHOW) {
7219 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_TRUE);
7220 _candidate_angle = (int)ev->data.l[0];
7221 if (_candidate_angle == 90 || _candidate_angle == 270) {
7222 evas_object_resize (_candidate_window, _candidate_land_width, _candidate_land_height_min);
7224 evas_object_resize (_candidate_window, _candidate_port_width, _candidate_port_height_min);
7226 ui_candidate_window_rotate (_candidate_angle);
7227 ui_settle_candidate_window ();
7228 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_FALSE);
7229 LOGD ("ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE : %d", _candidate_angle);
7231 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " : ANGLE (" << _candidate_angle << ")\n";
7236 /* Screen reader feature */
7237 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL) {
7238 static int last_pos_x = -10000;
7239 static int last_pos_y = -10000;
7241 if (_candidate_window) {
7242 if ((unsigned int)ev->data.l[0] == elm_win_xwindow_get (_candidate_window)) {
7243 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE) {
7244 // 1 finger double tap
7245 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger double tap focus index = " << _candidate_tts_focus_index << "\n";
7246 ui_mouse_click (_candidate_tts_focus_index);
7247 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ) {
7249 // 1 finger touch & move
7250 last_pos_x = ev->data.l[2];
7251 last_pos_y = ev->data.l[3];
7252 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger touch & move (" << last_pos_x << ", " << last_pos_y << ")\n";
7253 ui_mouse_over (last_pos_x, last_pos_y);
7254 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT ||
7255 (unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV) {
7256 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT) {
7258 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick right\n";
7259 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_display_number - 1))
7260 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : 0;
7261 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7262 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7263 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7264 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7265 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7266 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? 0 : _candidate_row_items[0];
7267 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7268 _candidate_tts_focus_index = _candidate_row_items[0];
7269 else if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < (g_isf_candidate_table.get_current_page_size () - 1))
7270 _candidate_tts_focus_index++;
7271 else if (_candidate_tts_focus_index == (g_isf_candidate_table.get_current_page_size () - 1))
7272 _candidate_tts_focus_index = 0;
7275 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick left\n";
7276 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == 0)
7277 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : _candidate_display_number - 1;
7278 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7279 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7280 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7281 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7282 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7283 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7284 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7285 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7286 else if (_candidate_tts_focus_index > 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ())
7287 _candidate_tts_focus_index--;
7288 else if (_candidate_tts_focus_index == 0)
7289 _candidate_tts_focus_index = g_isf_candidate_table.get_current_page_size () - 1;
7292 int x = 0, y = 0, w = 0, h = 0;
7293 _wait_stop_event = false;
7294 if (candidate_expanded) {
7296 int cursor_line = 0;
7297 for (unsigned int i = 0; i < _candidate_row_items.size (); i++) {
7298 total += _candidate_row_items [i];
7299 if (total > (int)_candidate_display_number && _candidate_tts_focus_index >= total)
7303 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
7305 int line_h = _item_min_height + _v_padding;
7306 int cursor_y = cursor_line * line_h;
7308 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
7309 _wait_stop_event = true;
7310 } else if (cursor_y >= y + h) {
7311 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
7312 _wait_stop_event = true;
7317 String strTts = String ("");
7318 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
7319 strTts = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (_candidate_tts_focus_index));
7320 if (_candidate_0 [_candidate_tts_focus_index])
7321 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
7322 } else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX) {
7323 strTts = String (_("more button"));
7324 evas_object_geometry_get (_more_btn, &x, &y, &w, &h);
7325 } else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX) {
7326 strTts = String (_("close button"));
7327 evas_object_geometry_get (_close_btn, &x, &y, &w, &h);
7329 LOGW ("TTS focus index = %d", _candidate_tts_focus_index);
7330 ui_tts_focus_rect_hide ();
7334 if (strTts.length () > 0)
7335 ui_play_tts (strTts.c_str ());
7337 if (w > 0 && h > 0) {
7338 if (!_wait_stop_event)
7339 ui_tts_focus_rect_show (x, y, w, h);
7341 ui_tts_focus_rect_hide ();
7348 return ECORE_CALLBACK_RENEW;
7352 Eina_Bool check_focus_out_by_popup_win ()
7354 Eina_Bool ret = EINA_FALSE;
7356 Ecore_X_Window focus_win = ecore_x_window_focus_get ();
7357 Ecore_X_Window_Type win_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
7359 if (!ecore_x_netwm_window_type_get (focus_win, &win_type))
7362 LOGD ("win type : %d", win_type);
7364 if (win_type == ECORE_X_WINDOW_TYPE_POPUP_MENU ||
7365 win_type == ECORE_X_WINDOW_TYPE_NOTIFICATION) {
7374 * @brief Callback function for focus out event of application window
7376 * @param data Data to pass when it is called.
7378 * @return ECORE_CALLBACK_RENEW
7380 static Eina_Bool x_event_window_focus_out_cb (void *data, int ev_type, void *event)
7382 Ecore_X_Event_Window_Focus_Out *e = (Ecore_X_Event_Window_Focus_Out*)event;
7384 if (e && e->win == _app_window) {
7385 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7386 if (check_focus_out_by_popup_win ())
7387 return ECORE_CALLBACK_RENEW;
7389 #if ENABLE_MULTIWINDOW_SUPPORT
7390 unsigned int layout = 0;
7391 LOGD ("Application window focus OUT!");
7392 delete_ise_hide_timer ();
7394 // Check multi window mode
7395 if (ecore_x_window_prop_card32_get (efl_get_app_window (), ECORE_X_ATOM_E_WINDOW_DESKTOP_LAYOUT, &layout, 1) != -1) {
7396 if (layout == 0 || layout == 1) {
7398 LOGD ("Multi window mode. start timer to hide IME");
7400 // Use timer not to hide and show IME again in focus-out and focus-in event between applications
7401 _ise_hide_timer = ecore_timer_add (ISF_ISE_HIDE_DELAY, ise_hide_timeout, NULL);
7405 if (!_ise_hide_timer) {
7406 LOGD ("Panel hides ISE");
7407 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7409 ui_candidate_hide (true, false, false);
7412 LOGD ("Application window focus OUT! Panel hides ISE");
7413 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7415 ui_candidate_hide (true, false, false);
7420 return ECORE_CALLBACK_RENEW;
7425 * @brief : Launches default soft keyboard for performance enhancement (It's not mandatory)
7427 static void launch_default_soft_keyboard (keynode_t *key, void* data)
7429 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7431 /* Start default ISE */
7432 change_keyboard_mode (TOOLBAR_HELPER_MODE);
7435 static String sanitize_string (const char *str, int maxlen = 32)
7438 static char acceptables[] =
7439 "abcdefghijklmnopqrstuvwxyz"
7440 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7443 char *newstr = NULL;
7445 newstr = new char[maxlen + 1];
7449 memset (newstr, 0x00, sizeof (char) * (maxlen + 1));
7452 while (len < maxlen && str[len] != '\0' && strchr (acceptables, str[len]) != NULL) {
7453 newstr[len] = str[len];
7463 int main (int argc, char *argv [])
7465 struct tms tiks_buf;
7466 _clock_start = times (&tiks_buf);
7471 bool daemon = false;
7472 bool should_resident = true;
7475 char **new_argv = new char * [40];
7476 int display_name_c = 0;
7477 ConfigModule *config_module = NULL;
7478 String config_name = String ("simple");
7479 String display_name = String ();
7480 char buf[256] = {0};
7483 Ecore_Event_Handler *xclient_message_handler = NULL;
7484 Ecore_Event_Handler *xwindow_property_handler = NULL;
7485 Ecore_Event_Handler *xwindow_focus_out_handler = NULL;
7488 check_time ("\nStarting ISF Panel EFL...... ");
7489 ISF_SAVE_LOG ("Starting ISF Panel EFL......");
7491 DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
7492 DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
7494 /* Parse command options */
7500 if (String ("-c") == argv [i] || String ("--config") == argv [i]) {
7502 std::cerr << "no argument for option " << argv [i-1] << "\n";
7506 config_name = argv [i];
7510 if (String ("-h") == argv [i] || String ("--help") == argv [i]) {
7511 std::cout << "Usage: " << argv [0] << " [option]...\n\n"
7512 << "The options are: \n"
7513 << " --display DISPLAY Run on display DISPLAY.\n"
7514 << " -c, --config NAME Uses specified Config module.\n"
7515 << " -d, --daemon Run " << argv [0] << " as a daemon.\n"
7516 << " -ns, --no-stay Quit if no connected client.\n"
7518 << " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
7519 << " -o, --output FILE Output debug information into FILE.\n"
7521 << " -h, --help Show this help message.\n";
7526 if (String ("-d") == argv [i] || String ("--daemon") == argv [i]) {
7531 if (String ("-ns") == argv [i] || String ("--no-stay") == argv [i]) {
7532 should_resident = false;
7536 if (String ("-v") == argv [i] || String ("--verbose") == argv [i]) {
7538 std::cerr << "no argument for option " << argv [i-1] << "\n";
7542 DebugOutput::set_verbose_level (atoi (argv [i]));
7546 if (String ("-o") == argv [i] || String ("--output") == argv [i]) {
7548 std::cerr << "No argument for option " << argv [i-1] << "\n";
7552 DebugOutput::set_output (argv [i]);
7556 if (String ("--display") == argv [i]) {
7558 std::cerr << "No argument for option " << argv [i-1] << "\n";
7562 display_name = sanitize_string (argv [i]);
7566 if (String ("--") == argv [i])
7569 std::cerr << "Invalid command line option: " << argv [i] << "\n";
7572 } /* End of command line parsing. */
7575 new_argv [new_argc ++] = argv [0];
7577 /* Store the rest argvs into new_argv. */
7578 for (++i; i < argc && new_argc < 37; ++i) {
7579 new_argv [new_argc ++] = argv [i];
7582 /* Make up DISPLAY env. */
7583 if (display_name.length ()) {
7584 new_argv [new_argc ++] = const_cast <char*> ("--display");
7585 display_name_c = new_argc;
7586 new_argv [new_argc ++] = strdup (display_name.c_str ());
7588 setenv ("DISPLAY", display_name.c_str (), 1);
7591 new_argv [new_argc] = 0;
7594 if (!config_name.length ()) {
7595 std::cerr << "No Config module is available!\n";
7600 /* Get current display. */
7602 const char *p = getenv ("DISPLAY");
7604 display_name = String (p);
7607 snprintf (buf, sizeof (buf), "config_name=%s display_name=%s", config_name.c_str (), display_name.c_str ());
7611 check_time ("ISF Panel EFL run as daemon");
7615 /* No loading default theme to reduce heap memory */
7616 setenv ("ELM_THEME", "", 1);
7618 #if ISF_BUILD_CANDIDATE_UI
7619 elm_init (argc, argv);
7622 ecore_app_args_set(argc, (const char **)argv);
7623 #endif /* CANDIDATE */
7625 check_time ("elm_init");
7629 #if ISF_BUILD_CANDIDATE_UI
7630 elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
7631 #endif /* CANDIDATE */
7633 if (config_name != "dummy") {
7634 /* Load config module */
7635 config_module = new ConfigModule (config_name);
7637 if (!config_module || !config_module->valid ()) {
7638 std::cerr << "Can not load " << config_name << " Config module.\n";
7643 _config = new DummyConfig ();
7646 /* Create config instance */
7647 if (_config.null () && config_module && config_module->valid ())
7648 _config = config_module->create_config ();
7649 if (_config.null ()) {
7650 std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
7654 ConfigBase::set (_config);
7655 check_time ("create config instance");
7658 if (!initialize_panel_agent (_config, display_name, should_resident)) {
7659 check_time ("Failed to initialize Panel Agent!");
7660 std::cerr << "Failed to initialize Panel Agent!\n";
7661 LOGE ("Failed to initialize Panel Agent!");
7665 } catch (scim::Exception & e) {
7666 std::cerr << e.what () << "\n";
7671 check_time ("initialize_panel_agent");
7673 #if ISF_BUILD_CANDIDATE_UI
7674 /* Initialize global variables and pointers for candidate items and etc. */
7675 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; i++) {
7676 _candidate_0 [i] = NULL;
7677 _seperate_0 [i] = NULL;
7678 _seperate_items [i] = NULL;
7680 _line_items [i] = NULL;
7681 _candidate_text [i] = NULL;
7682 _candidate_image [i] = NULL;
7683 _candidate_pop_image [i] = NULL;
7685 #endif /* CANDIDATE */
7687 /* Connect the configuration reload signal. */
7688 _config_connection = _config->signal_connect_reload (slot (config_reload_cb));
7691 if (!efl_create_control_window ()) {
7692 LOGW ("Failed to create control window");
7697 #if ISF_BUILD_CANDIDATE_UI
7698 efl_get_screen_resolution (_screen_width, _screen_height);
7700 _width_rate = (float)(_screen_width / 720.0);
7701 _height_rate = (float)(_screen_height / 1280.0);
7702 _blank_width = (int)(_blank_width * _width_rate);
7703 _item_min_width = (int)(_item_min_width * _width_rate);
7704 _item_min_height = (int)(_item_min_height * _height_rate);
7705 _candidate_width = (int)(_candidate_port_width * _width_rate);
7706 _candidate_height = (int)(_candidate_port_height_min * _height_rate);
7707 _indicator_height = (int)(_indicator_height * _height_rate);
7709 _aux_font_size = (int)(_aux_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7710 _candidate_font_size = (int)(_candidate_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7711 #endif /* CANDIDATE */
7713 /* Load ISF configuration */
7715 check_time ("load_config");
7719 lang_str = vconf_get_str (VCONFKEY_LANGSET);
7720 set_language_and_locale (lang_str);
7724 /* Add callback function for input language and display language */
7725 vconf_notify_key_changed (VCONFKEY_LANGSET, display_language_changed_cb, NULL);
7726 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
7729 if (0 != register_edbus_signal_handler ())
7730 LOGW ("register edbus signal fail");
7733 /* Update ISE list */
7734 std::vector<String> list;
7735 update_ise_list (list);
7737 /* Load initial ISE information */
7738 _initial_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_INITIAL_ISE_UUID), String (SCIM_COMPOSE_KEY_FACTORY_UUID));
7740 /* Check if SCIM_CONFIG_DEFAULT_HELPER_ISE is available. If it's not, set it as _initial_ise_uuid.
7741 e.g., This might be necessary when the platform is upgraded from 2.3 to 2.4. */
7742 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
7743 if (helper_uuid.length() > 0 && _initial_ise_uuid.length() > 0 && helper_uuid != _initial_ise_uuid) {
7745 for (unsigned int u = 0; u < _ime_info.size (); u++) {
7746 if (_ime_info[u].mode == TOOLBAR_HELPER_MODE && helper_uuid == _ime_info[u].appid) {
7752 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), _initial_ise_uuid);
7756 /* Launches default soft keyboard when all conditions are satisfied */
7757 launch_default_soft_keyboard ();
7759 /* Update the name of each ISE according to display language */
7760 update_ise_locale ();
7761 } catch (scim::Exception & e) {
7762 std::cerr << e.what () << "\n";
7763 } catch (std::logic_error & e) {
7764 std::cerr << e.what () << "\n";
7767 xclient_message_handler = ecore_event_handler_add (ECORE_X_EVENT_CLIENT_MESSAGE, x_event_client_message_cb, NULL);
7768 xwindow_property_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, x_event_window_property_cb, NULL);
7769 xwindow_focus_out_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_FOCUS_OUT, x_event_window_focus_out_cb, NULL);
7772 #ifdef HAVE_BLUETOOTH
7773 /* Register the callback function of Bluetooth connection */
7774 ret = bt_initialize ();
7775 if (ret != BT_ERROR_NONE)
7776 LOGW ("Fail to init Bluetooth");
7778 ret = bt_hid_host_initialize (_bt_cb_hid_state_changed, NULL);
7779 if (ret != BT_ERROR_NONE)
7780 LOGW ("bt_hid_host_initialize failed");
7784 launch_remote_input = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_REMOTE_INPUT), launch_remote_input);
7786 /* Create remote input */
7787 if (launch_remote_input) {
7788 LOGD("remote input start");
7789 remote_input_impl = new Remote_Input();
7790 if (remote_input_impl) {
7791 remote_input_impl->init(_info_manager);
7796 #if ISF_BUILD_CANDIDATE_UI
7797 _system_scale = elm_config_scale_get ();
7799 /* Set elementary scale */
7800 if (_screen_width) {
7801 _app_scale = _screen_width / 720.0;
7802 elm_config_scale_set (_app_scale);
7804 snprintf (buf, sizeof (buf), "%4.3f", _app_scale);
7805 setenv ("ELM_SCALE", buf, 1);
7807 #endif /* CANDIDATE */
7809 signal (SIGQUIT, signalhandler);
7810 signal (SIGTERM, signalhandler);
7811 signal (SIGINT, signalhandler);
7812 signal (SIGHUP, signalhandler);
7814 check_time ("EFL Panel launch time");
7816 if (!isf_cynara_initialize())
7817 LOGW ("Failed to initialize cynara");
7819 #if ISF_BUILD_CANDIDATE_UI
7822 ecore_main_loop_begin ();
7823 #endif /* CANDIDATE */
7825 LOGW("out of loop");
7827 isf_cynara_finish();
7832 #ifdef HAVE_BLUETOOTH
7833 /* deinitialize the callback function of Bluetooth connection */
7834 ret = bt_hid_host_deinitialize ();
7835 if (ret != BT_ERROR_NONE)
7836 LOGW ("bt_hid_host_deinitialize failed: %d", ret);
7838 ret = bt_deinitialize ();
7839 if (ret != BT_ERROR_NONE)
7840 LOGW ("bt_deinitialize failed: %d", ret);
7844 if (xclient_message_handler) {
7845 ecore_event_handler_del (xclient_message_handler);
7846 xclient_message_handler = NULL;
7849 if (xwindow_property_handler) {
7850 ecore_event_handler_del (xwindow_property_handler);
7851 xwindow_property_handler = NULL;
7854 if (xwindow_focus_out_handler) {
7855 ecore_event_handler_del (xwindow_focus_out_handler);
7856 xwindow_focus_out_handler = NULL;
7861 /* Remove callback function for input language and display language */
7862 vconf_ignore_key_changed (VCONFKEY_LANGSET, display_language_changed_cb);
7863 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
7867 #if ISF_BUILD_CANDIDATE_UI
7868 ui_destroy_candidate_window ();
7869 ui_candidate_delete_check_size_timer ();
7870 ui_candidate_delete_longpress_timer ();
7871 ui_candidate_delete_destroy_timer ();
7872 #endif /* CANDIDATE */
7873 #ifdef HAVE_PKGMGR_INFO
7875 package_manager_destroy (pkgmgr);
7879 delete_ise_check_pid_alive_timer();
7881 #if ISF_BUILD_CANDIDATE_UI
7887 unregister_edbus_signal_handler ();
7889 if (_info_manager) {
7891 _info_manager->stop ();
7892 } catch (scim::Exception & e) {
7893 std::cerr << "Exception is thrown from _info_manager->stop (), error is " << e.what () << "\n";
7895 delete _info_manager;
7897 _config_connection.disconnect ();
7898 if (!_config.null ())
7900 ConfigBase::set (0);
7903 delete config_module;
7905 #if ISF_BUILD_CANDIDATE_UI
7909 #endif /* CANDIDATE */
7912 if ((display_name_c > 0) && new_argv [display_name_c]) {
7913 free (new_argv [display_name_c]);
7918 ISF_SAVE_LOG ("ret=%d", ret);
7920 std::cerr << "Successfully exited.\n";
7923 std::cerr << "Abnormally exited.\n";
7929 vi:ts=4:nowrap:expandtab