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>
42 #include <Ecore_File.h>
44 #include "scim_private.h"
46 #include "scim_stl_map.h"
47 #if ISF_BUILD_CANDIDATE_UI
49 #include <Elementary.h>
52 #include <Ecore_Wayland.h>
53 #endif /* HAVE_ECOREWL */
56 #endif /* HAVE_ECOREX */
59 #include <X11/Xatom.h>
66 #endif /* HAVE_FEEDBACK */
67 #endif /* CANDIDATE */
70 #include <vconf-keys.h>
73 #ifdef HAVE_NOTIFICATION
74 #include <notification.h>
75 #include <notification_internal.h>
81 #include <bluetooth.h>
83 #ifdef HAVE_PKGMGR_INFO
84 #include <package_manager.h>
85 #include <pkgmgr-info.h>
87 #include <app_control.h>
90 #include "isf_panel_efl.h"
91 #include "isf_panel_utility.h"
92 #include "isf_query_utility.h"
94 #include "privilege_checker.h"
95 #include "remote_input.h"
96 #include "tizen_profile.h"
101 /////////////////////////////////////////////////////////////////////////////
102 // Declaration of macro.
103 /////////////////////////////////////////////////////////////////////////////
104 #define EFL_CANDIDATE_THEME1 (SCIM_DATADIR "/isf_candidate_theme1.edj")
106 #define ISF_CANDIDATE_TABLE 0
108 #define ISF_EFL_AUX 1
109 #define ISF_EFL_CANDIDATE_0 2
110 #define ISF_EFL_CANDIDATE_ITEMS 3
112 #define ISE_DEFAULT_HEIGHT_PORTRAIT 444
113 #define ISE_DEFAULT_HEIGHT_LANDSCAPE 316
115 #define ISF_CANDIDATE_DESTROY_DELAY 3
116 #define ISF_ISE_HIDE_DELAY 0.15
118 #define ISF_PREEDIT_BORDER 16
119 #define ISE_LAUNCH_TIMEOUT 2.0
121 #define ISF_POP_PLAY_ICON_FILE (SCIM_ICONDIR "/pop_play.png")
122 #define ISF_KEYBOARD_ICON_FILE (SCIM_ICONDIR "/noti_keyboard_connected.png")
123 #define ISF_ISE_SELECTOR_ICON_FILE "/noti_keyboard.png"
125 #define HOST_BUS_NAME "org.tizen.usb.host"
126 #define HOST_OBJECT_PATH "/Org/Tizen/Usb/Host"
127 #define HOST_INTERFACE_NAME "org.tizen.usb.host"
128 #define HOST_KEYBOARD_SIGNAL "usbkeyboard"
129 #define HOST_ADDED "added"
130 #define HOST_REMOVED "removed"
132 #define E_PROP_DEVICEMGR_INPUTWIN "DeviceMgr Input Window"
135 /////////////////////////////////////////////////////////////////////////////
136 // Declaration of external variables.
137 /////////////////////////////////////////////////////////////////////////////
138 extern MapStringVectorSizeT _groups;
139 extern std::vector<ImeInfoDB> _ime_info;
141 CommonLookupTable g_isf_candidate_table;
144 /////////////////////////////////////////////////////////////////////////////
145 // Declaration of internal data types.
146 /////////////////////////////////////////////////////////////////////////////
147 typedef enum _WINDOW_STATE {
148 WINDOW_STATE_HIDE = 0,
149 WINDOW_STATE_WILL_HIDE,
150 WINDOW_STATE_WILL_SHOW,
155 typedef struct NotiData
164 typedef std::vector < std::pair <String, uint32> > VectorPairStringUint32;
166 /////////////////////////////////////////////////////////////////////////////
167 // Declaration of internal functions.
168 /////////////////////////////////////////////////////////////////////////////
169 #if ISF_BUILD_CANDIDATE_UI
170 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect);
171 #endif /* CANDIDATE */
174 static void efl_set_transient_for_app_window (Ecore_X_Window window);
176 #if ISF_BUILD_CANDIDATE_UI
177 static int efl_get_app_window_angle (void);
178 #endif /* CANDIDATE */
179 static int efl_get_ise_window_angle (void);
180 #if ISF_BUILD_CANDIDATE_UI
182 static int efl_get_quickpanel_window_angle (void);
183 #endif /* HAVE_ECOREX */
185 static int ui_candidate_get_valid_height (void);
186 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd = true, bool will_hide = false);
187 static void ui_destroy_candidate_window (void);
188 static void ui_settle_candidate_window (void);
189 static void ui_candidate_show (bool bSetVirtualKbd = true);
190 static void ui_create_candidate_window (void);
191 static void update_table (int table_type, const LookupTable &table);
192 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info);
193 #endif /* CANDIDATE */
194 static void set_soft_candidate_geometry (int x, int y, int width, int height);
195 #if ISF_BUILD_CANDIDATE_UI
196 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack);
197 static void ui_tts_focus_rect_hide (void);
198 #endif /* CANDIDATE */
200 #if ISF_BUILD_CANDIDATE_UI
201 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);
202 static bool tokenize_tag (const String& str, struct image *image_data);
203 #endif /* CANDIDATE */
205 static void launch_default_soft_keyboard (keynode_t *key = NULL, void* data = NULL);
207 /* PanelAgent related functions */
208 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident);
210 static void slot_focus_in (void);
211 static void slot_focus_out (void);
212 static void slot_expand_candidate (void);
213 static void slot_contract_candidate (void);
214 static void slot_set_candidate_style (int portrait_line, int mode);
215 static void slot_update_input_context (int type, int value);
216 static void slot_update_ise_geometry (int x, int y, int width, int height);
217 static void slot_update_spot_location (int x, int y, int top_y);
218 static void slot_update_factory_info (const PanelFactoryInfo &info);
219 static void slot_show_preedit_string (void);
220 static void slot_show_aux_string (void);
221 static void slot_show_candidate_table (void);
222 static void slot_hide_preedit_string (void);
223 static void slot_hide_aux_string (void);
224 static void slot_hide_candidate_table (void);
225 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret);
226 static void slot_update_preedit_caret (int caret);
227 static void slot_update_aux_string (const String &str, const AttributeList &attrs);
228 static void slot_update_candidate_table (const LookupTable &table);
229 static void slot_select_candidate (int index);
230 static void slot_set_active_ise (const String &uuid, bool changeDefault);
231 static bool slot_get_ise_list (std::vector<String> &list);
232 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info);
233 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option);
234 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled);
235 static void slot_show_helper_ise_list (void);
236 static void slot_show_helper_ise_selector (void);
237 static bool slot_is_helper_ise_enabled (String appid, int &enabled);
238 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name);
239 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list);
240 static void slot_get_language_list (std::vector<String> &name);
241 static void slot_get_all_language (std::vector<String> &lang);
242 static void slot_get_ise_language (char *name, std::vector<String> &list);
243 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info);
244 static void slot_get_candidate_geometry (struct rectinfo &info);
245 static void slot_get_input_panel_geometry (struct rectinfo &info);
246 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info);
247 static bool slot_check_privilege_by_sockfd (int client_id, String privilege);
248 static void slot_set_keyboard_ise (const String &uuid);
249 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid);
250 static void slot_accept_connection (int fd);
251 static void slot_close_connection (int fd);
252 static void slot_exit (void);
254 static void slot_register_helper (int id, const HelperInfo& info);
255 static void slot_register_helper_properties (int id, const PropertyList &props);
256 static void slot_show_ise (void);
257 static void slot_hide_ise (void);
259 static void slot_will_hide_ack (void);
260 static void slot_candidate_will_hide_ack (void);
262 static void slot_set_keyboard_mode (int mode);
263 static void slot_get_ise_state (int &state);
264 static void slot_start_default_ise (void);
265 static void slot_stop_default_ise (bool is_exist);
266 static void slot_run_helper (const String &uuid, const String &config, const String &display);
267 static bool slot_launch_option_application (String ime_appid);
269 #if ENABLE_REMOTE_INPUT
270 static void slot_send_remote_input_message (const String &msg, bool len);
271 static void slot_recv_remote_surrounding_text (int cursor, const String &text);
275 static Eina_Bool efl_create_control_window (void);
276 static Ecore_X_Window efl_get_app_window (void);
277 static Ecore_X_Window efl_get_quickpanel_window (void);
278 static Ecore_X_Window efl_get_global_navigation_window (void);
281 static void change_keyboard_mode (TOOLBAR_MODE_T mode);
282 static unsigned int get_ise_index (const String uuid);
283 static bool set_active_ise (const String &uuid, bool launch_ise);
284 static bool update_ise_list (std::vector<String> &list);
285 static void update_ise_locale (const char *lang = NULL);
286 #ifdef HAVE_NOTIFICATION
287 static void delete_notification (NotificationData *noti_data);
288 static void create_notification (NotificationData *noti_data);
289 static void show_ime_selector_notification (void);
291 static void set_language_and_locale (const char *lang_str);
292 static bool app_control_launch (const char *app_id);
294 /////////////////////////////////////////////////////////////////////////////
295 // Declaration of internal variables.
296 /////////////////////////////////////////////////////////////////////////////
297 #if ISF_BUILD_CANDIDATE_UI
298 static Evas_Object *_candidate_window = 0;
299 static Evas_Object *_candidate_area_1 = 0;
300 static Evas_Object *_candidate_area_2 = 0;
301 static Evas_Object *_candidate_bg = 0;
302 static Evas_Object *_candidate_0_scroll = 0;
303 static Evas_Object *_candidate_scroll = 0;
304 static Evas_Object *_scroller_bg = 0;
305 static Evas_Object *_candidate_0_table = 0;
306 static Evas_Object *_candidate_table = 0;
307 static Evas_Object *_candidate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
308 static Evas_Object *_candidate_text [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
309 static Evas_Object *_candidate_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
310 static Evas_Object *_candidate_pop_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
311 static Evas_Object *_seperate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
312 static Evas_Object *_seperate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
313 static Evas_Object *_line_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
314 static Evas_Object *_line_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
315 static Evas_Object *_more_btn = 0;
316 static Evas_Object *_close_btn = 0;
317 static bool _candidate_show_requested = false;
318 #endif /* CANDIDATE */
319 static bool _updated_hide_state_geometry = false;
320 #if ISF_BUILD_CANDIDATE_UI
321 static int _candidate_x = 0;
322 static int _candidate_y = 0;
323 static int _candidate_width = 0;
324 static int _candidate_height = 0;
325 #endif /* CANDIDATE */
326 static int _soft_candidate_width = 0;
327 static int _soft_candidate_height = 0;
328 #if ISF_BUILD_CANDIDATE_UI
329 static int _candidate_valid_height = 0;
331 static bool _candidate_area_1_visible = false;
332 static bool _candidate_area_2_visible = false;
333 static bool _aux_area_visible = false;
334 #endif /* CANDIDATE */
336 static ISF_CANDIDATE_MODE_T _candidate_mode = SOFT_CANDIDATE_WINDOW;
337 static ISF_CANDIDATE_PORTRAIT_LINE_T _candidate_port_line = ONE_LINE_CANDIDATE;
339 #if ISF_BUILD_CANDIDATE_UI
340 static int _candidate_port_width = 480;
341 static int _candidate_port_height_min = 76;
342 static int _candidate_port_height_min_2 = 150;
343 static int _candidate_port_height_max = 286;
344 static int _candidate_port_height_max_2 = 350;
345 static int _candidate_land_width = 784;
346 static int _candidate_land_height_min = 84;
347 static int _candidate_land_height_min_2 = 168;
348 static int _candidate_land_height_max = 150;
349 static int _candidate_land_height_max_2 = 214;
350 static int _candidate_area_1_pos [2] = {0, 2};
351 static int _more_btn_pos [4] = {369, 11, 689, 11};
352 static int _close_btn_pos [4] = {362, 211, 682, 75};
353 static int _more_btn_width = 80;
354 static int _more_btn_height = 64;
356 static int _h_padding = 4;
357 static int _v_padding = 2;
358 static int _item_min_width = 99;
359 static int _item_min_height = 82;
361 static int _candidate_scroll_0_width_min = 350;
362 static int _candidate_scroll_0_width_max = 670;
364 static int _candidate_scroll_width = 453;
365 static int _candidate_scroll_width_min = 453;
366 static int _candidate_scroll_width_max = 663;
367 static int _candidate_scroll_height_min = 124;
368 static int _candidate_scroll_height_max = 190;
370 const int MORE_BUTTON_INDEX = -1;
371 const int CLOSE_BUTTON_INDEX = -2;
372 const int INVALID_TTS_FOCUS_INDEX = -100;
373 static int _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
374 static uint32 _candidate_display_number = 0;
375 static std::vector<uint32> _candidate_row_items;
376 static Evas_Object *_tts_focus_rect = 0;
377 static bool _wait_stop_event = false;
379 static Evas_Object *_preedit_window = 0;
380 static Evas_Object *_preedit_text = 0;
381 static int _preedit_width = 100;
382 static int _preedit_height = 54;
384 static Evas_Object *_aux_area = 0;
385 static Evas_Object *_aux_line = 0;
386 static Evas_Object *_aux_table = 0;
387 static int _aux_height = 0;
388 static int _aux_port_width = 444;
389 static int _aux_land_width = 764;
390 static std::vector<Evas_Object *> _aux_items;
391 static std::vector<Evas_Object *> _aux_seperates;
393 static Evas_Object *_tmp_preedit_text = 0;
394 static Evas_Object *_tmp_aux_text = 0;
395 static Evas_Object *_tmp_candidate_text = 0;
397 static int _spot_location_x = -1;
398 static int _spot_location_y = -1;
399 static int _spot_location_top_y = -1;
400 static int _candidate_angle = 0;
401 #endif /* CANDIDATE */
403 static int _ise_angle = -1;
404 static int _ise_x = 0;
405 static int _ise_y = 0;
406 static int _ise_width = 0;
407 static int _ise_height = 0;
408 static WINDOW_STATE _ise_state = WINDOW_STATE_HIDE;
409 static WINDOW_STATE _candidate_state = WINDOW_STATE_HIDE;
411 #if ISF_BUILD_CANDIDATE_UI
412 static int _indicator_height = 0;//24;
413 static int _screen_width = 720;
414 static int _screen_height = 1280;
415 static float _width_rate = 1.0;
416 static float _height_rate = 1.0;
417 static int _blank_width = 30;
419 static String _candidate_name = String ("candidate");
420 static String _candidate_edje_file = String (EFL_CANDIDATE_THEME1);
422 static String _candidate_font_name = String ("Tizen");
423 static int _candidate_font_size = 38;
424 static int _aux_font_size = 38;
425 static int _click_object = 0;
426 static int _click_down_pos [2] = {0, 0};
427 static int _click_up_pos [2] = {0, 0};
428 static bool _is_click = true;
429 #endif /* CANDIDATE */
430 static String _initial_ise_uuid = String ("");
431 static String _locale_string = String ("");
432 static ConfigPointer _config;
433 static Connection _config_connection;
435 static InfoManager *_info_manager = 0;
437 static clock_t _clock_start;
439 #if ISF_BUILD_CANDIDATE_UI
440 static Ecore_Timer *_check_size_timer = NULL;
441 static Ecore_Timer *_longpress_timer = NULL;
442 static Ecore_Timer *_destroy_timer = NULL;
443 #endif /* CANDIDATE */
445 static Ecore_Timer *_off_prepare_done_timer = NULL;
447 #if ISF_BUILD_CANDIDATE_UI
448 static Ecore_Timer *_candidate_hide_timer = NULL;
449 #endif /* CANDIDATE */
450 static Ecore_Timer *_ise_hide_timer = NULL;
453 static Ecore_X_Window _ise_window = 0;
454 static Ecore_X_Window _app_window = 0;
455 static Ecore_X_Window _control_window = 0;
456 static Ecore_X_Window _input_win = 0;
459 #ifdef HAVE_PKGMGR_INFO
460 static package_manager_h pkgmgr = NULL;
461 static VectorPairStringUint32 g_pkgids_to_be_uninstalled;
462 static Ecore_Timer *g_release_uninstalled_ime_info_timer = NULL;
463 static String g_stopped_helper_pkgid = "";
464 static Ecore_Timer *g_start_default_helper_timer = NULL;
465 static VectorPairStringUint32 g_pkgids_to_be_updated_and_installed;
466 static String g_updated_helper_pkgid = "";
469 static bool _launch_ise_on_request = false;
470 static bool _auto_destroy_ise = false;
471 static bool _soft_keyboard_launched = false;
472 static bool _focus_in = false;
474 #if ISF_BUILD_CANDIDATE_UI
475 static bool candidate_expanded = false;
476 static int _candidate_image_count = 0;
477 static int _candidate_text_count = 0;
478 static int _candidate_pop_image_count = 0;
479 static int candidate_image_height = 38;
480 static int candidate_play_image_width_height = 19;
482 static const int CANDIDATE_TEXT_OFFSET = 2;
484 static double _app_scale = 1.0;
485 static double _system_scale = 1.0;
486 #endif /* CANDIDATE */
488 #ifdef HAVE_NOTIFICATION
489 static NotificationData hwkbd_module_noti = {"Input detected from hardware keyboard", "Tap to use virtual keyboard", ISF_KEYBOARD_ICON_FILE, "", 0};
490 static NotificationData ise_selector_module_noti = {"Select input method", "", "", "", 0};
493 #if ISF_BUILD_CANDIDATE_UI
495 static tts_h _tts = NULL;
499 static bool feedback_initialized = false;
501 #endif /* CANDIDATE */
504 static E_DBus_Connection *edbus_conn;
505 static E_DBus_Signal_Handler *edbus_handler;
508 #if ENABLE_REMOTE_INPUT
509 static Remote_Input* remote_input_impl = NULL;
510 static bool launch_remote_input = false;
513 #if ISF_BUILD_CANDIDATE_UI
515 static Ecore_Event_Handler *_candidate_show_handler = NULL;
517 #endif /* CANDIDATE */
519 static String ime_selector_app = "";
520 static String ime_list_app = "";
522 static Ecore_Timer *_ise_check_pid_alive_timer = NULL;
523 static const double _ise_check_pid_alive_time = 3.0f;
524 static String _ise_check_pid_alive_uuid;
526 static Ecore_Timer *g_monitor_user_data_path_timer = NULL;
529 EMOJI_IMAGE_WIDTH = 0,
532 EMOJI_IMAGE_TAG_FLAG,
533 EMOJI_IMAGE_POP_FLAG,
540 int emoji_option[EMOJI_IMAGE_END];
543 /* This structure stores the geometry information reported by ISE */
546 bool valid; /* Whether this information is currently valid */
547 int angle; /* For which angle this information is useful */
548 struct rectinfo geometry; /* Geometry information */
551 static struct GeometryCache _ise_reported_geometry = {0, 0, {0, 0, 0, 0}};
552 static struct GeometryCache _portrait_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
553 static struct GeometryCache _landscape_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
556 static void get_input_window (void)
559 Ecore_X_Atom atom = 0;
561 if (_input_win == 0) {
562 atom = ecore_x_atom_get (E_PROP_DEVICEMGR_INPUTWIN);
563 win_ret = ecore_x_window_prop_window_get (ecore_x_window_root_first_get (), atom, &_input_win, 1);
564 if (_input_win == 0 || win_ret < 1) {
565 LOGW ("Input window is NULL!");
567 ecore_x_event_mask_set (_input_win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
573 static int pkgmgr_get_appinfo (const char *appid, pkgmgrinfo_appinfo_h *handle)
576 /* Try to get in global packages */
577 ret = pkgmgrinfo_appinfo_get_appinfo (appid, handle);
578 if (ret != PMINFO_R_OK) {
579 LOGW ("[pkgmgrinfo_appinfo_get_appinfo] appid : '%s', ret : %d, uid : %d", appid, ret, getuid ());
580 /* Try to get in user packages */
581 ret = pkgmgrinfo_appinfo_get_usr_appinfo (appid, getuid (), handle);
582 if (ret != PMINFO_R_OK)
583 LOGW ("[pkgmgrinfo_appinfo_get_usr_appinfo] appid : '%s', ret : %d", appid, ret);
590 static void usb_keyboard_signal_cb (void *data, DBusMessage *msg)
600 if (dbus_message_is_signal (msg, HOST_INTERFACE_NAME, HOST_KEYBOARD_SIGNAL) == 0) {
601 LOGW ("HOST_KEYBOARD_SIGNAL");
605 dbus_error_init (&err);
607 if (dbus_message_get_args (msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) {
608 LOGW ("DBUS_TYPE_INVALID");
614 if (!strncmp (str, HOST_ADDED, strlen (HOST_ADDED))) {
619 if (!strncmp (str, HOST_REMOVED, strlen (HOST_REMOVED))) {
620 LOGD ("HOST_REMOVED");
621 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
622 change_keyboard_mode (TOOLBAR_HELPER_MODE);
627 LOGW ("ERROR: msg (%s) is improper", str);
630 static void unregister_edbus_signal_handler (void)
633 LOGD ("unregister signal handler for keyboard");
635 e_dbus_signal_handler_del (edbus_conn, edbus_handler);
636 edbus_handler = NULL;
638 e_dbus_connection_close (edbus_conn);
644 static int register_edbus_signal_handler (void)
649 while (e_dbus_init () == 0) {
656 edbus_conn = e_dbus_bus_get (DBUS_BUS_SYSTEM);
658 LOGW ("edbus connection fail");
662 edbus_handler = e_dbus_signal_handler_add (edbus_conn, NULL, HOST_OBJECT_PATH, HOST_INTERFACE_NAME, HOST_KEYBOARD_SIGNAL, usb_keyboard_signal_cb, NULL);
663 if (!edbus_handler) {
664 LOGW ("cannot register signal");
668 LOGD ("Success edbus register");
674 #ifdef HAVE_NOTIFICATION
675 static void delete_notification (NotificationData *noti_data)
677 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
679 if (!_MOBILE) return;
681 if (noti_data->noti_id != 0) {
682 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
683 LOGD ("deleted notification : %s", noti_data->launch_app.c_str ());
684 noti_data->noti_id = 0;
688 static void create_notification (NotificationData *noti_data)
690 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
692 notification_h notification = NULL;
695 if (!_MOBILE) return;
697 if (noti_data->noti_id != 0) {
698 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
699 noti_data->noti_id = 0;
702 notification = notification_create (NOTIFICATION_TYPE_ONGOING);
703 if (notification != NULL) {
704 notification_set_pkgname (notification, "isf-panel-efl");
705 notification_set_layout (notification, NOTIFICATION_LY_ONGOING_EVENT);
706 notification_set_image (notification, NOTIFICATION_IMAGE_TYPE_ICON, noti_data->icon.c_str());
707 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_TITLE, _(noti_data->title.c_str()), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
708 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_CONTENT, _(noti_data->content.c_str ()), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
709 notification_set_display_applist (notification, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
711 app_control_h service = NULL;
712 if (app_control_create (&service) == APP_CONTROL_ERROR_NONE) {
713 app_control_set_operation (service, APP_CONTROL_OPERATION_DEFAULT);
714 app_control_set_app_id (service, noti_data->launch_app.c_str ());
716 notification_set_launch_option (notification, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)service);
717 ret = notification_insert (notification, ¬i_data->noti_id);
718 if (ret != NOTIFICATION_ERROR_NONE) {
719 LOGW ("Failed to insert notification. error code : %d", ret);
721 app_control_destroy (service);
724 LOGW ("Failed to create appcontrol");
726 notification_free (notification);
729 LOGW ("Failed to create notification");
732 #endif /* HAVE_NOTIFICATION */
734 #if ISF_BUILD_CANDIDATE_UI
735 static bool tokenize_tag (const String& str, struct image *image_token)
737 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
738 if (str.length () <= 0) {
739 LOGW ("str is empty!!!");
743 char **tag_str = NULL;
745 tag_str = eina_str_split (str.c_str (), "\u3013", 0);
750 for (i = 0; tag_str [i]; i++) {
752 if (str.length () == strlen (tag_str[i])) {
762 image_token->path = String (tag_str[i]);
764 if (i - 1 < EMOJI_IMAGE_END)
765 image_token->emoji_option [i - 1] = atoi (tag_str[i]);
767 LOGW ("emoji option is more than EMOJI_IMAGE_END!!!");
779 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)
781 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
783 struct image image_data;
784 int object_width = 0, text_width = 0, image_width = 0, image_height = 0, max_width = 0, button_width = 0;
786 int image_get_width = 0, image_get_height = 0;
787 char image_key [10] = {0, };
788 char **splited_string = NULL;
789 char **sub_splited_string = NULL;
790 double image_rate = 0.0;
791 bool tokenize_result = false;
792 bool candidate_is_long = false;
794 Evas_Object *candidate_object_table = NULL;
795 Evas_Object *candidate_object_table_bg_rect = NULL;
796 Evas_Object *candidate_left_padding = NULL;
798 candidate_object_table = elm_table_add (parent);
800 candidate_left_padding = evas_object_rectangle_add (evas_object_evas_get (parent));
801 evas_object_size_hint_weight_set (candidate_left_padding, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
802 evas_object_size_hint_align_set (candidate_left_padding, EVAS_HINT_FILL, EVAS_HINT_FILL);
803 evas_object_size_hint_min_set (candidate_left_padding, _blank_width, 1);
804 evas_object_color_set (candidate_left_padding, 0, 0, 0, 0);
805 elm_table_pack (candidate_object_table, candidate_left_padding, 0, 0, _blank_width, 1);
806 evas_object_show (candidate_left_padding);
808 object_width += _blank_width;
809 if (item_num > 1 && item_index == 0)
810 button_width = 92 * _width_rate;
814 splited_string = eina_str_split (str.c_str (), "\uE000", 0);
815 if (splited_string) {
816 for (i = 0; splited_string [i]; i++) {
817 if (candidate_is_long)
819 sub_splited_string = eina_str_split (splited_string [i], "\uE001", 0);
820 if (sub_splited_string) {
821 for (j = 0; sub_splited_string [j]; j++) {
822 if (candidate_is_long)
824 tokenize_result = tokenize_tag (sub_splited_string [j], &image_data);
825 if (tokenize_result && _candidate_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
826 _candidate_image [_candidate_image_count] = elm_image_add (parent);
827 snprintf (image_key, sizeof (image_key), "%d", _candidate_image_count);
828 elm_image_file_set (_candidate_image [_candidate_image_count], image_data.path.c_str (), image_key);
829 elm_image_animated_set (_candidate_image [_candidate_image_count], EINA_TRUE);
830 elm_image_animated_play_set (_candidate_image [_candidate_image_count], EINA_TRUE);
831 elm_image_object_size_get (_candidate_image [_candidate_image_count], &image_get_width, &image_get_height);
832 LOGD ("image_path=%s, key=%s", image_data.path.c_str (), image_key);
834 if (image_get_height > image_get_width)
835 image_rate = ((double)candidate_image_height / (double)image_get_width);
837 image_rate = ((double)candidate_image_height / (double)image_get_height);
839 image_width = (int)((double)image_get_width * image_rate);
840 image_height = candidate_image_height;
842 if (_candidate_angle == 90 || _candidate_angle == 270)
843 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
845 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
847 if (image_width > max_width) {
848 Evas_Object *candidate_end = edje_object_add (evas_object_evas_get (parent));
849 edje_object_file_set (candidate_end, _candidate_edje_file.c_str (), _candidate_name.c_str ());
850 evas_object_show (candidate_end);
851 edje_object_part_text_set (candidate_end, "candidate", "...");
852 edje_object_scale_set (_candidate_text [_candidate_text_count], _height_rate);
854 text_width = max_width;
855 evas_object_size_hint_min_set (candidate_end, text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
856 if (HighLight || SetBack) {
857 set_highlight_color (candidate_end, ForeGround, BackGround, SetBack);
859 elm_table_pack (candidate_object_table, candidate_end, object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
860 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
862 if (_candidate_image [_candidate_image_count]) {
863 evas_object_del (_candidate_image [_candidate_image_count]);
864 _candidate_image [_candidate_image_count] = NULL;
866 candidate_is_long = true;
870 evas_object_resize (_candidate_image [_candidate_image_count], image_width, image_height);
871 evas_object_show (_candidate_image [_candidate_image_count]);
872 evas_object_size_hint_min_set (_candidate_image [_candidate_image_count], image_width, image_height);
874 elm_table_pack (candidate_object_table, _candidate_image [_candidate_image_count], object_width, 1, image_width, image_height);
875 object_width += image_width;
876 _candidate_image_count++;
878 if (image_data.emoji_option [EMOJI_IMAGE_POP_FLAG] == 1 && image_width > 0 && _candidate_pop_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
879 _candidate_pop_image [_candidate_pop_image_count] = elm_image_add (parent);
880 elm_image_file_set (_candidate_pop_image [_candidate_pop_image_count], ISF_POP_PLAY_ICON_FILE, image_key);
881 evas_object_resize (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
882 evas_object_show (_candidate_pop_image [_candidate_pop_image_count]);
883 evas_object_size_hint_min_set (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
885 elm_table_pack (candidate_object_table, _candidate_pop_image [_candidate_pop_image_count],
886 object_width - candidate_play_image_width_height, image_height - candidate_play_image_width_height - 2,
887 candidate_play_image_width_height, candidate_play_image_width_height);
889 _candidate_pop_image_count++;
892 } else if (strlen (sub_splited_string [j]) > 0 && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
893 _candidate_text [_candidate_text_count] = edje_object_add (evas_object_evas_get (parent));
894 edje_object_file_set (_candidate_text [_candidate_text_count], _candidate_edje_file.c_str (), _candidate_name.c_str ());
895 evas_object_show (_candidate_text [_candidate_text_count]);
896 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", sub_splited_string [j]);
897 edje_object_text_class_set (_candidate_text [_candidate_text_count], "tizen",
898 _candidate_font_name.c_str (), _candidate_font_size);
899 evas_object_text_text_set (_tmp_candidate_text, sub_splited_string [j]);
900 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &text_width, NULL);
902 if (_candidate_angle == 90 || _candidate_angle == 270)
903 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
905 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
907 if (text_width > max_width) {
908 candidate_is_long = true;
909 /* In order to avoid overlap issue, calculate show_string */
910 String show_string = String (sub_splited_string [j]);
911 int show_length = text_width;
912 while (show_length > max_width && show_string.length () > 1) {
913 show_string = show_string.substr (0, show_string.length () - 1);
914 evas_object_text_text_set (_tmp_candidate_text, (show_string + String ("...")).c_str ());
915 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &show_length, NULL);
917 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", (show_string + String ("...")).c_str ());
918 text_width = max_width;
921 evas_object_size_hint_min_set (_candidate_text [_candidate_text_count], text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
922 if (HighLight || SetBack) {
923 set_highlight_color (_candidate_text [_candidate_text_count], ForeGround, BackGround, SetBack);
925 elm_table_pack (candidate_object_table, _candidate_text [_candidate_text_count], object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
926 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
927 _candidate_text_count++;
933 if (splited_string [0])
934 free (splited_string [0]);
936 free (splited_string);
939 if (sub_splited_string) {
940 if (sub_splited_string [0])
941 free (sub_splited_string [0]);
943 free (sub_splited_string);
946 *total_width = object_width + _blank_width;
948 candidate_object_table_bg_rect = edje_object_add (evas_object_evas_get (parent));
949 edje_object_file_set (candidate_object_table_bg_rect, _candidate_edje_file.c_str (), "candidate_object_table");
950 evas_object_size_hint_weight_set (candidate_object_table_bg_rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
951 evas_object_size_hint_align_set (candidate_object_table_bg_rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
952 evas_object_size_hint_min_set (candidate_object_table_bg_rect, *total_width, _item_min_height);
953 elm_table_pack (candidate_object_table, candidate_object_table_bg_rect, 0, 0, *total_width, _item_min_height);
954 evas_object_show (candidate_object_table_bg_rect);
956 evas_object_size_hint_align_set (candidate_object_table, EVAS_HINT_FILL, EVAS_HINT_FILL);
957 evas_object_size_hint_weight_set (candidate_object_table, EVAS_HINT_EXPAND, 0.0);
959 return candidate_object_table;
961 #endif /* CANDIDATE */
963 /////////////////////////////////////////////////////////////////////////////
964 // Implementation of internal functions.
965 /////////////////////////////////////////////////////////////////////////////
967 * @brief Print system time point for panel performance.
969 * @param strInfo The output information.
971 static void check_time (const char *strInfo)
973 gettime (_clock_start, strInfo);
974 ISF_LOG ("%s ppid=%d pid=%d\n", strInfo, getppid (), getpid ());
978 * @brief Flush memory for elm.
982 static void flush_memory (void)
984 #if ISF_BUILD_CANDIDATE_UI
985 elm_cache_all_flush ();
990 #if ISF_BUILD_CANDIDATE_UI
992 * @brief Get ISE geometry information.
993 * Returns the "expected" ISE geometry when kbd_state is ON, otherwise w/h set to 0
995 * @param info The data is used to store ISE position and size.
996 * @param kbd_state The keyboard state.
998 static struct rectinfo get_ise_geometry ()
1000 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1002 struct rectinfo info = {0, 0, 0, 0};
1006 Ecore_X_Window gnb_win = efl_get_global_navigation_window ();
1008 ecore_x_window_size_get (gnb_win, &w, &h);
1011 int win_w = _screen_width, win_h = _screen_height;
1012 int angle = (_ise_angle == -1) ? efl_get_app_window_angle () : _ise_angle;
1015 /* The height of global navigation bar */
1018 if (angle == 90 || angle == 270) {
1019 win_w = _screen_height;
1020 win_h = _screen_width;
1025 /* If we have geometry reported by ISE, use the geometry information */
1026 if (_ise_reported_geometry.valid && _ise_reported_geometry.angle == angle) {
1027 info = _ise_reported_geometry.geometry;
1028 /* But still, if the current ISE is not in SHOW state, set w/h to 0 */
1029 if (_ise_state != WINDOW_STATE_SHOW) {
1030 info.pos_y = (win_h > win_w) ? win_h : win_w;
1035 /* READ ISE's SIZE HINT HERE */
1038 int pos_x, pos_y, width, height;
1039 if (ecore_x_e_window_rotation_geometry_get (_ise_window, angle,
1040 &pos_x, &pos_y, &width, &height)) {
1044 if (angle == 90 || angle == 270) {
1045 info.width = height;
1046 info.height = width;
1049 info.height = height;
1052 info.pos_x = (int)info.width > win_w ? 0 : (win_w - info.width) / 2;
1053 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
1055 info.pos_y = (win_h > win_w) ? win_h : win_w;
1059 if (_ise_state == WINDOW_STATE_SHOW) {
1060 info.pos_y = win_h - info.height - gnb_height;
1062 info.pos_y = (win_h > win_w) ? win_h : win_w;
1068 LOGD ("angle : %d, w_angle : %d, mode : %d, Geometry : %d %d %d %d",
1070 _info_manager->get_current_toolbar_mode (),
1071 info.pos_x, info.pos_y, info.width, info.height);
1080 // FIXME: Get the ISE's SIZE.
1088 _ise_width = info.width;
1089 _ise_height = info.height;
1093 #endif /* CANDIDATE */
1097 * @brief Set keyboard geometry for autoscroll.
1098 * This includes the ISE geometry together with candidate window
1100 * @param kbd_state The keyboard state.
1102 static void set_keyboard_geometry_atom_info (Ecore_X_Window window, struct rectinfo ise_rect)
1104 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1106 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
1109 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1110 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1111 ise_rect.width = _candidate_width;
1112 ise_rect.height = _candidate_height;
1114 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
1115 ise_rect.width = _soft_candidate_width;
1116 ise_rect.height = _soft_candidate_height;
1119 int angle = efl_get_app_window_angle ();
1120 if (angle == 90 || angle == 270)
1121 ise_rect.pos_y = _screen_width - ise_rect.height;
1123 ise_rect.pos_y = _screen_height - ise_rect.height;
1125 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1126 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1127 _candidate_valid_height = ui_candidate_get_valid_height ();
1128 if ((_candidate_height - _candidate_valid_height) > _ise_height) {
1129 _candidate_valid_height = _candidate_height;
1130 ise_rect.pos_y = ise_rect.pos_y + ise_rect.height - _candidate_height;
1131 ise_rect.height = _candidate_height;
1133 ise_rect.pos_y -= _candidate_valid_height;
1134 ise_rect.height += _candidate_valid_height;
1140 ecore_x_e_illume_keyboard_geometry_set (window, ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1141 LOGD ("KEYBOARD_GEOMETRY_SET : %d %d %d %d", ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1142 SCIM_DEBUG_MAIN (3) << " KEYBOARD_GEOMETRY x=" << ise_rect.pos_x << " y=" << ise_rect.pos_y
1143 << " width=" << ise_rect.width << " height=" << ise_rect.height << "\n";
1145 /* even the kbd_state is OFF, consider the keyboard is still ON if we have candidate opened */
1146 if (ise_rect.width == 0 && ise_rect.height == 0) {
1147 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1149 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1151 if (_ise_angle == 0 || _ise_angle == 180) {
1152 _portrait_recent_ise_geometry.valid = true;
1153 _portrait_recent_ise_geometry.geometry = ise_rect;
1156 _landscape_recent_ise_geometry.valid = true;
1157 _landscape_recent_ise_geometry.geometry = ise_rect;
1164 * @brief Get ISE index according to uuid.
1166 * @param uuid The ISE uuid.
1168 * @return The ISE index
1170 static unsigned int get_ise_index (const String uuid)
1172 unsigned int index = 0;
1173 if (uuid.length () > 0) {
1174 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1175 if (uuid == _ime_info[i].appid) {
1185 static void set_keyboard_engine (String active_uuid)
1187 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
1188 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
1189 if (active_uuid != keyboard_uuid) {
1190 _info_manager->change_factory (active_uuid);
1191 _config->write (IMENGINE_KEY, active_uuid);
1196 static void _update_ime_info(void)
1198 std::vector<String> ise_langs;
1201 isf_pkg_select_all_ime_info_db(_ime_info);
1203 /* Update _groups */
1205 for (size_t i = 0; i < _ime_info.size (); ++i) {
1206 scim_split_string_list(ise_langs, _ime_info[i].languages);
1207 for (size_t j = 0; j < ise_langs.size (); j++) {
1208 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
1209 _groups[ise_langs[j]].push_back (i);
1215 static void _initialize_ime_info (void)
1217 std::vector<ImeInfoDB>::iterator iter;
1218 VectorPairStringUint32 ime_on_off;
1219 // Store is_enabled values of each keyboard
1220 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1221 if (iter->mode == TOOLBAR_HELPER_MODE) {
1222 ime_on_off.push_back (std::make_pair (iter->appid, iter->is_enabled));
1225 // Delete the whole ime_info DB and reload
1226 isf_db_delete_ime_info ();
1227 _update_ime_info ();
1228 // Restore is_enabled value to valid keyboards
1229 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1230 if (iter->mode == TOOLBAR_HELPER_MODE) {
1231 for (VectorPairStringUint32::iterator it = ime_on_off.begin (); it != ime_on_off.end (); it++) {
1232 if (it->first.compare (iter->appid) == 0) {
1233 if (it->second != iter->is_enabled) {
1234 iter->is_enabled = it->second;
1235 isf_db_update_is_enabled_by_appid (iter->appid.c_str (), static_cast<bool>(iter->is_enabled));
1237 ime_on_off.erase (it);
1245 #ifdef HAVE_PKGMGR_INFO
1247 * @brief Insert or update ime_info data with pkgid.
1249 * @param pkgid pkgid to insert/update ime_info table.
1251 * @return 1 on successful insert, 2 on successful update, -1 if pkgid is not IME package, otherwise return 0.
1253 static int _isf_insert_ime_info_by_pkgid(const char *pkgid)
1256 pkgmgrinfo_pkginfo_h handle = NULL;
1257 int result = 0; // 0: not IME, 1: Inserted, 2: Updated (because of the same appid)
1258 uid_t uid = getuid ();
1262 LOGW ("pkgid is null.");
1266 /* Try to get in global packages */
1267 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &handle);
1268 if (ret != PMINFO_R_OK) {
1269 /* Try to get in user packages */
1270 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, uid, &handle);
1271 if (ret != PMINFO_R_OK) {
1272 LOGW ("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d, uid : %d", pkgid, ret, getuid ());
1281 /* Try to get in user packages */
1282 ret = pkgmgrinfo_appinfo_get_usr_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result, uid);
1285 /* Try to get in global packages */
1286 ret = pkgmgrinfo_appinfo_get_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result);
1289 if (ret != PMINFO_R_OK) {
1290 LOGW ("Failed to call %s failed(%d)", user ? "pkgmgrinfo_appinfo_get_usr_list" : "pkgmgrinfo_appinfo_get_list", ret);
1297 pkgmgrinfo_pkginfo_destroy_pkginfo (handle);
1303 * @brief Timer to start initial Helper ISE if the active (selected) 3rd party keyboard is uninstalled.
1305 * @param data User data
1307 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1308 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1310 static Eina_Bool _start_default_helper_timer(void *data)
1312 std::vector<String> total_appids;
1313 std::vector<ImeInfoDB>::iterator it;
1314 VectorPairStringUint32::iterator iter;
1316 /* Let panel know that ISE is deleted... */
1317 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1318 total_appids.push_back(it->appid);
1320 if (total_appids.size() > 0)
1321 _info_manager->update_ise_list (total_appids);
1323 LOGD ("Try to start the initial helper");
1324 set_active_ise(_initial_ise_uuid, true);
1326 for (iter = g_pkgids_to_be_uninstalled.begin (); iter != g_pkgids_to_be_uninstalled.end (); iter++) {
1327 if (iter->first.compare(g_stopped_helper_pkgid) == 0) {
1328 g_pkgids_to_be_uninstalled.erase (iter);
1332 g_stopped_helper_pkgid = "";
1334 g_start_default_helper_timer = NULL;
1335 return ECORE_CALLBACK_CANCEL;
1339 * @brief Timer to release uninstalled IME related info; g_pkgids_to_be_uninstalled has appid and is_enabled.
1341 * @param data User data
1343 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1344 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1346 static Eina_Bool _release_uninstalled_pkginfo_timer(void *data)
1348 g_pkgids_to_be_uninstalled.clear ();
1349 g_release_uninstalled_ime_info_timer = NULL;
1350 return ECORE_CALLBACK_CANCEL;
1354 * @brief Called when the package is installed, uninstalled or updated, and the progress of the request to the package manager changes.
1356 * @param[in] type The type of the package to be installed, uninstalled or updated
1357 * @param[in] package The name of the package to be installed, uninstalled or updated
1358 * @param[in] event_type The type of the request to the package manager
1359 * @param[in] event_state The current state of the request to the package manager
1360 * @param[in] progress The progress for the request that is being processed by the package manager \n
1361 * The range of progress is from 0 to 100
1362 * @param[in] error The error code when the package manager failed to process the request
1363 * @param[in] user_data The user data passed from package_manager_set_event_cb()
1364 * @see package_manager_set_event_cb()
1365 * @see package_manager_unset_event_cb()
1367 INFO: Package install/update/uninstall scenario
1368 Install and Uninstall are obviously simple.
1369 Install: just INSTALL
1370 Uninstall: just UNINSTALL
1371 Update package (change the source codes in IME project and Run As again), there are four scenarios:
1374 2. UNINSTALL -> INSTALL
1375 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1376 and change Application ID in tizen-manifest.xml file and Run As.
1377 3. UPDATE -> INSTALL
1378 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1379 and change Application ID in tizen-manifest.xml file and Run As.
1380 At UPDATE event, pkgid (package parameter) is invalid...
1382 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1383 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1385 If multiple packages (including non-IME pkgs) are uninstalled and installed; Z300H UPS (ultra power saving) mode scenario.
1386 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
1388 Assuming IMEngine won't be changed through this. IMEngine might have multiple appids for one pkgid.
1389 Assuming preinstalled IME won't be changed through this.
1391 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)
1393 String current_ime_appid; // now appid is uuid.
1394 std::vector<String> appids;
1395 std::vector<String> total_appids;
1396 std::vector<ImeInfoDB>::iterator it;
1397 std::vector<String>::iterator it2;
1398 VectorPairStringUint32::iterator it3;
1401 if (!package || !type)
1404 if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
1405 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1406 LOGD ("type=%s package=%s event_type=UPDATE event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1408 ret = _isf_insert_ime_info_by_pkgid (package); // If package is not IME, -1 would be returned.
1409 if (ret == 1) { // In case the package is updated with the changed appid. In this case, there will be two IMEs
1410 ret = isf_db_select_appids_by_pkgid (package, appids);
1412 if (_ime_info.size () > 0 && _ime_info [get_ise_index (appids.front ())].is_enabled)
1413 isf_db_update_is_enabled_by_appid (appids.back ().c_str (), true);
1414 isf_db_delete_ime_info_by_appid (appids.front ().c_str ());
1417 _update_ime_info ();
1419 /* Let panel know that ise list is changed... */
1420 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1421 total_appids.push_back(it->appid);
1423 if (total_appids.size() > 0)
1424 _info_manager->update_ise_list (total_appids);
1426 if (ret > 1 && _soft_keyboard_launched) { // If the previous appid of pkgid is the current IME, restart it with new appid.
1427 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1428 if (current_ime_appid.compare (appids.front ()) == 0) {
1429 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1430 _info_manager->hide_helper (current_ime_appid);
1431 _info_manager->stop_helper (current_ime_appid);
1432 LOGD ("Start IME(%s)", appids.back ().c_str ());
1433 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids.back ());
1434 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1435 _info_manager->start_helper (appids.back ());
1439 else if (ret == 2) { // In case IME package is just updated...
1440 _update_ime_info ();
1442 if (_soft_keyboard_launched) { // If package is the current IME, restart it.
1443 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1444 if (isf_db_select_appids_by_pkgid(package, appids)) {
1445 if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the current ISE package is updated, restart it.
1446 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1447 if (it->mode == TOOLBAR_HELPER_MODE && it->appid.compare(current_ime_appid) == 0) { // Make sure it's Helper ISE...
1448 LOGD ("Restart IME(%s)", current_ime_appid.c_str ());
1449 _info_manager->hide_helper (current_ime_appid);
1450 _info_manager->stop_helper (current_ime_appid);
1451 _info_manager->start_helper (current_ime_appid);
1459 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...
1460 if (isf_db_select_appids_by_pkgid(package, appids) == 1) {
1461 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1462 if (it->pkgid.compare(package) == 0) {
1463 g_pkgids_to_be_updated_and_installed.push_back (std::make_pair (it->pkgid, it->is_enabled));
1467 if (it == _ime_info.end ()) // Probably not going to happen.
1468 g_pkgids_to_be_updated_and_installed.push_back(std::make_pair (String(package), 0));
1470 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1471 if (_soft_keyboard_launched && std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the updated IME is the current ISE...
1472 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1473 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1474 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1475 _info_manager->hide_helper (current_ime_appid);
1476 _info_manager->stop_helper (current_ime_appid);
1477 _soft_keyboard_launched = false;
1478 g_updated_helper_pkgid = package;
1484 if (appids.size () > 0) // Probably appids size is 1.
1485 LOGD ("Delete IME(%s)", appids[0].c_str ());
1486 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1489 /* Let panel know that ise is deleted... */
1490 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1491 total_appids.push_back(it->appid);
1493 if (total_appids.size() > 0)
1494 _info_manager->update_ise_list (total_appids);
1498 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1503 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL) {
1504 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1505 LOGD ("type=%s package=%s event_type=INSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1507 ///////////////// UNINSTALL -> INSTALL and if the uninstalled IME is reinstalled /////////////////
1508 if (g_stopped_helper_pkgid.compare(package) == 0 && g_start_default_helper_timer) {
1509 LOGD ("Cancel timer to start the default IME");
1510 ecore_timer_del(g_start_default_helper_timer);
1511 g_start_default_helper_timer = NULL;
1512 g_stopped_helper_pkgid = "";
1514 ret = _isf_insert_ime_info_by_pkgid(package);
1516 /* Find appid by pkgid. There might be multiple appid, but assume Helper always has one appid.
1517 And appid can be changed, but pkgid won't be changed. */
1518 ret = isf_db_select_appids_by_pkgid(package, appids);
1519 if (ret == 1 && appids.size () == 1) {
1520 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1521 if (it3->first.compare(package) == 0) {
1523 isf_db_update_is_enabled_by_appid(appids[0].c_str (), (bool)it3->second);
1527 /* Let panel know that ise is added... */
1528 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1529 total_appids.push_back(it->appid);
1531 if (total_appids.size() > 0)
1532 _info_manager->update_ise_list (total_appids);
1534 LOGD ("Restart IME(%s)", appids[0].c_str ());
1535 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids[0]);
1536 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1537 _info_manager->start_helper (appids[0]);
1538 _soft_keyboard_launched = true;
1540 g_pkgids_to_be_uninstalled.erase (it3);
1546 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1550 /* Let panel know that ise is added... */
1551 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1552 total_appids.push_back(it->appid);
1554 if (total_appids.size() > 0)
1555 _info_manager->update_ise_list (total_appids);
1559 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1562 else { // If new package is installed...
1563 ret = _isf_insert_ime_info_by_pkgid(package); // If package is not IME, -1 would be returned.
1564 if (ret > 0) { // In case package is IME...
1565 ///////////////// INSTALL /////////////////
1568 /* Let panel know that ise is added... */
1569 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1570 total_appids.push_back(it->appid);
1572 if (total_appids.size() > 0)
1573 _info_manager->update_ise_list (total_appids);
1574 ///////////////// END /////////////////
1576 /* For example, the following happens if appid is changed in IME project and Run As again. The appid would be changed this time.
1577 Assuming only Helper (3rd party) might be installed after update or uninstall and there is one appid per each pkgid...*/
1579 ///////////////// UPDATE -> INSTALL /////////////////
1580 for (it3 = g_pkgids_to_be_updated_and_installed.begin (); it3 != g_pkgids_to_be_updated_and_installed.end (); it3++) {
1581 if (it3->first.compare(package) == 0) {
1583 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1584 if (it->pkgid.compare(package) == 0) {
1585 it->is_enabled = it3->second;
1586 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1591 g_pkgids_to_be_updated_and_installed.erase (it3);
1595 if (g_updated_helper_pkgid.compare(package) == 0) {
1596 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1597 if (it->mode == TOOLBAR_HELPER_MODE && it->pkgid.compare(package) == 0) {
1598 LOGD ("Start IME(%s)", it->appid.c_str ());
1599 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), it->appid);
1600 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1601 _info_manager->start_helper (it->appid);
1602 _soft_keyboard_launched = true;
1606 g_updated_helper_pkgid = "";
1609 ///////////////// END /////////////////
1611 ///////////////// UNINSTALL -> INSTALL /////////////////
1612 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1613 if (it3->first.compare(package) == 0) {
1615 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1616 if (it->pkgid.compare(package) == 0) {
1617 it->is_enabled = it3->second;
1618 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1623 g_pkgids_to_be_uninstalled.erase (it3);
1627 ///////////////// END /////////////////
1629 else if (ret == 0) {
1630 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.", ret);
1635 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL) {
1636 switch (event_state) {
1637 case PACKAGE_MANAGER_EVENT_STATE_STARTED:
1638 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=STARTED progress=%d error=%d", type, package, progress, error);
1640 // Need to check if there is "http://tizen.org/category/ime" category; it can be done by comparing pkgid with ime_info db.
1642 if (_ime_info.size() == 0)
1645 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1646 if (it->pkgid.compare(package) == 0 && it->is_preinstalled == 0) { // Ignore if it's preinstalled IME and IMEngine.
1653 // 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.
1654 LOGD ("%s for pkgid(\"%s\") is about to be deleted", it->appid.c_str (), package);
1655 g_pkgids_to_be_uninstalled.push_back(std::make_pair (String(package), it->is_enabled));
1657 if (_soft_keyboard_launched && isf_db_select_appids_by_pkgid(package, appids)) {
1658 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1659 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.
1660 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1661 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1662 LOGD ("Stop IME(%s)", current_ime_appid.c_str ());
1663 _info_manager->hide_helper (current_ime_appid);
1664 _info_manager->stop_helper (current_ime_appid);
1665 _soft_keyboard_launched = false;
1666 g_stopped_helper_pkgid = package;
1676 case PACKAGE_MANAGER_EVENT_STATE_COMPLETED:
1677 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1679 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1680 if (it3->first.compare(package) == 0) {
1681 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1685 if (g_stopped_helper_pkgid.compare(package) == 0) { // If the uninstalled ISE is the current ISE, start the initial helper ISE by timer.
1686 if (g_start_default_helper_timer)
1687 ecore_timer_del(g_start_default_helper_timer);
1688 LOGD ("Add timer to start the default IME");
1689 g_start_default_helper_timer = ecore_timer_add(3.0, _start_default_helper_timer, NULL);
1691 else { // Need to clean up g_pkgids_to_be_uninstalled info unless the same package is installed again; e.g., UNINSTALL -> INSTALL case.
1692 if (g_release_uninstalled_ime_info_timer)
1693 ecore_timer_del(g_release_uninstalled_ime_info_timer);
1694 LOGD ("Add timer to release uninstalled IME pkg info");
1695 g_release_uninstalled_ime_info_timer = ecore_timer_add(7.0, _release_uninstalled_pkginfo_timer, NULL);
1698 /* Let panel know that ise is deleted... */
1699 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1700 total_appids.push_back(it->appid);
1702 if (total_appids.size() > 0)
1703 _info_manager->update_ise_list (total_appids);
1710 case PACKAGE_MANAGER_EVENT_STATE_FAILED:
1711 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=FAILED progress=%d error=%d", type, package, progress, error);
1713 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1714 if (it3->first.compare(package) == 0) {
1715 // Update _ime_info for sure...
1718 if (g_stopped_helper_pkgid.compare(package) == 0) {
1719 ret = isf_db_select_appids_by_pkgid(package, appids);
1720 if (ret == 1 && appids.size () == 1) {
1721 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1722 if (it->appid.compare(appids[0]) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1723 LOGD ("Restart IME(%s)", appids[0].c_str ());
1724 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1725 _info_manager->start_helper (appids[0]);
1726 _soft_keyboard_launched = true;
1732 LOGW ("isf_db_select_appids_by_pkgid returned %d.", ret);
1734 g_stopped_helper_pkgid = "";
1737 g_pkgids_to_be_uninstalled.erase (it3);
1751 * @brief Set keyboard ISE.
1753 * @param uuid The keyboard ISE's uuid.
1755 * @return false if keyboard ISE change is failed, otherwise return true.
1757 static bool set_keyboard_ise (const String &uuid)
1759 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1761 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1763 if (TOOLBAR_HELPER_MODE == mode) {
1764 String pre_uuid = _info_manager->get_current_helper_uuid ();
1765 _info_manager->hide_helper (pre_uuid);
1766 _info_manager->stop_helper (pre_uuid);
1767 _soft_keyboard_launched = false;
1768 } else if (TOOLBAR_KEYBOARD_MODE == mode) {
1769 uint32 kbd_option = 0;
1770 String kbd_uuid, kbd_name;
1771 isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
1772 if (kbd_uuid == uuid)
1776 _info_manager->change_factory (uuid);
1778 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
1779 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
1785 * @brief Set helper ISE.
1787 * @param uuid The helper ISE's uuid.
1788 * @param launch_ise The flag for launching helper ISE.
1790 * @return false if helper ISE change is failed, otherwise return true.
1792 static bool set_helper_ise (const String &uuid, bool launch_ise)
1794 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1796 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1797 String pre_uuid = _info_manager->get_current_helper_uuid ();
1798 LOGD ("pre_appid=%s, appid=%s, launch_ise=%d, %d", pre_uuid.c_str(), uuid.c_str(), launch_ise, _soft_keyboard_launched);
1799 if (pre_uuid == uuid && _soft_keyboard_launched)
1802 if (TOOLBAR_HELPER_MODE == mode && pre_uuid.length () > 0 && _soft_keyboard_launched) {
1803 _info_manager->hide_helper (pre_uuid);
1804 _info_manager->stop_helper (pre_uuid);
1805 _soft_keyboard_launched = false;
1806 LOGD ("stop helper : %s", pre_uuid.c_str ());
1810 LOGD ("Start helper (%s)", uuid.c_str ());
1812 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1813 if (_info_manager->start_helper (uuid))
1814 _soft_keyboard_launched = true;
1816 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), uuid);
1821 #ifdef HAVE_PKGMGR_INFO
1822 int get_ime_app_list_cb (const pkgmgrinfo_appinfo_h handle, void *user_data)
1825 char *appid = NULL, *pkgid = NULL, *pkgtype = NULL, *exec = NULL, *label = NULL, *path = NULL;
1826 pkgmgrinfo_pkginfo_h pkginfo_handle = NULL;
1828 int *result = static_cast<int*>(user_data);
1830 if (result) /* in this case, need to check category */ {
1832 ret = pkgmgrinfo_appinfo_is_category_exist (handle, "http://tizen.org/category/ime", &exist);
1833 if (ret != PMINFO_R_OK || !exist) {
1839 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
1840 if (ret == PMINFO_R_OK)
1841 ime_db.appid = String (appid ? appid : "");
1843 LOGE ("pkgmgrinfo_appinfo_get_appid failed! error code=%d", ret);
1847 ime_db.iconpath = "";
1850 ret = pkgmgrinfo_appinfo_get_pkgid (handle, &pkgid);
1851 if (ret == PMINFO_R_OK)
1852 ime_db.pkgid = String (pkgid ? pkgid : "");
1854 LOGE ("pkgmgrinfo_appinfo_get_pkgid failed! error code=%d", ret);
1859 ret = pkgmgrinfo_appinfo_get_exec (handle, &exec);
1860 if (ret == PMINFO_R_OK)
1861 ime_db.exec = String (exec ? exec : "");
1863 LOGE ("pkgmgrinfo_appinfo_get_exec failed! error code=%d", ret);
1868 ret = pkgmgrinfo_appinfo_get_label (handle, &label);
1869 if (ret == PMINFO_R_OK)
1870 ime_db.label = String (label ? label : "");
1872 /* get pkgmgrinfo_pkginfo_h */
1873 /* Try to get in global packages */
1874 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &pkginfo_handle);
1875 if (ret != PMINFO_R_OK) {
1876 /* Try to get in user packages */
1877 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, getuid (), &pkginfo_handle);
1880 if (ret == PMINFO_R_OK && pkginfo_handle) {
1882 ret = pkgmgrinfo_pkginfo_get_type (pkginfo_handle, &pkgtype);
1884 if (ret == PMINFO_R_OK)
1885 ime_db.pkgtype = String (pkgtype ? pkgtype : "");
1887 ISF_SAVE_LOG ("pkgtype is not available!");
1888 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1893 pkgmgrinfo_pkginfo_get_root_path (pkginfo_handle, &path);
1896 ime_db.languages = "en";
1897 ime_db.display_lang = "";
1899 if (ime_db.pkgtype.compare ("rpm") == 0 && //1 Inhouse IMEngine ISE(IME)
1900 ime_db.exec.find ("scim-launcher") != String::npos) // Some IMEngine's pkgid doesn't have "ise-engine" prefix.
1902 ime_db.mode = TOOLBAR_KEYBOARD_MODE;
1904 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1905 + String (SCIM_PATH_DELIM_STRING) + String ("IMEngine");
1906 ime_db.module_name = ime_db.pkgid;
1907 ime_db.is_enabled = 1;
1908 ime_db.is_preinstalled = 1;
1909 ime_db.has_option = 0; // It doesn't matter. No option for IMEngine...
1912 ime_db.mode = TOOLBAR_HELPER_MODE;
1913 if (ime_db.pkgtype.compare ("rpm") == 0 && path) //1 Inhouse Helper ISE(IME)
1916 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1918 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART;
1920 ime_db.module_name = ime_db.pkgid;
1922 String module_path = String (path) + String ("/lib");
1923 String fullpath = module_path + String (SCIM_PATH_DELIM_STRING) + ime_db.module_name + String (".so");
1925 if (stat (fullpath.c_str (), &st) < 0) {
1926 /* Not found in lib directory of package's root path */
1927 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1928 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1931 ime_db.module_path = module_path;
1934 ime_db.is_enabled = 1;
1935 ime_db.is_preinstalled = 1;
1936 ime_db.has_option = 1; // Let's assume the inhouse IME always has an option menu.
1938 else if (ime_db.pkgtype.compare ("wgt") == 0) //1 Download Web IME
1940 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1941 | SCIM_HELPER_NEED_SPOT_LOCATION_INFO | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1942 ime_db.module_path = String (SCIM_MODULE_PATH) + String (SCIM_PATH_DELIM_STRING) + String (SCIM_BINARY_VERSION)
1943 + String (SCIM_PATH_DELIM_STRING) + String ("Helper");
1944 ime_db.module_name = String ("ise-web-helper-agent");
1945 if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1946 ime_db.is_enabled = 1;
1947 ime_db.is_preinstalled = 1;
1951 ime_db.is_enabled = 0;
1953 ime_db.is_enabled = 1;
1955 ime_db.is_preinstalled = 0;
1957 ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1959 else if (ime_db.pkgtype.compare ("tpk") == 0) //1 Download Native IME
1961 ime_db.options = SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO | SCIM_HELPER_AUTO_RESTART
1962 | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT | ISM_HELPER_WITHOUT_IMENGINE;
1964 ime_db.module_path = String (path) + String ("/lib");
1966 ime_db.module_path = String (tzplatform_getenv(TZ_SYS_RW_APP)) + ime_db.pkgid + String ("/lib");
1967 ime_db.module_name = String ("lib") + ime_db.exec.substr (ime_db.exec.find_last_of (SCIM_PATH_DELIM) + 1);
1968 if (ime_db.exec.compare (0, 5, "/usr/") == 0) {
1969 ime_db.is_enabled = 1;
1970 ime_db.is_preinstalled = 1;
1974 ime_db.is_enabled = 0;
1976 ime_db.is_enabled = 1;
1978 ime_db.is_preinstalled = 0;
1980 ime_db.has_option = -1; // At this point, we can't know IME has an option (setting) or not; -1 means unknown.
1983 LOGE ("Unsupported pkgtype(%s)", ime_db.pkgtype.c_str ());
1984 if (pkginfo_handle) {
1985 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1986 pkginfo_handle = NULL;
1992 _ime_info.push_back(ime_db);
1994 if (pkginfo_handle) {
1995 pkgmgrinfo_pkginfo_destroy_pkginfo (pkginfo_handle);
1996 pkginfo_handle = NULL;
2004 * @brief Set active ISE.
2006 * @param uuid The ISE's uuid.
2007 * @param launch_ise The flag for launching helper ISE.
2009 * @return false if ISE change is failed, otherwise return true.
2011 static bool set_active_ise (const String &uuid, bool launch_ise)
2013 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2014 LOGD ("set ISE (%s) %d", uuid.c_str(), launch_ise);
2016 if (uuid.length () <= 0)
2019 bool ise_changed = false, valid = false;
2021 int ime_num = -1; /* If we failed retrieving the number of IMEs installed, assume we need to clear IME related settings */
2022 pkgmgrinfo_appinfo_filter_h handle;
2023 int ret = pkgmgrinfo_appinfo_filter_create(&handle);
2024 if (ret == PMINFO_R_OK) {
2025 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
2026 if (ret == PMINFO_R_OK) {
2027 ret = pkgmgrinfo_appinfo_filter_count(handle, &ime_num);
2028 if (ret != PMINFO_R_OK) {
2029 LOGW("pkgmgrinfo_appinfo_filter_count failed(%d)", ret);
2032 pkgmgrinfo_appinfo_filter_destroy (handle);
2035 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
2038 /* If the ime_num and _ime_info.size() are different, it is likely that the isf-panel-efl was
2039 terminated abnormally while processing package manager's install / uninstall events */
2040 LOGD("Checking whether db file needs to be re-created : %d %d", ime_num, _ime_info.size());
2041 if (ime_num != (int)_ime_info.size()) {
2043 isf_db_delete_ime_info();
2044 isf_pkg_reload_ime_info_db();
2045 isf_pkg_select_all_ime_info_db(_ime_info);
2048 if (_ime_info.size () == 0) {
2049 #ifdef HAVE_PKGMGR_INFO
2050 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
2051 if (ret == PMINFO_R_OK) {
2052 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime");
2053 if (ret == PMINFO_R_OK)
2054 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
2056 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
2058 pkgmgrinfo_appinfo_filter_destroy (handle);
2061 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
2066 for (unsigned int i = 0; i < _ime_info.size (); i++) {
2067 if (!uuid.compare (_ime_info[i].appid)) {
2068 if (TOOLBAR_KEYBOARD_MODE == _ime_info[i].mode)
2069 ise_changed = set_keyboard_ise (_ime_info[i].appid);
2070 else if (TOOLBAR_HELPER_MODE == _ime_info[i].mode) {
2071 if (_ime_info[i].is_enabled) {
2072 if (_ime_info[i].exec == String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
2073 /* If IME so is deleted somehow, main() in scim_helper_launcher.cpp will return -1.
2074 Checking HelperModule validity seems necessary here. */
2075 HelperModule helper_module (_ime_info[i].module_name);
2076 if (helper_module.valid ())
2078 helper_module.unload ();
2081 /* executable type */
2086 ise_changed = set_helper_ise (_ime_info[i].appid, launch_ise);
2088 LOGW ("Helper ISE(appid=\"%s\",module_name=\"%s\") is not valid.", _ime_info[i].appid.c_str (), _ime_info[i].module_name.c_str ());
2091 LOGW ("Helper ISE(appid=\"%s\") is not enabled.", _ime_info[i].appid.c_str ());
2094 _info_manager->set_current_toolbar_mode (_ime_info[i].mode);
2096 /* From Tizen 4.0 all the ISEs need to handle H/W keyboard events */
2097 _ime_info[i].options |= ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
2098 _info_manager->set_current_helper_option (_ime_info[i].options);
2099 _info_manager->set_current_ise_name (_ime_info[i].label);
2102 _ise_state = WINDOW_STATE_HIDE;
2103 _candidate_mode = SOFT_CANDIDATE_WINDOW;
2104 _candidate_port_line = ONE_LINE_CANDIDATE;
2105 _soft_candidate_width = 0;
2106 _soft_candidate_height = 0;
2107 #if ISF_BUILD_CANDIDATE_UI
2108 if (_candidate_window)
2109 ui_create_candidate_window ();
2112 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _ime_info[i].appid);
2113 scim_global_config_flush ();
2119 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2123 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2130 LOGW ("Failed to launch IME (%s), %d", uuid.c_str (), _ime_info.size());
2136 * @brief Set temporary ISE.
2138 * @param uuid The ISE's uuid.
2140 * @return false if ISE change is failed, otherwise return true.
2142 static bool set_temporary_ise (const String &uuid)
2144 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2145 LOGD ("set temporary ISE (%s)", uuid.c_str ());
2147 if (uuid.length () <= 0)
2150 if (_ime_info.size () == 0) {
2151 #ifdef HAVE_PKGMGR_INFO
2152 pkgmgrinfo_appinfo_filter_h handle;
2153 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
2154 if (ret == PMINFO_R_OK) {
2155 /* Add the package info for the IME that matches with our uuid only */
2156 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_ID, uuid.c_str ());
2157 if (ret == PMINFO_R_OK)
2158 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, get_ime_app_list_cb, NULL);
2160 LOGE ("pkgmgrinfo_appinfo_filter_add_string failed(%d)", ret);
2162 pkgmgrinfo_appinfo_filter_destroy (handle);
2164 LOGE ("pkgmgrinfo_appinfo_filter_create failed(%d)", ret);
2169 #ifdef HAVE_PKGMGR_INFO
2170 bool ise_changed = false;
2172 pkgmgrinfo_appinfo_h handle = NULL;
2173 int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
2174 if (ret != PMINFO_R_OK) {
2175 LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
2181 ret = pkgmgrinfo_appinfo_get_label (handle, &label);
2182 if (ret != PMINFO_R_OK) {
2183 LOGW ("Could not get label for appid '%s'", uuid.c_str ());
2184 pkgmgrinfo_appinfo_destroy_appinfo (handle);
2188 ise_changed = set_helper_ise (uuid, true);
2191 _info_manager->set_current_toolbar_mode (TOOLBAR_HELPER_MODE);
2193 _info_manager->set_current_helper_option (SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO |
2194 SCIM_HELPER_AUTO_RESTART | ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT);
2196 _info_manager->set_current_helper_option (SCIM_HELPER_STAND_ALONE | SCIM_HELPER_NEED_SCREEN_INFO |
2197 SCIM_HELPER_AUTO_RESTART);
2198 String label_string = label;
2199 _info_manager->set_current_ise_name (label_string);
2202 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
2205 LOGW ("Failed to launch IME (%s)", uuid.c_str ());
2208 pkgmgrinfo_appinfo_destroy_appinfo (handle);
2218 * @brief Load ISF configuration and ISEs information.
2220 static void load_config (void)
2222 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2224 /* Read configurations. */
2225 if (!_config.null ()) {
2226 bool shared_ise = _config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), false);
2227 _info_manager->set_should_shared_ise (shared_ise);
2229 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
2230 _auto_destroy_ise = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_ENABLE_AUTO_DESTROY_ISE), _auto_destroy_ise);
2232 isf_load_ise_information (ALL_ISE, _config);
2236 * @brief Reload config callback function for ISF panel.
2238 * @param config The config pointer.
2240 static void config_reload_cb (const ConfigPointer &config)
2242 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2243 /* load_config (); */
2244 _info_manager->reload_config ();
2247 #if ISF_BUILD_CANDIDATE_UI
2248 //////////////////////////////////////////////////////////////////////
2249 // Start of Candidate Functions
2250 //////////////////////////////////////////////////////////////////////
2252 * @brief Get candidate window valid height for autoscroll.
2254 * @return The valid height.
2256 static int ui_candidate_get_valid_height (void)
2258 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2263 if (_candidate_window) {
2264 if (_candidate_state == WINDOW_STATE_SHOW)
2265 angle = _candidate_angle;
2267 angle = efl_get_app_window_angle ();
2269 if (_aux_area_visible && _candidate_area_1_visible) {
2270 if (angle == 90 || angle == 270)
2271 height = _candidate_land_height_min_2;
2273 height = _candidate_port_height_min_2;
2275 if (angle == 90 || angle == 270)
2276 height = _candidate_land_height_min;
2278 height = _candidate_port_height_min;
2285 * @brief Resize candidate window size.
2287 * @param new_width New width for candidate window.
2288 * @param new_height New height for candidate window.
2290 static void ui_candidate_window_resize (int new_width, int new_height)
2292 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " width:" << new_width << " height:" << new_height << "\n";
2294 if (!_candidate_window)
2299 LOGD ("%s (w: %d, h: %d)", __func__, new_width, new_height);
2300 evas_object_resize (_aux_line, new_width, 2);
2301 _candidate_width = new_width;
2302 _candidate_height = new_height;
2303 if (_candidate_state == WINDOW_STATE_SHOW)
2304 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2306 if (_candidate_state == WINDOW_STATE_SHOW && _candidate_mode == FIXED_CANDIDATE_WINDOW) {
2307 height = ui_candidate_get_valid_height ();
2308 if ((_ise_width == 0 && _ise_height == 0) ||
2309 (_ise_height > 0 && _candidate_valid_height != height) ||
2310 (_ise_height > 0 && (_candidate_height - height) > _ise_height) ||
2311 ((_candidate_angle == 90 || _candidate_angle == 270) && (_ise_width < _screen_height)) ||
2312 ((_candidate_angle == 0 || _candidate_angle == 180) && (_ise_width > _screen_width ))) {
2314 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2316 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2320 /* Get height for portrait and landscape */
2321 int port_width = _candidate_port_width;
2322 int port_height = _candidate_port_height_min;
2323 int land_width = _candidate_land_width;
2324 int land_height = _candidate_land_height_min;
2325 if (_candidate_angle == 90 || _candidate_angle == 270) {
2326 land_height = new_height;
2327 if (land_height == _candidate_land_height_min_2) {
2328 port_height = _candidate_port_height_min_2;
2329 } else if (land_height == _candidate_land_height_max) {
2330 port_height = _candidate_port_height_max;
2331 } else if (land_height == _candidate_land_height_max_2) {
2332 port_height = _candidate_port_height_max_2;
2335 port_height = new_height;
2336 if (port_height == _candidate_port_height_min_2) {
2337 land_height = _candidate_land_height_min_2;
2338 } else if (port_height == _candidate_port_height_max) {
2339 land_height = _candidate_land_height_max;
2340 } else if (port_height == _candidate_port_height_max_2) {
2341 land_height = _candidate_land_height_max_2;
2345 LOGD ("window_rotation_geometry_set (_candidate_window), port (%d, %d), land (%d, %d)",
2346 port_width, port_height, land_width, land_height);
2350 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2351 0, 0, 0, port_width, port_height);
2352 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2353 90, 0, 0, land_height, land_width);
2354 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2355 180, 0, 0, port_width, port_height);
2356 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2357 270, 0, 0, land_height, land_width);
2360 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2361 0, 0, 0, port_width, port_height);
2362 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2363 90, 0, 0, land_height, land_width);
2364 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2365 180, 0, 0, port_width, port_height);
2366 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
2367 270, 0, 0, land_height, land_width);
2372 * @brief This function will show/hide widgets of candidate window,
2373 * and resize candidate window size according to aux_area/candidate_area.
2375 static void ui_candidate_window_adjust (void)
2377 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2378 if (!_candidate_window)
2381 int x = 0, y = 0, width = 0, height = 0;
2383 /* Get candidate window size */
2386 if (_candidate_angle == 90 || _candidate_angle == 270) {
2387 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2388 &x, &y, &height, &width);
2390 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2391 &x, &y, &width, &height);
2395 if (_candidate_angle == 90 || _candidate_angle == 270)
2396 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &height, &width);
2398 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
2401 if (_aux_area_visible && _candidate_area_2_visible) {
2402 evas_object_show (_aux_line);
2403 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);
2404 if (_candidate_angle == 90 || _candidate_angle == 270) {
2405 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2406 _ise_height > _candidate_land_height_max_2 - _candidate_land_height_min_2)
2407 ui_candidate_window_resize (width, _candidate_land_height_min_2 + _ise_height);
2409 ui_candidate_window_resize (width, _candidate_land_height_max_2);
2410 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2411 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min_2);
2412 evas_object_move (_scroller_bg, 0, _candidate_land_height_min_2);
2413 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2415 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2416 _ise_height > _candidate_port_height_max_2 - _candidate_port_height_min_2)
2417 ui_candidate_window_resize (width, _candidate_port_height_min_2 + _ise_height);
2419 ui_candidate_window_resize (width, _candidate_port_height_max_2);
2420 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2421 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min_2);
2422 evas_object_move (_scroller_bg, 0, _candidate_port_height_min_2);
2423 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2425 } else if (_aux_area_visible && _candidate_area_1_visible) {
2426 evas_object_show (_aux_line);
2427 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);
2428 if (_candidate_angle == 90 || _candidate_angle == 270) {
2429 ui_candidate_window_resize (width, _candidate_land_height_min_2);
2430 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2431 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2433 ui_candidate_window_resize (width, _candidate_port_height_min_2);
2434 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2435 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2437 } else if (_aux_area_visible) {
2438 evas_object_hide (_aux_line);
2439 ui_candidate_window_resize (width, _aux_height + 2);
2440 evas_object_resize (_candidate_bg, width, _aux_height + 2);
2441 } else if (_candidate_area_2_visible) {
2442 evas_object_hide (_aux_line);
2443 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2444 if (_candidate_angle == 90 || _candidate_angle == 270) {
2445 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2446 _ise_height > _candidate_land_height_max - _candidate_land_height_min)
2447 ui_candidate_window_resize (width, _candidate_land_height_min + _ise_height);
2449 ui_candidate_window_resize (width, _candidate_land_height_max);
2450 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3]);
2451 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min);
2452 evas_object_move (_scroller_bg, 0, _candidate_land_height_min);
2453 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2455 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2456 _ise_height > _candidate_port_height_max - _candidate_port_height_min)
2457 ui_candidate_window_resize (width, _candidate_port_height_min + _ise_height);
2459 ui_candidate_window_resize (width, _candidate_port_height_max);
2460 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
2461 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min);
2462 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
2463 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2466 evas_object_hide (_aux_line);
2467 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2468 if (_candidate_angle == 90 || _candidate_angle == 270) {
2469 ui_candidate_window_resize (width, _candidate_land_height_min);
2470 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3]);
2471 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2473 ui_candidate_window_resize (width, _candidate_port_height_min);
2474 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
2475 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2481 * @brief Rotate candidate window.
2483 * @param angle The angle of candidate window.
2485 static void ui_candidate_window_rotate (int angle)
2487 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2488 if (!_candidate_window)
2491 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
2493 if (angle == 90 || angle == 270) {
2494 _candidate_scroll_width = _candidate_scroll_width_max;
2495 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
2496 evas_object_resize (_aux_area, _aux_land_width, _aux_height);
2497 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_max, _item_min_height);
2498 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_min);
2499 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_min + 6);
2501 _candidate_scroll_width = _candidate_scroll_width_min;
2502 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
2503 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
2504 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
2505 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_max);
2506 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
2509 evas_object_hide (_candidate_area_2);
2510 _candidate_area_2_visible = false;
2511 ui_candidate_window_adjust ();
2512 if (_candidate_area_1_visible) {
2513 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2514 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
2515 ui_tts_focus_rect_hide ();
2521 * @brief This function is used to judge whether candidate window should be hidden.
2523 * @return true if candidate window should be hidden, otherwise return false.
2525 static bool ui_candidate_can_be_hide (void)
2527 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2529 if (_aux_area_visible || _candidate_area_1_visible || _candidate_area_2_visible)
2536 * @brief Delete check candidate window size timer.
2540 static void ui_candidate_delete_check_size_timer (void)
2542 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2544 if (_check_size_timer != NULL) {
2545 ecore_timer_del (_check_size_timer);
2546 _check_size_timer = NULL;
2551 * @brief Callback function for check candidate window size timer.
2553 * @param data Data to pass when it is called.
2555 * @return ECORE_CALLBACK_CANCEL
2557 static Eina_Bool ui_candidate_check_size_timeout (void *data)
2559 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2561 ui_candidate_delete_check_size_timer ();
2562 ui_candidate_window_resize (_candidate_width, _candidate_height);
2563 ui_settle_candidate_window ();
2564 return ECORE_CALLBACK_CANCEL;
2568 * @brief Delete longpress timer.
2572 static void ui_candidate_delete_longpress_timer (void)
2574 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2576 if (_longpress_timer != NULL) {
2577 ecore_timer_del (_longpress_timer);
2578 _longpress_timer = NULL;
2583 * @brief Callback function for candidate longpress timer.
2585 * @param data Data to pass when it is called.
2587 * @return ECORE_CALLBACK_CANCEL
2589 static Eina_Bool ui_candidate_longpress_timeout (void *data)
2591 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2593 int index = (int)GPOINTER_TO_INT (data);
2594 ui_candidate_delete_longpress_timer ();
2596 _info_manager->send_longpress_event (_click_object, index);
2597 return ECORE_CALLBACK_CANCEL;
2601 * @brief Delete destroy timer.
2605 static void ui_candidate_delete_destroy_timer (void)
2607 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2609 if (_destroy_timer != NULL) {
2610 ecore_timer_del (_destroy_timer);
2611 _destroy_timer = NULL;
2616 * @brief Callback function for destroy timer.
2618 * @param data Data to pass when it is called.
2620 * @return ECORE_CALLBACK_CANCEL
2622 static Eina_Bool ui_candidate_destroy_timeout (void *data)
2624 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2626 ui_candidate_delete_destroy_timer ();
2627 ui_destroy_candidate_window ();
2628 return ECORE_CALLBACK_CANCEL;
2630 #endif /* CANDIDATE */
2634 * @brief Callback function for off_prepare_done.
2636 * @param data Data to pass when it is called.
2638 * @return ECORE_CALLBACK_CANCEL
2640 static Eina_Bool off_prepare_done_timeout (void *data)
2642 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2644 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
2645 // WILL_HIDE_REQUEST_DONE Ack to WM
2646 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
2647 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
2648 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
2649 root_window, _control_window);
2650 _off_prepare_done_timer = NULL;
2652 return ECORE_CALLBACK_CANCEL;
2654 #endif /* HAVE_ECOREX */
2656 #if ISF_BUILD_CANDIDATE_UI
2658 * @brief Delete candidate hide timer.
2662 static void delete_candidate_hide_timer (void)
2664 LOGD ("deleting candidate_hide_timer");
2665 if (_candidate_hide_timer) {
2666 ecore_timer_del (_candidate_hide_timer);
2667 _candidate_hide_timer = NULL;
2671 static void candidate_window_hide (void)
2673 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2675 delete_candidate_hide_timer ();
2676 _candidate_state = WINDOW_STATE_HIDE;
2678 LOGD ("evas_object_hide (_candidate_window, %p)", elm_win_xwindow_get (_candidate_window));
2680 if (_candidate_window) {
2681 /* There are cases that when there are rapid ISE_HIDE and ISE_SHOW requests,
2682 candidate window should be displayed but STATE_OFF for the first ISE_HIDE
2683 calls this function, so when the candidate window is shown by the following
2684 STATE_ON message, a blank area is displayed in candidate window -
2685 so we let the _candidate_area_1 as the default area that would be displayed */
2686 //evas_object_hide (_candidate_area_1);
2687 //evas_object_hide (_more_btn);
2688 _candidate_area_1_visible = false;
2690 evas_object_hide (_candidate_window);
2691 SCIM_DEBUG_MAIN (3) << " Hide candidate window\n";
2696 * @brief Callback function for candidate hide timer
2698 * @param data Data to pass when it is called.
2700 * @return ECORE_CALLBACK_CANCEL
2702 static Eina_Bool candidate_hide_timer (void *data)
2704 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2706 LOGD ("calling candidate_window_hide ()");
2707 candidate_window_hide ();
2709 return ECORE_CALLBACK_CANCEL;
2714 * @brief Delete candidate show handler.
2718 static void delete_candidate_show_handler (void)
2720 if (_candidate_show_handler) {
2721 ecore_event_handler_del (_candidate_show_handler);
2722 _candidate_show_handler = NULL;
2727 * @brief Callback function for window show completion event
2729 * @param data Data to pass when it is called.
2731 * @return ECORE_CALLBACK_CANCEL
2734 static Eina_Bool x_event_window_show_cb (void *data, int ev_type, void *event)
2736 delete_candidate_show_handler ();
2738 Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
2739 if (_candidate_state == WINDOW_STATE_WILL_SHOW) {
2740 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2741 LOGD ("Candidate window show callback");
2743 /* If our candidate window is in WILL_SHOW state and this show callback was called,
2744 now we are finally displayed on to the screen */
2745 _candidate_state = WINDOW_STATE_SHOW;
2747 /* Update the geometry information for auto scrolling */
2748 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2749 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2750 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2752 /* And the state event */
2753 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2755 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2756 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2757 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2758 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2763 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2764 LOGD ("Candidate window show callback, but _candidate_state is %d", _candidate_state);
2768 return ECORE_CALLBACK_CANCEL;
2770 #endif /* HAVE_ECOREX */
2773 * @brief Show candidate window.
2775 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2777 static void ui_candidate_show (bool bSetVirtualKbd)
2779 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2781 delete_candidate_hide_timer ();
2783 if (!_candidate_window) return;
2784 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
2787 /* FIXME : SHOULD UNIFY THE METHOD FOR CHECKING THE HW KEYBOARD EXISTENCE */
2788 /* If the ISE is not visible currently, wait for the ISE to be opened and then show our candidate window */
2789 _candidate_show_requested = true;
2790 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) && (_ise_state != WINDOW_STATE_SHOW)) {
2791 LOGD ("setting _show_candidate_requested to TRUE");
2795 /* If the ISE angle is valid, respect the value to make sure
2796 the candidate window always have the same angle with ISE */
2797 if (_ise_angle != -1) {
2798 _candidate_angle = _ise_angle;
2800 ui_candidate_window_rotate (_candidate_angle);
2802 /* If the candidate window was about to hide, turn it back to SHOW state now */
2803 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
2804 _candidate_state = WINDOW_STATE_SHOW;
2807 /* Change to WILL_SHOW state only when we are not currently in SHOW state */
2808 if (_candidate_state != WINDOW_STATE_SHOW) {
2809 _candidate_state = WINDOW_STATE_WILL_SHOW;
2813 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2814 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
2815 // Unset conformant area
2816 Ecore_X_Window current_app_window = efl_get_app_window ();
2817 if (_app_window != current_app_window) {
2818 struct rectinfo info = {0, 0, 0, 0};
2819 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
2820 set_keyboard_geometry_atom_info (_app_window, info);
2821 LOGD ("Conformant reset for window %x", _app_window);
2822 _app_window = current_app_window;
2826 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2827 if (bSetVirtualKbd) {
2828 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2831 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
2834 ui_candidate_delete_check_size_timer ();
2835 _check_size_timer = ecore_timer_add (0.02, ui_candidate_check_size_timeout, NULL);
2837 SCIM_DEBUG_MAIN (3) << " Show candidate window\n";
2839 if (_ise_state == WINDOW_STATE_SHOW) {
2840 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
2841 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
2843 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
2844 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
2847 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2848 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2849 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2850 LOGD ("sending ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW");
2851 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
2855 if (_candidate_state != WINDOW_STATE_SHOW) {
2857 if (_candidate_show_handler) {
2858 LOGD ("Was still waiting for CANDIDATE_WINDOW_SHOW....");
2860 delete_candidate_show_handler ();
2861 LOGD ("Registering ECORE_X_EVENT_WINDOW_SHOW event, %d", _candidate_state);
2862 _candidate_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_window_show_cb, NULL);
2866 LOGD ("The candidate window was already in SHOW state, update geometry information");
2867 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2868 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2870 /* And the state event */
2871 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2873 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2874 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2875 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2876 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2881 evas_object_show (_candidate_window);
2885 * @brief Hide candidate window.
2887 * @param bForce The flag to hide candidate window by force.
2888 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2890 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd, bool will_hide)
2892 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " bForce:" << bForce << " bSetVirtualKbd:" << bSetVirtualKbd << " will_hide:" << will_hide << "...\n";
2894 if (!_candidate_window)
2898 if (_candidate_area_2 && _candidate_area_2_visible) {
2899 evas_object_hide (_candidate_area_2);
2900 _candidate_area_2_visible = false;
2901 evas_object_hide (_scroller_bg);
2902 evas_object_hide (_close_btn);
2903 _info_manager->candidate_more_window_hide ();
2904 ui_candidate_window_adjust ();
2908 if (bForce || ui_candidate_can_be_hide ()) {
2910 LOGD ("candidate_state = WILL_HIDE");
2911 _candidate_state = WINDOW_STATE_WILL_HIDE;
2913 delete_candidate_hide_timer ();
2914 _candidate_hide_timer = ecore_timer_add (2.0, candidate_hide_timer, NULL);
2917 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2918 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2919 /* FIXME : should check if bSetVirtualKbd flag is really needed in this case */
2921 if (_ise_state == WINDOW_STATE_SHOW) {
2922 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2924 if (bSetVirtualKbd) {
2925 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2929 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2930 _info_manager->update_input_panel_event
2931 ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_HIDE);
2935 /* Update the new keyboard geometry first, and then send the candidate hide event */
2936 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_HIDE);
2939 /* If we are not in will_hide state, hide the candidate window immediately */
2940 candidate_window_hide ();
2942 if (_preedit_window)
2943 evas_object_hide (_preedit_window);
2949 * @brief Callback function for more button.
2951 * @param data Data to pass when it is called.
2952 * @param e The evas for current event.
2953 * @param button The evas object for current event.
2954 * @param event_info The information for current event.
2956 static void ui_candidate_window_more_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2958 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2960 _info_manager->candidate_more_window_show ();
2962 if (candidate_expanded == false) {
2963 candidate_expanded = true;
2964 int number = SCIM_LOOKUP_TABLE_MAX_PAGESIZE;
2965 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
2966 if (_candidate_0 [i] == NULL) {
2971 if (g_isf_candidate_table.get_current_page_size () != number)
2972 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2975 if (_candidate_angle == 180) {
2976 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2977 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2978 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
2979 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2981 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2982 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2983 * for avoiding this situation.
2985 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2986 ecore_evas_move_resize (ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2987 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
2988 ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2991 evas_object_show (_candidate_area_2);
2992 _candidate_area_2_visible = true;
2993 evas_object_show (_scroller_bg);
2994 evas_object_hide (_more_btn);
2995 evas_object_show (_close_btn);
2997 ui_candidate_window_adjust ();
2998 ui_settle_candidate_window ();
3003 * @brief Callback function for close button.
3005 * @param data Data to pass when it is called.
3006 * @param e The evas for current event.
3007 * @param button The evas object for current event.
3008 * @param event_info The information for current event.
3010 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3012 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3014 if (_candidate_area_2 == NULL || !_candidate_area_2_visible)
3017 _info_manager->candidate_more_window_hide ();
3019 evas_object_hide (_candidate_area_2);
3020 _candidate_area_2_visible = false;
3021 evas_object_hide (_scroller_bg);
3022 evas_object_hide (_close_btn);
3024 candidate_expanded = false;
3025 evas_object_show (_candidate_area_1);
3026 _candidate_area_1_visible = true;
3027 evas_object_show (_more_btn);
3029 elm_scroller_region_show (_candidate_area_2, 0, 0, _candidate_scroll_width, 100);
3030 if (_candidate_angle == 180) {
3031 Ecore_Evas *ee= ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
3032 ecore_evas_move_resize (ee, 0, 0, 0, 0);
3033 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)", ee, 0, 0, 0, 0);
3034 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
3036 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
3037 * candidates, but it will flash or locate in a wrong position, this code just a workaround
3038 * for avoiding this situation.
3040 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
3041 ecore_evas_move_resize (ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
3042 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)",
3043 ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
3046 ui_candidate_window_adjust ();
3047 ui_settle_candidate_window ();
3052 * @brief Callback function for mouse button press.
3054 * @param data Data to pass when it is called.
3055 * @param e The evas for current event.
3056 * @param button The evas object for current event.
3057 * @param event_info The information for current event.
3059 static void ui_mouse_button_pressed_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3061 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3063 _click_object = GPOINTER_TO_INT (data) & 0xFF;
3066 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
3069 _click_down_pos [0] = ev->canvas.x;
3070 _click_down_pos [1] = ev->canvas.y;
3072 if (_click_object == ISF_EFL_CANDIDATE_0 || _click_object == ISF_EFL_CANDIDATE_ITEMS) {
3073 int index = (int)GPOINTER_TO_INT (data) >> 8;
3075 #ifdef HAVE_FEEDBACK
3076 if (feedback_initialized) {
3077 int feedback_result = 0;
3078 bool sound_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_SOUND_FEEDBACK, false);
3080 if (sound_feedback) {
3081 feedback_result = feedback_play_type (FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_SIP);
3083 if (FEEDBACK_ERROR_NONE == feedback_result)
3084 LOGD ("Sound play successful");
3086 LOGW ("Cannot play feedback sound : %d", feedback_result);
3089 bool vibrate_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_VIBRATION_FEEDBACK, false);
3091 if (vibrate_feedback) {
3092 feedback_result = feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
3094 if (FEEDBACK_ERROR_NONE == feedback_result)
3095 LOGD ("Vibration play successful");
3097 LOGW ("Cannot play feedback vibration : %d", feedback_result);
3102 ui_candidate_delete_longpress_timer ();
3103 _longpress_timer = ecore_timer_add (1.0, ui_candidate_longpress_timeout, (void *)index);
3108 * @brief Callback function for mouse button release.
3110 * @param data Data to pass when it is called.
3111 * @param e The evas for current event.
3112 * @param button The evas object for current event.
3113 * @param event_info The information for current event.
3115 static void ui_mouse_button_released_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3117 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " index:" << GPOINTER_TO_INT (data) << "...\n";
3119 ui_candidate_delete_longpress_timer ();
3121 int index = GPOINTER_TO_INT (data);
3122 if (_click_object == ISF_EFL_AUX && _is_click) {
3124 const char *buf = edje_object_part_state_get (button, "aux", &ret);
3125 if (strcmp ("selected", buf)) {
3126 for (unsigned int i = 0; i < _aux_items.size (); i++) {
3127 buf = edje_object_part_state_get (_aux_items [i], "aux", &ret);
3128 if (!strcmp ("selected", buf))
3129 edje_object_signal_emit (_aux_items [i], "aux,state,unselected", "aux");
3131 edje_object_signal_emit (button, "aux,state,selected", "aux");
3132 _info_manager->select_aux (index);
3134 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
3135 edje_object_color_class_get (_aux_items [index], "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
3136 // Normal item is clicked
3137 if (!(r == 62 && g == 207 && b == 255)) {
3138 for (unsigned int i = 0; i < _aux_items.size (); i++) {
3139 edje_object_color_class_set (_aux_items [i], "text_color", 249, 249, 249, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3141 edje_object_color_class_set (_aux_items [index], "text_color", 62, 207, 255, 255, r2, g2, b2, a2, r3, g3, b3, a3);
3142 _info_manager->select_aux (index);
3144 } else if (_click_object == ISF_EFL_CANDIDATE_0 && _is_click) {
3145 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3146 _info_manager->select_candidate (index);
3147 } else if (_click_object == ISF_EFL_CANDIDATE_ITEMS && _is_click) {
3148 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
3149 _info_manager->select_candidate (index);
3154 * @brief Callback function for mouse move.
3156 * @param data Data to pass when it is called.
3157 * @param e The evas for current event.
3158 * @param button The evas object for current event.
3159 * @param event_info The information for current event.
3161 static void ui_mouse_moved_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
3163 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3165 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
3168 _click_up_pos [0] = ev->canvas.x;
3169 _click_up_pos [1] = ev->canvas.y;
3171 if (abs (_click_up_pos [0] - _click_down_pos [0]) >= (int)(15 * _height_rate) ||
3172 abs (_click_up_pos [1] - _click_down_pos [1]) >= (int)(15 * _height_rate)) {
3174 ui_candidate_delete_longpress_timer ();
3180 * @brief Open TTS device.
3182 * @return false if open is failed, otherwise return true.
3184 static bool ui_open_tts (void)
3186 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3188 int r = tts_create (&_tts);
3189 if (TTS_ERROR_NONE != r) {
3190 LOGW ("tts_create FAILED : result (%d)", r);
3195 r = tts_set_mode (_tts, TTS_MODE_SCREEN_READER);
3196 if (TTS_ERROR_NONE != r) {
3197 LOGW ("tts_set_mode FAILED : result (%d)", r);
3200 tts_state_e current_state;
3201 r = tts_get_state (_tts, ¤t_state);
3202 if (TTS_ERROR_NONE != r) {
3203 LOGW ("tts_get_state FAILED : result (%d)", r);
3206 if (TTS_STATE_CREATED == current_state) {
3207 r = tts_prepare (_tts);
3208 if (TTS_ERROR_NONE != r) {
3209 LOGW ("tts_prepare FAILED : ret (%d)", r);
3216 * @brief Close TTS device.
3218 static void ui_close_tts (void)
3220 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3223 int r = tts_unprepare (_tts);
3224 if (TTS_ERROR_NONE != r) {
3225 LOGW ("tts_unprepare FAILED : result (%d)", r);
3228 r = tts_destroy (_tts);
3229 if (TTS_ERROR_NONE != r) {
3230 LOGW ("tts_destroy FAILED : result (%d)", r);
3236 * @brief Play string by TTS.
3238 * @param str The string for playing.
3240 static void ui_play_tts (const char* str)
3242 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << "\n";
3247 if (!ui_open_tts ())
3253 tts_state_e current_state;
3255 r = tts_get_state (_tts, ¤t_state);
3256 if (TTS_ERROR_NONE != r) {
3257 LOGW ("Fail to get state from TTS : ret (%d)", r);
3260 if (TTS_STATE_PLAYING == current_state) {
3261 r = tts_stop (_tts);
3262 if (TTS_ERROR_NONE != r) {
3263 LOGW ("Fail to stop TTS : ret (%d)", r);
3267 /* Get ISE language */
3268 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
3269 String language = String ("en_US");
3270 if (default_uuid.length () > 0) {
3271 language = _ime_info[get_ise_index (default_uuid)].languages;
3272 if (language.length () > 0) {
3273 std::vector<String> ise_langs;
3274 scim_split_string_list (ise_langs, language);
3275 language = ise_langs[0];
3278 LOGD ("TTS language:%s, str:%s", language.c_str (), str);
3280 r = tts_add_text (_tts, str, language.c_str (), TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &utt_id);
3281 if (TTS_ERROR_NONE == r) {
3282 r = tts_play (_tts);
3283 if (TTS_ERROR_NONE != r) {
3284 LOGW ("Fail to play TTS : ret (%d)", r);
3288 #endif /* HAVE_TTS */
3291 * @brief Show rect for candidate focus object when screen reader is enabled.
3293 * @param x Rect X position.
3294 * @param y Rect Y position.
3295 * @param w Rect width.
3296 * @param h Rect height.
3298 static void ui_tts_focus_rect_show (int x, int y, int w, int h)
3300 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3301 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
3304 if (_tts_focus_rect == NULL) {
3305 _tts_focus_rect = evas_object_rectangle_add (evas_object_evas_get ((Evas_Object*)_candidate_window));
3306 evas_object_color_set (_tts_focus_rect, 0, 0, 0, 0);
3307 elm_access_highlight_set (elm_access_object_register (_tts_focus_rect, (Evas_Object*)_candidate_window));
3309 evas_object_move (_tts_focus_rect, x, y);
3310 evas_object_resize (_tts_focus_rect, w, h);
3311 evas_object_raise (_tts_focus_rect);
3312 evas_object_show (_tts_focus_rect);
3316 * @brief Hide rect for candidate focus object when screen reader is enabled.
3318 static void ui_tts_focus_rect_hide (void)
3320 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3322 if (_tts_focus_rect) {
3323 //evas_object_hide (_tts_focus_rect);
3324 evas_object_move (_tts_focus_rect, -1000, -1000);
3329 * @brief Callback function for candidate scroller stop event.
3331 * @param data Data to pass when it is called.
3332 * @param obj The evas object for current event.
3333 * @param event_info The information for current event.
3335 static void ui_candidate_scroller_stop_cb (void *data, Evas_Object *obj, void *event_info)
3337 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3338 if (!_wait_stop_event)
3341 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
3342 if (_candidate_0 [_candidate_tts_focus_index]) {
3344 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
3345 ui_tts_focus_rect_show (x, y, w, h);
3348 _wait_stop_event = false;
3353 * @brief Mouse over (find focus object and play text by TTS) when screen reader is enabled.
3355 * @param mouse_x Mouse X position.
3356 * @param mouse_y Mouse Y position.
3358 static void ui_mouse_over (int mouse_x, int mouse_y)
3360 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3361 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
3364 int x, y, width, height;
3365 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3366 if (_candidate_0 [i]) {
3367 evas_object_geometry_get (_candidate_0 [i], &x, &y, &width, &height);
3368 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3369 /* FIXME: Should consider emoji case */
3370 String mbs = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (i));
3371 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " play candidate string: " << mbs << "\n";
3373 ui_play_tts (mbs.c_str ());
3375 _candidate_tts_focus_index = i;
3376 ui_tts_focus_rect_show (x, y, width, height);
3382 String strTts = String ("");
3383 if (_candidate_area_2_visible) {
3384 evas_object_geometry_get (_close_btn, &x, &y, &width, &height);
3385 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3386 strTts = String (_("close button"));
3387 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
3388 ui_tts_focus_rect_show (x, y, width, height);
3391 evas_object_geometry_get (_more_btn, &x, &y, &width, &height);
3392 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3393 strTts = String (_("more button"));
3394 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
3395 ui_tts_focus_rect_show (x, y, width, height);
3399 if (strTts.length () > 0)
3400 ui_play_tts (strTts.c_str ());
3405 * @brief Mouse click (find focus object and do click event) when screen reader is enabled.
3407 * @param focus_index focused candidate index.
3409 static void ui_mouse_click (int focus_index)
3411 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3412 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW || focus_index == INVALID_TTS_FOCUS_INDEX)
3415 if (focus_index >= 0 && focus_index < g_isf_candidate_table.get_current_page_size ()) {
3416 if (_candidate_0 [focus_index]) {
3417 int x, y, width, height;
3418 evas_object_geometry_get (_candidate_0 [focus_index], &x, &y, &width, &height);
3419 Evas_Event_Mouse_Down event_info;
3420 event_info.canvas.x = x + width / 2;
3421 event_info.canvas.y = y + height / 2;
3422 ui_mouse_button_pressed_cb (GINT_TO_POINTER ((focus_index << 8) + ISF_EFL_CANDIDATE_0), NULL, NULL, &event_info);
3423 ui_mouse_button_released_cb (GINT_TO_POINTER (focus_index), NULL, NULL, &event_info);
3425 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
3426 ui_tts_focus_rect_hide ();
3430 if (_candidate_area_2_visible) {
3431 if (focus_index == CLOSE_BUTTON_INDEX) {
3432 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
3433 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
3436 if (focus_index == MORE_BUTTON_INDEX) {
3437 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
3438 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
3442 #endif /* HAVE_ECOREX */
3445 * @brief Create preedit window.
3447 static void ui_create_preedit_window (void)
3449 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3451 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3454 _preedit_width = 100;
3455 _preedit_height = _preedit_height * _height_rate;
3456 if (_preedit_window == NULL) {
3457 _preedit_window = efl_create_window ("ISF Popup", "Preedit Window");
3458 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
3459 int rots [4] = {0, 90, 180, 270};
3460 elm_win_wm_rotation_available_rotations_set (_preedit_window, rots, 4);
3461 int preedit_font_size = (int)(32 * _width_rate);
3463 _preedit_text = edje_object_add (evas_object_evas_get (_preedit_window));
3464 edje_object_file_set (_preedit_text, _candidate_edje_file.c_str (), "preedit_text");
3465 evas_object_size_hint_fill_set (_preedit_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
3466 evas_object_size_hint_weight_set (_preedit_text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3467 elm_win_resize_object_add (_preedit_window, _preedit_text);
3468 evas_object_show (_preedit_text);
3470 _tmp_preedit_text = evas_object_text_add (evas_object_evas_get (_preedit_window));
3471 evas_object_text_font_set (_tmp_preedit_text, _candidate_font_name.c_str (), preedit_font_size);
3476 * @brief Create native style candidate window.
3478 static void ui_create_native_candidate_window (void)
3480 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3481 _more_btn_width = 80 * (_width_rate > 1 ? 1 : _width_rate);
3482 _more_btn_height = 64 * _height_rate;
3484 _candidate_port_width = _screen_width;
3485 _candidate_port_height_min = 84 * _height_rate * _candidate_port_line;
3486 _candidate_port_height_min_2 = 84 * _height_rate + _candidate_port_height_min;
3487 _candidate_port_height_max = 426 * _height_rate + _candidate_port_height_min;
3488 _candidate_port_height_max_2 = 84 * _height_rate + _candidate_port_height_max;
3489 _candidate_land_width = _screen_height;
3490 _candidate_land_height_min = 84 * _width_rate;
3491 _candidate_land_height_min_2 = 168 * _width_rate;
3492 _candidate_land_height_max = 342 * _width_rate;
3493 _candidate_land_height_max_2 = 426 * _width_rate;
3495 _candidate_scroll_0_width_min= _screen_width;
3496 _candidate_scroll_0_width_max= _screen_height;
3497 _candidate_scroll_width_min = _screen_width;
3498 _candidate_scroll_width_max = _screen_height;
3499 _candidate_scroll_height_min = 252 * _width_rate;
3500 _candidate_scroll_height_max = 420 * _height_rate;
3502 _candidate_area_1_pos [0] = 0 * _width_rate;
3503 _candidate_area_1_pos [1] = 2 * _height_rate;
3504 _more_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3505 _more_btn_pos [1] = 12 * _height_rate;
3506 _more_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3507 _more_btn_pos [3] = 12 * _width_rate;
3508 _close_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3509 _close_btn_pos [1] = 12 * _height_rate;
3510 _close_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3511 _close_btn_pos [3] = 12 * _width_rate;
3513 _aux_height = 84 * _height_rate - 2;
3514 _aux_port_width = _screen_width;
3515 _aux_land_width = _screen_height;
3517 _item_min_height = 84 * _height_rate - 2;
3519 /* Create candidate window */
3520 if (_candidate_window == NULL) {
3521 _candidate_window = efl_create_window ("ISF Popup", "Prediction Window");
3522 int rots [4] = {0, 90, 180, 270};
3523 elm_win_wm_rotation_available_rotations_set (_candidate_window, rots, 4);
3524 if (_candidate_angle == 90 || _candidate_angle == 270) {
3525 _candidate_width = _candidate_land_width;
3526 _candidate_height = _candidate_land_height_min;
3528 _candidate_width = _candidate_port_width;
3529 _candidate_height = _candidate_port_height_min;
3533 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3534 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3535 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3536 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3537 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3538 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3539 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3540 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3543 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3544 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3545 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3546 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3547 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3548 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3549 ecore_wl2_window_rotation_geometry_set ((Ecore_Wl2_Window *)elm_win_wl_window_get (_candidate_window),
3550 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3552 /* Add dim background */
3553 Evas_Object *dim_bg = elm_bg_add (_candidate_window);
3554 evas_object_color_set (dim_bg, 0, 0, 0, 153);
3555 elm_win_resize_object_add (_candidate_window, dim_bg);
3556 evas_object_show (dim_bg);
3558 /* Add candidate background */
3559 _candidate_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3560 edje_object_file_set (_candidate_bg, _candidate_edje_file.c_str (), "candidate_bg");
3561 evas_object_size_hint_weight_set (_candidate_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3562 evas_object_resize (_candidate_bg, _candidate_port_width, _candidate_port_height_min);
3563 evas_object_move (_candidate_bg, 0, 0);
3564 evas_object_show (_candidate_bg);
3566 /* Create _candidate_0 scroller */
3567 _candidate_0_scroll = elm_scroller_add (_candidate_window);
3568 elm_scroller_bounce_set (_candidate_0_scroll, EINA_TRUE, EINA_FALSE);
3569 elm_scroller_policy_set (_candidate_0_scroll, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3570 evas_object_resize (_candidate_0_scroll, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
3571 evas_object_move (_candidate_0_scroll, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3573 /* Create candidate table */
3574 _candidate_0_table = elm_table_add (_candidate_window);
3575 evas_object_size_hint_weight_set (_candidate_0_table, 0.0, 0.0);
3576 evas_object_size_hint_align_set (_candidate_0_table, 0.0, 0.0);
3577 elm_table_padding_set (_candidate_0_table, 0, 0);
3578 elm_object_content_set (_candidate_0_scroll, _candidate_0_table);
3579 evas_object_show (_candidate_0_table);
3580 _candidate_area_1 = _candidate_0_scroll;
3582 /* Create more button */
3583 _more_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3584 if (_ise_width == 0 && _ise_height == 0)
3585 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
3587 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
3588 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
3589 evas_object_resize (_more_btn, _more_btn_width, _more_btn_height);
3590 evas_object_event_callback_add (_more_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_more_button_cb, NULL);
3592 /* Add scroller background */
3593 _candidate_scroll_width = _candidate_scroll_width_min;
3594 _scroller_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3595 edje_object_file_set (_scroller_bg, _candidate_edje_file.c_str (), "scroller_bg");
3596 evas_object_size_hint_weight_set (_scroller_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3597 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3598 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
3600 /* Create vertical scroller */
3601 _candidate_scroll = elm_scroller_add (_candidate_window);
3602 elm_scroller_bounce_set (_candidate_scroll, 0, 1);
3603 elm_scroller_policy_set (_candidate_scroll, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
3604 evas_object_resize (_candidate_scroll, _candidate_scroll_width, _candidate_scroll_height_max);
3605 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3606 elm_scroller_page_size_set (_candidate_scroll, 0, _item_min_height+_v_padding);
3607 evas_object_move (_candidate_scroll, 0, _candidate_port_height_min);
3609 /* Create candidate table */
3610 _candidate_table = elm_table_add (_candidate_window);
3611 evas_object_size_hint_weight_set (_candidate_table, 0.0, 0.0);
3612 evas_object_size_hint_align_set (_candidate_table, 0.0, 0.0);
3613 elm_table_padding_set (_candidate_table, 0, 0);
3614 elm_object_content_set (_candidate_scroll, _candidate_table);
3615 evas_object_show (_candidate_table);
3616 _candidate_area_2 = _candidate_scroll;
3617 evas_object_smart_callback_add (_candidate_scroll, "scroll,anim,stop", ui_candidate_scroller_stop_cb, NULL);
3619 /* Create close button */
3620 _close_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3621 if (_ise_width == 0 && _ise_height == 0)
3622 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
3624 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
3625 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
3626 evas_object_resize (_close_btn, _more_btn_width, _more_btn_height);
3627 evas_object_event_callback_add (_close_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_close_button_cb, NULL);
3629 _tmp_candidate_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3630 evas_object_text_font_set (_tmp_candidate_text, _candidate_font_name.c_str (), _candidate_font_size);
3633 _aux_area = elm_scroller_add (_candidate_window);
3634 elm_scroller_bounce_set (_aux_area, 1, 0);
3635 elm_scroller_policy_set (_aux_area, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3636 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
3637 evas_object_move (_aux_area, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3639 _aux_table = elm_table_add (_candidate_window);
3640 elm_object_content_set (_aux_area, _aux_table);
3641 elm_table_padding_set (_aux_table, 0, 0);
3642 evas_object_size_hint_weight_set (_aux_table, 0.0, 0.0);
3643 evas_object_size_hint_align_set (_aux_table, 0.0, 0.0);
3644 evas_object_show (_aux_table);
3646 _aux_line = edje_object_add (evas_object_evas_get (_candidate_window));
3647 edje_object_file_set (_aux_line, _candidate_edje_file.c_str (), "popup_line");
3648 evas_object_resize (_aux_line, _candidate_port_width, 2);
3649 evas_object_move (_aux_line, 0, _aux_height + 2);
3651 _tmp_aux_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3652 evas_object_text_font_set (_tmp_aux_text, _candidate_font_name.c_str (), _aux_font_size);
3654 evas_object_hide (_candidate_window);
3661 * @brief Create candidate window.
3665 static void ui_create_candidate_window (void)
3667 check_time ("\nEnter ui_create_candidate_window");
3668 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3669 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3674 _candidate_angle = 0;
3676 ui_create_native_candidate_window ();
3679 unsigned int set = 1;
3681 ecore_x_window_prop_card32_set (elm_win_xwindow_get (_candidate_window),
3682 ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
3685 int angle = efl_get_app_window_angle ();
3686 if (_candidate_angle != angle) {
3687 _candidate_angle = angle;
3688 ui_candidate_window_rotate (angle);
3690 ui_settle_candidate_window ();
3693 candidate_expanded = false;
3695 check_time ("Exit ui_create_candidate_window");
3699 * @brief Destroy candidate window.
3703 static void ui_destroy_candidate_window (void)
3705 check_time ("Enter ui_destroy_candidate_window");
3706 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3708 /* Delete candidate items, popup lines and seperator items */
3709 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3710 if (_candidate_0 [i]) {
3711 evas_object_del (_candidate_0 [i]);
3712 _candidate_0 [i] = NULL;
3714 if (_seperate_0 [i]) {
3715 evas_object_del (_seperate_0 [i]);
3716 _seperate_0 [i] = NULL;
3718 if (_seperate_items [i]) {
3719 evas_object_del (_seperate_items [i]);
3720 _seperate_items [i] = NULL;
3723 evas_object_del (_line_0 [i]);
3726 if (_line_items [i]) {
3727 evas_object_del (_line_items [i]);
3728 _line_items [i] = NULL;
3732 _aux_items.clear ();
3733 _aux_seperates.clear ();
3734 /* Delete candidate window */
3735 if (_candidate_window) {
3736 LOGD ("calling ui_candidate_hide (true)");
3737 ui_candidate_hide (true);
3739 evas_object_del (_candidate_window);
3740 _candidate_window = NULL;
3742 _candidate_area_1 = NULL;
3743 _candidate_area_2 = NULL;
3746 if (_tts_focus_rect) {
3747 evas_object_del (_tts_focus_rect);
3748 _tts_focus_rect = NULL;
3751 if (_candidate_bg) {
3752 evas_object_del (_candidate_bg);
3753 _candidate_bg = NULL;
3757 evas_object_del (_more_btn);
3762 evas_object_del (_scroller_bg);
3763 _scroller_bg = NULL;
3767 evas_object_del (_close_btn);
3772 evas_object_del (_aux_line);
3776 if (_tmp_candidate_text) {
3777 evas_object_del (_tmp_candidate_text);
3778 _tmp_candidate_text = NULL;
3781 if (_tmp_preedit_text) {
3782 evas_object_del (_tmp_preedit_text);
3783 _tmp_preedit_text = NULL;
3786 if (_tmp_aux_text) {
3787 evas_object_del (_tmp_aux_text);
3788 _tmp_aux_text = NULL;
3791 if (_preedit_text) {
3792 evas_object_del (_preedit_text);
3793 _preedit_text = NULL;
3796 if (_preedit_window) {
3797 evas_object_hide (_preedit_window);
3798 evas_object_del (_preedit_window);
3799 _preedit_window = NULL;
3803 check_time ("Exit ui_destroy_candidate_window");
3807 * @brief Settle candidate window position.
3809 static void ui_settle_candidate_window (void)
3811 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3813 if (!_candidate_window)
3816 /* If both ISE and candidate window are going to be hidden,
3817 let's just not move our candidate window */
3818 if (_ise_state == WINDOW_STATE_WILL_HIDE && _candidate_state == WINDOW_STATE_WILL_HIDE)
3822 int x, y, width, height;
3823 int ise_width = 0, ise_height = 0;
3824 bool get_geometry_result = false;
3826 /* Get candidate window position */
3827 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
3831 int pos_x = 0, pos_y = 0;
3832 if (_candidate_angle == 90 || _candidate_angle == 270)
3833 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_height, &ise_width);
3835 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_width, &ise_height);
3840 ise_width = _ise_width;
3841 ise_height = _ise_height;
3842 get_geometry_result = true;
3844 if ((_ise_state != WINDOW_STATE_SHOW && _ise_state != WINDOW_STATE_WILL_HIDE) ||
3845 (get_geometry_result == false) || (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
3850 int height2 = ui_candidate_get_valid_height ();
3852 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
3853 if (_candidate_angle == 90) {
3854 spot_x = _screen_width - ise_height - height2;
3856 } else if (_candidate_angle == 270) {
3857 spot_x = ise_height - (_candidate_height - height2);
3859 } else if (_candidate_angle == 180) {
3861 spot_y = ise_height - (_candidate_height - height2);
3864 spot_y = _screen_height - ise_height - height2;
3867 spot_x = _spot_location_x;
3868 spot_y = _spot_location_y;
3870 rectinfo ise_rect = {0, 0, (uint32)ise_width, (uint32)ise_height};
3871 if (_candidate_angle == 90 || _candidate_angle == 270) {
3872 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32)_screen_width)
3873 ise_rect.height = ISE_DEFAULT_HEIGHT_LANDSCAPE * _width_rate;
3875 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32) _screen_height)
3876 ise_rect.height = ISE_DEFAULT_HEIGHT_PORTRAIT * _height_rate;
3879 int nOffset = _candidate_port_height_min / 3;
3880 if (_candidate_angle == 270) {
3881 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3882 spot_x = _screen_width - _spot_location_top_y - (_candidate_height - height2);
3884 spot_x = _screen_width - _spot_location_y - _candidate_height;
3886 } else if (_candidate_angle == 90) {
3887 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3888 spot_x = _spot_location_top_y - height2;
3892 } else if (_candidate_angle == 180) {
3893 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3894 spot_y = _screen_height - _spot_location_top_y - (_candidate_height - height2);
3896 spot_y = _screen_height - _spot_location_y - _candidate_height;
3899 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3900 spot_y = _spot_location_top_y - height2;
3905 if (_candidate_angle == 90) {
3906 spot_y = (_screen_height - _candidate_width) / 2;
3907 spot_x = spot_x < _indicator_height ? _indicator_height : spot_x;
3908 if (spot_x > _screen_width - _candidate_height)
3909 spot_x = _screen_width - _candidate_height;
3910 } else if (_candidate_angle == 270) {
3911 spot_y = (_screen_height - _candidate_width) / 2;
3912 spot_x = spot_x < 0 ? 0 : spot_x;
3913 if (spot_x > _screen_width - (_indicator_height+_candidate_height))
3914 spot_x = _screen_width - (_indicator_height+_candidate_height);
3915 } else if (_candidate_angle == 180) {
3916 spot_x = (_screen_width - _candidate_width) / 2;
3917 spot_y = spot_y < 0 ? 0 : spot_y;
3918 if (spot_y > _screen_height - (_indicator_height+_candidate_height))
3919 spot_y = _screen_height - (_indicator_height+_candidate_height);
3921 spot_x = (_screen_width - _candidate_width) / 2;
3922 spot_y = spot_y < _indicator_height ? _indicator_height : spot_y;
3923 if (spot_y > _screen_height - _candidate_height)
3924 spot_y = _screen_height - _candidate_height;
3927 if (spot_x != x || spot_y != y) {
3928 _candidate_x = spot_x;
3929 _candidate_y = spot_y;
3930 evas_object_move (_candidate_window, spot_x, spot_y);
3931 LOGD ("Moving candidate window to : %d %d", spot_x, spot_y);
3932 if (_preedit_window) {
3933 if (_candidate_angle == 90) {
3934 spot_x -= _preedit_height;
3935 spot_y = _screen_height - _preedit_width;
3936 } else if (_candidate_angle == 270) {
3938 } else if (_candidate_angle == 180) {
3939 spot_x = _screen_width - _preedit_width;
3942 spot_y -= _preedit_height;
3944 evas_object_move (_preedit_window, spot_x, spot_y);
3946 if (_candidate_state == WINDOW_STATE_SHOW) {
3947 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
3951 #endif /* CANDIDATE */
3954 * @brief Set soft candidate geometry.
3956 * @param x The x position in screen.
3957 * @param y The y position in screen.
3958 * @param width The candidate window width.
3959 * @param height The candidate window height.
3961 static void set_soft_candidate_geometry (int x, int y, int width, int height)
3963 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
3965 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);
3967 if ((_candidate_mode != SOFT_CANDIDATE_WINDOW) || (_info_manager->get_current_toolbar_mode () != TOOLBAR_KEYBOARD_MODE))
3970 _soft_candidate_width = width;
3971 _soft_candidate_height = height;
3973 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry());
3975 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
3978 #if ISF_BUILD_CANDIDATE_UI
3979 //////////////////////////////////////////////////////////////////////
3980 // End of Candidate Functions
3981 //////////////////////////////////////////////////////////////////////
3984 * @brief Set transient for app window.
3986 * @param window The Ecore_X_Window handler of app window.
3988 static void efl_set_transient_for_app_window (Ecore_X_Window window)
3990 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3992 /* Set a transient window for window stack */
3993 Ecore_X_Window xAppWindow = efl_get_app_window ();
3994 ecore_x_icccm_transient_for_set (window, xAppWindow);
3996 LOGD ("win : %x, forwin : %x", window, xAppWindow);
3999 static int efl_get_window_rotate_angle (Ecore_X_Window win)
4001 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4006 unsigned char *prop_data = NULL;
4008 ret = ecore_x_window_prop_property_get (win,
4009 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
4010 if (ret && prop_data) {
4011 memcpy (&angle, prop_data, sizeof (int));
4012 LOGD ("WINDOW angle of %p is %d", win, angle);
4014 std::cerr << "ecore_x_window_prop_property_get () is failed!!!\n";
4015 LOGW ("WINDOW angle of %p FAILED!", win);
4022 #endif /* HAVE_ECOREX */
4025 * @brief Get angle for app window.
4027 * @param win_obj The Evas_Object handler of application window.
4029 * @return The angle of app window.
4031 static int efl_get_app_window_angle ()
4033 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4035 return efl_get_window_rotate_angle (efl_get_app_window ());
4041 #endif /* CANDIDATE */
4044 * @brief Get angle for ise window.
4046 * @param win_obj The Evas_Object handler of ise window.
4048 * @return The angle of ise window.
4050 static int efl_get_ise_window_angle ()
4052 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4054 return efl_get_window_rotate_angle (_ise_window);
4061 #if ISF_BUILD_CANDIDATE_UI
4064 * @brief Get angle of quickpanel window.
4066 * @return The angle of quickpanel window.
4068 static int efl_get_quickpanel_window_angle ()
4070 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4071 return efl_get_window_rotate_angle (efl_get_quickpanel_window ());
4076 * @brief Set showing effect for application window.
4078 * @param win The Evas_Object handler of application window.
4079 * @param strEffect The pointer of effect string.
4081 static void efl_set_showing_effect_for_app_window (Evas_Object *win, const char* strEffect)
4083 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4085 ecore_x_icccm_name_class_set (elm_win_xwindow_get (static_cast<Evas_Object*>(win)), strEffect, "ISF");
4090 * @brief Create elementary window.
4092 * @param strWinName The window name.
4093 * @param strEffect The window effect string.
4095 * @return The window pointer
4097 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect)
4099 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4101 Evas_Object *win = elm_win_add (NULL, strWinName, ELM_WIN_UTILITY);
4102 elm_win_title_set (win, strWinName);
4104 /* set window properties */
4105 elm_win_autodel_set (win, EINA_TRUE);
4106 elm_object_focus_allow_set (win, EINA_FALSE);
4107 elm_win_borderless_set (win, EINA_TRUE);
4108 elm_win_alpha_set (win, EINA_TRUE);
4109 elm_win_prop_focus_skip_set (win, EINA_TRUE);
4110 efl_set_showing_effect_for_app_window (win, strEffect);
4114 #endif /* CANDIDATE */
4118 * @brief Create elementary control window.
4120 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
4122 static Eina_Bool efl_create_control_window (void)
4124 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4126 /* WMSYNC, #1 Creating and registering control window */
4127 if (ecore_x_display_get () == NULL)
4130 Ecore_X_Window root = ecore_x_window_root_first_get ();
4131 _control_window = ecore_x_window_input_new (root, -100, -100, 1, 1);
4132 //ecore_x_e_virtual_keyboard_control_window_set (root, _control_window, 0, EINA_TRUE);
4134 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_CONTROL_WINDOW");
4135 ecore_x_window_prop_xid_set (root, atom, ECORE_X_ATOM_WINDOW, &_control_window, 1);
4141 * @brief Get an window's x window id.
4143 * @param name the property name.
4144 * @return X window id.
4146 static Ecore_X_Window efl_get_window (const char *name)
4148 /* Gets the XID of the window from the root window property */
4152 unsigned long nitems_return;
4153 unsigned long bytes_after_return;
4154 unsigned char *data = NULL;
4155 Ecore_X_Window window = 0;
4157 ret = XGetWindowProperty ((Display *)ecore_x_display_get (),
4158 ecore_x_window_root_get (_control_window),
4159 ecore_x_atom_get (name),
4160 0, G_MAXLONG, False, XA_WINDOW, &type_return,
4161 &format_return, &nitems_return, &bytes_after_return,
4164 if (ret == Success) {
4165 if ((type_return == XA_WINDOW) && (format_return == 32) && (data)) {
4166 window = *(Window *)data;
4169 std::cerr << "XGetWindowProperty () is failed!!!\n";
4179 * @brief Get app window's x window id.
4181 * @return the X window id of application to have focus or to request to show IME.
4183 static Ecore_X_Window efl_get_app_window (void)
4185 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4187 return efl_get_window ("_ISF_ACTIVE_WINDOW");
4191 * @brief Get clipboard window's x window id.
4193 * @return the X window id of clipboard.
4195 static Ecore_X_Window efl_get_clipboard_window (void)
4197 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4199 return efl_get_window ("CBHM_ELM_WIN");
4203 * @brief Get global natigation window's x window id.
4205 * @return the X window id of global navigation.
4207 static Ecore_X_Window efl_get_global_navigation_window (void)
4209 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4211 return efl_get_window ("GNB_WIN");
4215 * @brief Get app window's x window id.
4217 * @return the X window id of quick panel.
4219 static Ecore_X_Window efl_get_quickpanel_window (void)
4221 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4223 Ecore_X_Window rootWin = ecore_x_window_root_first_get ();
4224 Ecore_X_Window qpwin;
4225 ecore_x_window_prop_xid_get (rootWin, ecore_x_atom_get ("_E_ILLUME_QUICKPANEL_WINDOW_LIST"), ECORE_X_ATOM_WINDOW, &qpwin, 1);
4231 * @brief Get default zone geometry.
4233 * @param x The zone x position.
4234 * @param y The zone y position.
4235 * @param w The zone width.
4236 * @param h The zone height.
4238 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
4240 static Eina_Bool efl_get_default_zone_geometry_info (Ecore_X_Window root, uint *x, uint *y, uint *w, uint *h)
4242 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4244 Ecore_X_Atom zone_geometry_atom;
4245 Ecore_X_Window *zone_lists;
4250 zone_geometry_atom = ecore_x_atom_get ("_E_ILLUME_ZONE_GEOMETRY");
4251 if (!zone_geometry_atom) {
4257 num_zone_lists = ecore_x_window_prop_window_list_get (root, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, &zone_lists);
4258 if (num_zone_lists > 0) {
4259 num_ret = ecore_x_window_prop_card32_get (zone_lists[0], zone_geometry_atom, geom, 4);
4261 if (x) *x = geom[0];
4262 if (y) *y = geom[1];
4263 if (w) *w = geom[2];
4264 if (h) *h = geom[3];
4270 /* if there is no zone available */
4275 /* We must free zone_lists */
4281 #endif /* HAVE_ECOREX */
4283 #if ISF_BUILD_CANDIDATE_UI
4285 * @brief Get screen resolution.
4287 * @param width The screen width.
4288 * @param height The screen height.
4290 static void efl_get_screen_resolution (int &width, int &height)
4292 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4294 static Evas_Coord scr_w = 0, scr_h = 0;
4295 if (scr_w == 0 || scr_h == 0) {
4298 if (efl_get_default_zone_geometry_info (ecore_x_window_root_first_get (), NULL, NULL, &w, &h)) {
4302 ecore_x_window_size_get (ecore_x_window_root_first_get (), &scr_w, &scr_h);
4305 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get(NULL);
4307 ecore_wl2_display_screen_size_get(wl2_display, &scr_w, &scr_h);
4314 #endif /* CANDIDATE */
4316 //////////////////////////////////////////////////////////////////////
4317 // Start of PanelAgent Functions
4318 //////////////////////////////////////////////////////////////////////
4321 * @brief Initialize panel agent.
4323 * @param config The config string for PanelAgent.
4324 * @param display The current display.
4325 * @param resident The variable indicates whether panel will be resident.
4327 * @return true if initialize is successful, otherwise return false.
4329 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident)
4331 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4333 LOGD ("initializing panel agent");
4335 _info_manager = new InfoManager ();
4337 if (!_info_manager || !_info_manager->initialize (_info_manager, config, display, resident)) {
4338 ISF_SAVE_LOG ("panel_agent initialize fail!");
4342 _info_manager->signal_connect_focus_in (slot (slot_focus_in));
4343 _info_manager->signal_connect_focus_out (slot (slot_focus_out));
4344 _info_manager->signal_connect_expand_candidate (slot (slot_expand_candidate));
4345 _info_manager->signal_connect_contract_candidate (slot (slot_contract_candidate));
4346 _info_manager->signal_connect_set_candidate_ui (slot (slot_set_candidate_style));
4347 _info_manager->signal_connect_update_factory_info (slot (slot_update_factory_info));
4348 _info_manager->signal_connect_update_spot_location (slot (slot_update_spot_location));
4349 _info_manager->signal_connect_update_input_context (slot (slot_update_input_context));
4350 _info_manager->signal_connect_update_ise_geometry (slot (slot_update_ise_geometry));
4351 _info_manager->signal_connect_show_preedit_string (slot (slot_show_preedit_string));
4352 _info_manager->signal_connect_show_aux_string (slot (slot_show_aux_string));
4353 _info_manager->signal_connect_show_lookup_table (slot (slot_show_candidate_table));
4354 _info_manager->signal_connect_hide_preedit_string (slot (slot_hide_preedit_string));
4355 _info_manager->signal_connect_hide_aux_string (slot (slot_hide_aux_string));
4356 _info_manager->signal_connect_hide_lookup_table (slot (slot_hide_candidate_table));
4357 _info_manager->signal_connect_update_preedit_string (slot (slot_update_preedit_string));
4358 _info_manager->signal_connect_update_preedit_caret (slot (slot_update_preedit_caret));
4359 _info_manager->signal_connect_update_aux_string (slot (slot_update_aux_string));
4360 _info_manager->signal_connect_update_lookup_table (slot (slot_update_candidate_table));
4361 _info_manager->signal_connect_select_candidate (slot (slot_select_candidate));
4362 _info_manager->signal_connect_get_candidate_geometry (slot (slot_get_candidate_geometry));
4363 _info_manager->signal_connect_get_input_panel_geometry (slot (slot_get_input_panel_geometry));
4364 _info_manager->signal_connect_set_active_ise_by_uuid (slot (slot_set_active_ise));
4365 _info_manager->signal_connect_get_ise_list (slot (slot_get_ise_list));
4366 _info_manager->signal_connect_get_all_helper_ise_info (slot (slot_get_all_helper_ise_info));
4367 _info_manager->signal_connect_set_has_option_helper_ise_info(slot (slot_set_has_option_helper_ise_info));
4368 _info_manager->signal_connect_set_enable_helper_ise_info (slot (slot_set_enable_helper_ise_info));
4369 _info_manager->signal_connect_show_helper_ise_list (slot (slot_show_helper_ise_list));
4370 _info_manager->signal_connect_show_helper_ise_selector (slot (slot_show_helper_ise_selector));
4371 _info_manager->signal_connect_is_helper_ise_enabled (slot (slot_is_helper_ise_enabled));
4372 _info_manager->signal_connect_get_ise_information (slot (slot_get_ise_information));
4373 _info_manager->signal_connect_get_keyboard_ise_list (slot (slot_get_keyboard_ise_list));
4374 _info_manager->signal_connect_get_language_list (slot (slot_get_language_list));
4375 _info_manager->signal_connect_get_all_language (slot (slot_get_all_language));
4376 _info_manager->signal_connect_get_ise_language (slot (slot_get_ise_language));
4377 _info_manager->signal_connect_get_ise_info_by_uuid (slot (slot_get_ise_info));
4378 _info_manager->signal_connect_set_keyboard_ise (slot (slot_set_keyboard_ise));
4379 _info_manager->signal_connect_get_keyboard_ise (slot (slot_get_keyboard_ise));
4380 _info_manager->signal_connect_accept_connection (slot (slot_accept_connection));
4381 _info_manager->signal_connect_close_connection (slot (slot_close_connection));
4382 _info_manager->signal_connect_exit (slot (slot_exit));
4384 _info_manager->signal_connect_register_helper (slot(slot_register_helper));
4385 _info_manager->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
4386 _info_manager->signal_connect_show_ise (slot (slot_show_ise));
4387 _info_manager->signal_connect_hide_ise (slot (slot_hide_ise));
4389 _info_manager->signal_connect_will_hide_ack (slot (slot_will_hide_ack));
4391 _info_manager->signal_connect_set_keyboard_mode (slot (slot_set_keyboard_mode));
4393 _info_manager->signal_connect_candidate_will_hide_ack (slot (slot_candidate_will_hide_ack));
4394 _info_manager->signal_connect_get_ise_state (slot (slot_get_ise_state));
4395 _info_manager->signal_connect_start_default_ise (slot (slot_start_default_ise));
4396 _info_manager->signal_connect_stop_default_ise (slot (slot_stop_default_ise));
4397 _info_manager->signal_connect_show_panel (slot (slot_show_helper_ise_selector));
4398 #if ENABLE_REMOTE_INPUT
4399 _info_manager->signal_connect_remoteinput_send_input_message(slot (slot_send_remote_input_message));
4400 _info_manager->signal_connect_remoteinput_send_surrounding_text(slot (slot_recv_remote_surrounding_text));
4402 _info_manager->signal_connect_get_recent_ise_geometry (slot (slot_get_recent_ise_geometry));
4403 _info_manager->signal_connect_check_privilege_by_sockfd (slot (slot_check_privilege_by_sockfd));
4405 _info_manager->signal_connect_run_helper (slot (slot_run_helper));
4406 _info_manager->signal_connect_launch_option_application (slot (slot_launch_option_application));
4408 LOGD ("initializing panel agent succeeded");
4413 static void delete_ise_hide_timer (void)
4415 LOGD ("deleting ise_hide_timer");
4416 if (_ise_hide_timer) {
4417 ecore_timer_del (_ise_hide_timer);
4418 _ise_hide_timer = NULL;
4422 static void hide_ise ()
4424 LOGD ("send request to hide helper");
4425 String uuid = _info_manager->get_current_helper_uuid ();
4426 _info_manager->hide_helper (uuid);
4428 /* Only if we are not already in HIDE state */
4429 if (_ise_state != WINDOW_STATE_HIDE) {
4430 /* From this point, slot_get_input_panel_geometry should return hidden state geometry */
4431 _ise_state = WINDOW_STATE_WILL_HIDE;
4433 _updated_hide_state_geometry = false;
4437 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
4439 #if ISF_BUILD_CANDIDATE_UI
4440 if (_candidate_window) {
4441 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)
4442 ui_candidate_hide (true, true, true);
4444 ui_candidate_hide (true, false, true);
4446 #endif /* CANDIDATE */
4449 #ifdef HAVE_NOTIFICATION
4450 delete_notification (&ise_selector_module_noti);
4455 #if ENABLE_MULTIWINDOW_SUPPORT
4456 static Eina_Bool ise_hide_timeout (void *data)
4458 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4460 delete_ise_hide_timer ();
4463 return ECORE_CALLBACK_CANCEL;
4468 * @brief Insert data to ime_info table.
4470 * @param list The list to store uuid
4472 * @return true if it is successful, otherwise return false.
4474 static bool update_ise_list (std::vector<String> &list)
4476 std::vector<String> uuids;
4477 std::vector<TOOLBAR_MODE_T> modes;
4478 std::vector<ImeInfoDB>::iterator iter;
4481 if (_ime_info.size() == 0) {
4482 if (isf_pkg_select_all_ime_info_db(_ime_info) == 0)
4486 /* Update _groups */
4488 std::vector<String> ise_langs;
4489 for (size_t i = 0; i < _ime_info.size (); ++i) {
4490 scim_split_string_list(ise_langs, _ime_info[i].languages);
4491 for (size_t j = 0; j < ise_langs.size (); j++) {
4492 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
4493 _groups[ise_langs[j]].push_back (i);
4498 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
4499 uuids.push_back(iter->appid);
4500 modes.push_back(iter->mode);
4503 if (uuids.size() > 0) {
4507 _info_manager->update_ise_list (list);
4509 if (_initial_ise_uuid.length () > 0) {
4510 String active_uuid = _initial_ise_uuid;
4511 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
4512 if (std::find (uuids.begin (), uuids.end (), default_uuid) == uuids.end ()) {
4513 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (modes[get_ise_index (_initial_ise_uuid)] != TOOLBAR_KEYBOARD_MODE)) {
4514 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4517 if (set_active_ise (active_uuid, _soft_keyboard_launched) == false) {
4518 if (_initial_ise_uuid.compare (active_uuid)) {
4519 LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
4520 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
4523 } else if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) { // Check whether keyboard engine is installed
4524 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
4525 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
4526 if (std::find (uuids.begin (), uuids.end (), keyboard_uuid) == uuids.end ()) {
4527 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4528 _info_manager->change_factory (active_uuid);
4529 _config->write (IMENGINE_KEY, active_uuid);
4536 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
4538 if (_ime_info.size () > 0 && _ime_info[0].display_lang.compare(lang_str) == 0)
4539 _locale_string = String (lang_str);
4545 LOGW ("No IME list");
4547 #ifdef HAVE_PKGMGR_INFO
4549 int ret = package_manager_create (&pkgmgr);
4550 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4551 ret = package_manager_set_event_cb (pkgmgr, _package_manager_event_cb, NULL);
4552 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4553 LOGD ("package_manager_set_event_cb succeeded.");
4556 LOGE ("package_manager_set_event_cb failed(%d)", ret);
4560 LOGE ("package_manager_create failed(%d)", ret);
4569 * @brief Focus in slot function for PanelAgent.
4571 static void slot_focus_in (void)
4573 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4576 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
4577 if (_launch_ise_on_request && !_soft_keyboard_launched) {
4578 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
4579 if (uuid.length () > 0 && (_ime_info[get_ise_index(uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
4580 LOGD ("Start helper (%s)", uuid.c_str ());
4582 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
4583 if (_info_manager->start_helper (uuid))
4584 _soft_keyboard_launched = true;
4589 #if ISF_BUILD_CANDIDATE_UI
4590 ui_candidate_delete_destroy_timer ();
4591 #endif /* CANDIDATE */
4595 * @brief Focus out slot function for PanelAgent.
4597 static void slot_focus_out (void)
4599 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4603 #if ISF_BUILD_CANDIDATE_UI
4604 ui_candidate_delete_destroy_timer ();
4605 _destroy_timer = ecore_timer_add (ISF_CANDIDATE_DESTROY_DELAY, ui_candidate_destroy_timeout, NULL);
4606 #endif /* CANDIDATE */
4610 * @brief Expand candidate slot function for PanelAgent.
4612 static void slot_expand_candidate (void)
4614 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4615 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4618 #if ISF_BUILD_CANDIDATE_UI
4619 if (_candidate_area_2 && !_candidate_area_2_visible)
4620 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
4621 #endif /* CANDIDATE */
4625 * @brief Contract candidate slot function for PanelAgent.
4627 static void slot_contract_candidate (void)
4629 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4631 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4634 #if ISF_BUILD_CANDIDATE_UI
4635 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
4636 #endif /* CANDIDATE */
4640 * @brief Set candidate style slot function for PanelAgent.
4642 * @param portrait_line The displayed line number for portrait.
4643 * @param mode The candidate mode.
4645 static void slot_set_candidate_style (int portrait_line, int mode)
4647 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " display_line:" << portrait_line << " mode:" << mode << "\n";
4648 #if ISF_BUILD_CANDIDATE_UI
4649 if ((portrait_line != _candidate_port_line) || (mode != _candidate_mode)) {
4650 _candidate_mode = (ISF_CANDIDATE_MODE_T)mode;
4651 _candidate_port_line = (ISF_CANDIDATE_PORTRAIT_LINE_T)portrait_line;
4652 _soft_candidate_width = 0;
4653 _soft_candidate_height = 0;
4655 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4656 if (_candidate_window)
4657 ui_destroy_candidate_window ();
4662 if (_candidate_window)
4663 ui_create_candidate_window ();
4665 #endif /* CANDIDATE */
4668 #if defined(HAVE_NOTIFICATION) || defined(HAVE_ECOREX)
4669 static unsigned int get_ise_count (TOOLBAR_MODE_T mode, bool valid_helper)
4671 unsigned int ise_count = 0;
4672 for (unsigned int i = 0; i < _ime_info.size (); i++) {
4673 if (mode == _ime_info[i].mode) {
4674 if (mode == TOOLBAR_KEYBOARD_MODE || !valid_helper)
4676 else if (_ime_info[i].is_enabled)
4686 * @brief Update keyboard ISE information slot function for PanelAgent.
4688 * @param info The information of current Keyboard ISE.
4690 static void slot_update_factory_info (const PanelFactoryInfo &info)
4692 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4694 String ise_name = info.name;
4696 String old_ise = _info_manager->get_current_ise_name ();
4697 #if ISF_BUILD_CANDIDATE_UI
4698 if (old_ise != ise_name) {
4699 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && _candidate_window) {
4700 ui_destroy_candidate_window ();
4703 #endif /* CANDIDATE */
4705 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
4707 if (TOOLBAR_HELPER_MODE == mode)
4708 ise_name = _ime_info[get_ise_index (_info_manager->get_current_helper_uuid())].label;
4710 if (ise_name.length () > 0)
4711 _info_manager->set_current_ise_name (ise_name);
4713 #ifdef HAVE_NOTIFICATION
4715 if (old_ise != ise_name) {
4716 if (TOOLBAR_KEYBOARD_MODE == mode) {
4717 char noti_msg[256] = {0};
4718 unsigned int keyboard_ise_count = get_ise_count (TOOLBAR_KEYBOARD_MODE, false);
4719 if (keyboard_ise_count == 0) {
4720 LOGD ("the number of keyboard ise is %d", keyboard_ise_count);
4723 else if (keyboard_ise_count >= 2) {
4724 snprintf (noti_msg, sizeof (noti_msg), _("%s selected"), ise_name.c_str ());
4726 else if (keyboard_ise_count == 1) {
4727 snprintf (noti_msg, sizeof (noti_msg), _("Only %s available"), ise_name.c_str ());
4730 notification_status_message_post (noti_msg);
4731 LOGD ("%s", noti_msg);
4739 * @brief Update cursor position slot function for PanelAgent.
4741 * @param x The x position of current cursor.
4742 * @param y The bottom y position of current cursor.
4743 * @param top_y The top y position of current cursor.
4745 static void slot_update_spot_location (int x, int y, int top_y)
4747 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4749 #if ISF_BUILD_CANDIDATE_UI
4750 if (x >= 0 && x < _screen_height && y >= 0 && y < _screen_height) {
4751 _spot_location_x = x;
4752 _spot_location_y = y;
4753 _spot_location_top_y = top_y;
4755 ui_settle_candidate_window ();
4757 #endif /* CANDIDATE */
4761 * @brief The input context of ISE is changed.
4763 * @param type The event type.
4764 * @param value The event value.
4766 static void slot_update_input_context (int type, int value)
4771 * @brief Update ise geometry.
4773 * @param x The x position in screen.
4774 * @param y The y position in screen.
4775 * @param width The ISE window width.
4776 * @param height The ISE window height.
4778 static void slot_update_ise_geometry (int x, int y, int width, int height)
4780 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
4782 LOGD ("x : %d , y : %d , width : %d , height : %d, _ise_state : %d", x, y, width, height, _ise_state);
4784 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
4785 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4786 /*IF ISE sent the ise_geometry information when the current_keyboard_mode is H/W mode and candidate_mode is SOFT_CANDIDATE,
4787 It means that given geometry information is for the candidate window */
4788 set_soft_candidate_geometry (x, y, width, height);
4796 _ise_height = height;
4798 #if ISF_BUILD_CANDIDATE_UI
4799 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
4800 ui_settle_candidate_window ();
4802 #endif /* CANDIDATE */
4804 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
4805 _ise_reported_geometry.valid = true;
4806 _ise_reported_geometry.angle = efl_get_ise_window_angle ();
4807 _ise_reported_geometry.geometry.pos_x = x;
4808 _ise_reported_geometry.geometry.pos_y = y;
4809 _ise_reported_geometry.geometry.width = width;
4810 _ise_reported_geometry.geometry.height = height;
4811 if (_ise_state == WINDOW_STATE_SHOW) {
4813 set_keyboard_geometry_atom_info (_app_window, _ise_reported_geometry.geometry);
4815 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
4821 * @brief Show preedit slot function for PanelAgent.
4823 static void slot_show_preedit_string (void)
4825 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4827 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4830 #if ISF_BUILD_CANDIDATE_UI
4831 if (_preedit_window == NULL) {
4832 ui_create_preedit_window ();
4834 /* Move preedit window according to candidate window position */
4835 if (_candidate_window) {
4836 /* Get candidate window position */
4837 int x, y, width, height;
4838 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
4840 int height2 = ui_candidate_get_valid_height ();
4841 int angle = efl_get_app_window_angle ();
4844 x -= _preedit_height;
4845 y = _screen_height - _preedit_width;
4846 } else if (_candidate_angle == 270) {
4848 } else if (_candidate_angle == 180) {
4849 x = _screen_width - _preedit_width;
4852 y -= _preedit_height;
4855 if (_preedit_window)
4856 evas_object_move (_preedit_window, x, y);
4860 if (_preedit_window && evas_object_visible_get (_preedit_window))
4863 slot_show_candidate_table ();
4865 if (_preedit_window)
4866 evas_object_show (_preedit_window);
4867 #endif /* CANDIDATE */
4871 * @brief Show aux slot function for PanelAgent.
4873 static void slot_show_aux_string (void)
4875 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4877 #if ISF_BUILD_CANDIDATE_UI
4878 if (_candidate_window == NULL)
4879 ui_create_candidate_window ();
4881 if (_aux_area == NULL || _aux_area_visible)
4884 evas_object_show (_aux_area);
4885 _aux_area_visible = true;
4886 ui_candidate_window_adjust ();
4888 LOGD ("calling ui_candidate_show ()");
4889 ui_candidate_show ();
4890 ui_settle_candidate_window ();
4891 ui_candidate_delete_destroy_timer ();
4892 #endif /* CANDIDATE */
4896 * @brief Show candidate table slot function for PanelAgent.
4898 static void slot_show_candidate_table (void)
4900 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4901 _info_manager->helper_candidate_show ();
4905 #if ISF_BUILD_CANDIDATE_UI
4906 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4907 if (_candidate_window == NULL)
4908 ui_create_candidate_window ();
4911 if (_candidate_state == WINDOW_STATE_SHOW &&
4912 (_candidate_area_1_visible || _candidate_area_2_visible)) {
4913 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
4918 evas_object_show (_candidate_area_1);
4919 _candidate_area_1_visible = true;
4920 ui_candidate_window_adjust ();
4922 LOGD ("calling ui_candidate_show ()");
4923 ui_candidate_show ();
4924 ui_settle_candidate_window ();
4925 ui_candidate_delete_destroy_timer ();
4927 #ifdef HAVE_FEEDBACK
4928 int feedback_result = feedback_initialize ();
4930 if (FEEDBACK_ERROR_NONE == feedback_result) {
4931 LOGD ("Feedback initialize successful");
4932 feedback_initialized = true;
4934 LOGW ("Feedback initialize fail : %d", feedback_result);
4935 feedback_initialized = false;
4937 #endif /* HAVE_FEEDBACK */
4938 #endif /* CANDIDATE */
4942 * @brief Hide preedit slot function for PanelAgent.
4944 static void slot_hide_preedit_string (void)
4946 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4948 #if ISF_BUILD_CANDIDATE_UI
4949 if (!_preedit_window || !evas_object_visible_get (_preedit_window))
4952 evas_object_hide (_preedit_window);
4953 #endif /* CANDIDATE */
4957 * @brief Hide aux slot function for PanelAgent.
4959 static void slot_hide_aux_string (void)
4961 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4963 #if ISF_BUILD_CANDIDATE_UI
4964 if (!_aux_area || !_aux_area_visible)
4967 evas_object_hide (_aux_area);
4968 _aux_area_visible = false;
4969 elm_scroller_region_show (_aux_area, 0, 0, 10, 10);
4970 ui_candidate_window_adjust ();
4972 LOGD ("calling ui_candidate_hide (false, true, true)");
4973 ui_candidate_hide (false, true, true);
4974 ui_settle_candidate_window ();
4976 if (ui_candidate_can_be_hide ()) {
4977 _candidate_show_requested = false;
4978 LOGD ("setting _show_candidate_requested to FALSE");
4980 #endif /* CANDIDATE */
4984 * @brief Hide candidate table slot function for PanelAgent.
4986 static void slot_hide_candidate_table (void)
4988 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4990 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4991 _info_manager->helper_candidate_hide ();
4995 #if ISF_BUILD_CANDIDATE_UI
4996 if (!_candidate_area_1 || _candidate_state == WINDOW_STATE_WILL_HIDE)
4999 if (_candidate_area_1_visible || _candidate_area_2_visible) {
5000 bool bForce = false;
5001 if (_candidate_area_1_visible) {
5002 if (_aux_area_visible) {
5003 evas_object_hide (_candidate_area_1);
5004 _candidate_area_1_visible = false;
5005 evas_object_hide (_more_btn);
5007 /* Let's not actually hide the _candidate_area_1 object, for the case that
5008 even if the application replies CANDIDATE_WILL_HIDE_ACK a little late,
5009 it is better to display the previous candidates instead of blank screen */
5010 _candidate_area_1_visible = false;
5014 if (_candidate_area_2_visible) {
5015 evas_object_hide (_candidate_area_2);
5016 _candidate_area_2_visible = false;
5017 evas_object_hide (_scroller_bg);
5018 evas_object_hide (_close_btn);
5019 _info_manager->candidate_more_window_hide ();
5021 ui_candidate_window_adjust ();
5023 LOGD ("calling ui_candidate_hide (%d, true, true)", bForce);
5024 ui_candidate_hide (bForce, true, true);
5025 ui_settle_candidate_window ();
5028 #ifdef HAVE_FEEDBACK
5029 int feedback_result = feedback_deinitialize ();
5031 if (FEEDBACK_ERROR_NONE == feedback_result)
5032 LOGD ("Feedback deinitialize successful");
5034 LOGW ("Feedback deinitialize fail : %d", feedback_result);
5036 feedback_initialized = false;
5039 if (ui_candidate_can_be_hide ()) {
5040 _candidate_show_requested = false;
5041 LOGD ("setting _show_candidate_requested to FALSE");
5043 #endif /* CANDIDATE */
5047 * @brief Update preedit slot function for PanelAgent.
5049 * @param str The new preedit string.
5050 * @param attrs The attribute list of new preedit string.
5052 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret)
5054 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " string=" << str << "\n";
5056 #if ISF_BUILD_CANDIDATE_UI
5057 if (str.length () <= 0)
5060 if (_preedit_window == NULL || !evas_object_visible_get (_preedit_window)) {
5061 slot_show_preedit_string ();
5064 int x, y, width, height, candidate_width;
5065 evas_object_text_text_set (_tmp_preedit_text, str.c_str ());
5066 evas_object_geometry_get (_tmp_preedit_text, &x, &y, &width, &height);
5067 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &candidate_width, &height);
5068 _preedit_width = (width + ISF_PREEDIT_BORDER * 2) < candidate_width ? (width + ISF_PREEDIT_BORDER * 2) : candidate_width;
5070 /* Resize preedit window and avoid text blink */
5071 int old_width, old_height;
5072 evas_object_geometry_get (_preedit_window, &x, &y, &old_width, &old_height);
5073 if (old_width < _preedit_width) {
5074 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
5075 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
5077 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
5078 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
5081 /* Move preedit window */
5082 if (_candidate_angle == 90 || _candidate_angle == 180) {
5083 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_preedit_window)), &x, &y, &width, &height);
5084 if (_candidate_angle == 90) {
5085 y = _screen_height - _preedit_width;
5086 } else if (_candidate_angle == 180) {
5087 x = _screen_width - _preedit_width;
5089 evas_object_move (_preedit_window, x, y);
5091 #endif /* CANDIDATE */
5095 * @brief Update caret slot function for PanelAgent.
5097 * @param caret The caret position.
5099 static void slot_update_preedit_caret (int caret)
5101 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " caret=" << caret << "\n";
5104 #if ISF_BUILD_CANDIDATE_UI
5106 * @brief Set highlight text color and background color for edje object.
5108 * @param item The edje object pointer.
5109 * @param nForeGround The text color.
5110 * @param nBackGround The background color.
5111 * @param bSetBack The flag for background color.
5113 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack)
5115 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5117 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
5118 if (edje_object_color_class_get (item, "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
5119 r = SCIM_RGB_COLOR_RED (nForeGround);
5120 g = SCIM_RGB_COLOR_GREEN (nForeGround);
5121 b = SCIM_RGB_COLOR_BLUE (nForeGround);
5122 edje_object_color_class_set (item, "text_color", r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
5124 if (bSetBack && edje_object_color_class_get (item, "rect_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
5125 r = SCIM_RGB_COLOR_RED (nBackGround);
5126 g = SCIM_RGB_COLOR_GREEN (nBackGround);
5127 b = SCIM_RGB_COLOR_BLUE (nBackGround);
5128 edje_object_color_class_set (item, "rect_color", r, g, b, 255, r2, g2, b2, a2, r3, g3, b3, a3);
5131 #endif /* CANDIDATE */
5134 * @brief Update aux slot function for PanelAgent.
5136 * @param str The new aux string.
5137 * @param attrs The attribute list of new aux string.
5139 static void slot_update_aux_string (const String &str, const AttributeList &attrs)
5141 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5142 #if ISF_BUILD_CANDIDATE_UI
5143 if (_candidate_window == NULL)
5144 ui_create_candidate_window ();
5146 if (!_aux_area || (str.length () <= 0))
5149 if (!_aux_area_visible) {
5150 LOGD ("calling ui_candidate_show ()");
5151 ui_candidate_show ();
5152 slot_show_aux_string ();
5155 int x, y, width, height, item_width = 0;
5156 unsigned int window_width = 0, count = 0, i;
5158 Evas_Object *aux_edje = NULL;
5160 /* Get highlight item index */
5161 int aux_index = -1, aux_start = 0, aux_end = 0;
5162 String strAux = str;
5163 bool bSetBack = false;
5164 uint32 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
5165 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
5166 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5167 if (aux_index == -1 && ait->get_type () == SCIM_ATTR_DECORATE) {
5168 aux_index = ait->get_value ();
5169 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
5170 nForeGround = ait->get_value ();
5171 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
5172 nBackGround = ait->get_value ();
5177 std::vector<String> aux_list;
5178 scim_split_string_list (aux_list, strAux, '|');
5180 if (_aux_items.size () > 0) {
5181 for (i = 0; i < _aux_items.size (); i++)
5182 evas_object_del (_aux_items [i]);
5183 _aux_items.clear ();
5185 if (_aux_seperates.size () > 0) {
5186 for (i = 0; i < _aux_seperates.size (); i++)
5187 evas_object_del (_aux_seperates [i]);
5188 _aux_seperates.clear ();
5191 int seperate_width = 4;
5192 int seperate_height = 52 * _height_rate;
5193 Evas *evas = evas_object_evas_get (_candidate_window);
5194 for (i = 0; i < aux_list.size (); i++) {
5196 Evas_Object *seperate_item = edje_object_add (evas);
5197 edje_object_file_set (seperate_item, _candidate_edje_file.c_str (), "seperate_line");
5198 evas_object_size_hint_min_set (seperate_item, seperate_width, seperate_height);
5199 elm_table_pack (_aux_table, seperate_item, 2 * i - 1, 0, 1, 1);
5200 evas_object_show (seperate_item);
5201 _aux_seperates.push_back (seperate_item);
5205 aux_edje = edje_object_add (evas);
5206 edje_object_file_set (aux_edje, _candidate_edje_file.c_str (), "aux");
5207 edje_object_part_text_set (aux_edje, "aux", aux_list [i].c_str ());
5208 edje_object_text_class_set (aux_edje, "tizen", _candidate_font_name.c_str (), _aux_font_size);
5209 elm_table_pack (_aux_table, aux_edje, 2 * i, 0, 1, 1);
5210 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_AUX));
5211 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5212 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_AUX));
5213 evas_object_show (aux_edje);
5214 _aux_items.push_back (aux_edje);
5215 /* if (i == (unsigned int)aux_index)
5216 edje_object_signal_emit (aux_edje, "aux,state,selected", "aux");
5218 edje_object_signal_emit (aux_edje, "aux,state,unselected", "aux");
5220 evas_object_text_text_set (_tmp_aux_text, aux_list [i].c_str ());
5221 evas_object_geometry_get (_tmp_aux_text, &x, &y, &width, &height);
5222 item_width = width + 2*_blank_width;
5223 item_width = item_width > _item_min_width ? item_width : _item_min_width;
5224 evas_object_size_hint_min_set (aux_edje, item_width, _aux_height);
5225 if (aux_index == (int)i || (aux_index == -1 && i == 0)) {
5226 aux_start = window_width;
5227 aux_end = window_width + item_width;
5229 window_width = window_width + item_width + 4;
5232 // Set highlight item
5233 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5234 if (ait->get_type () == SCIM_ATTR_DECORATE) {
5235 unsigned int index = ait->get_value ();
5236 if (index < _aux_items.size ())
5237 set_highlight_color (_aux_items [index], nForeGround, nBackGround, bSetBack);
5242 elm_scroller_region_get (_aux_area, &x, &y, &w, &h);
5243 item_width = aux_end - aux_start;
5244 if (item_width > 0) {
5245 if (item_width >= w)
5246 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
5247 else if (aux_end > x + w)
5248 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
5249 else if (aux_start < x)
5250 elm_scroller_region_show (_aux_area, aux_start, y, w, h);
5253 #endif /* CANDIDATE */
5256 #if ISF_BUILD_CANDIDATE_UI
5258 * @brief Update candidate/associate table.
5260 * @param table_type The table type.
5261 * @param table The lookup table for candidate or associate.
5263 static void update_table (int table_type, const LookupTable &table)
5265 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << table.get_current_page_size () << ")\n";
5267 int item_num = table.get_current_page_size ();
5274 AttributeList attrs;
5275 int i, x, y, item_0_width = 0;
5279 int seperate_width = 2;
5280 int seperate_height = 52 * _height_rate;
5281 int line_width = _candidate_scroll_width;
5282 int line_height = _v_padding;
5283 int total_width = 0;
5284 int current_width = 0;
5287 int more_item_count = 0;
5288 int scroll_0_width = _candidate_scroll_0_width_min;
5289 int cursor_pos = table.get_cursor_pos ();
5290 int cursor_line = 0;
5292 if (_candidate_angle == 90 || _candidate_angle == 270)
5293 scroll_0_width = _screen_height - _more_btn_width - _h_padding;
5295 scroll_0_width = _screen_width - _more_btn_width - _h_padding;
5297 _candidate_image_count = 0;
5298 _candidate_text_count = 0;
5299 _candidate_pop_image_count = 0;
5300 _candidate_display_number = 0;
5301 _candidate_row_items.clear ();
5303 Evas *evas = evas_object_evas_get (_candidate_window);
5304 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
5305 if (_candidate_0 [i]) {
5306 evas_object_del (_candidate_0 [i]);
5307 _candidate_0 [i] = NULL;
5309 if (_seperate_0 [i]) {
5310 evas_object_del (_seperate_0 [i]);
5311 _seperate_0 [i] = NULL;
5313 if (_seperate_items [i]) {
5314 evas_object_del (_seperate_items [i]);
5315 _seperate_items [i] = NULL;
5318 evas_object_del (_line_0 [i]);
5321 if (_line_items [i]) {
5322 evas_object_del (_line_items [i]);
5323 _line_items [i] = NULL;
5327 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
5329 bool bHighLight = false;
5330 bool bSetBack = false;
5331 uint32 nForeGround = SCIM_RGB_COLOR (249, 249, 249);
5332 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
5333 attrs = table.get_attributes_in_current_page (i);
5334 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5335 if (ait->get_type () == SCIM_ATTR_DECORATE && ait->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
5337 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
5338 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
5340 nForeGround = ait->get_value ();
5341 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
5343 nBackGround = ait->get_value ();
5347 wcs = table.get_candidate_in_current_page (i);
5348 mbs = utf8_wcstombs (wcs);
5350 if (!_candidate_0 [i] && total_width <= scroll_0_width) {
5351 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5352 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));
5353 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5354 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_0));
5356 /* Check whether this item is the last one */
5357 if (i == item_num - 1) {
5358 if (_candidate_angle == 90 || _candidate_angle == 270)
5359 scroll_0_width = _candidate_land_width;
5361 scroll_0_width = _candidate_port_width;
5364 /* Add first item */
5366 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5367 evas_object_show (_candidate_0 [i]);
5368 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5369 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, 0, item_0_width, _item_min_height);
5370 total_width += item_0_width;
5371 _candidate_display_number++;
5374 total_width += (item_0_width + seperate_width);
5375 if (total_width <= scroll_0_width) {
5376 _seperate_0 [i] = edje_object_add (evas);
5377 edje_object_file_set (_seperate_0 [i], _candidate_edje_file.c_str (), "seperate_line");
5378 evas_object_size_hint_min_set (_seperate_0 [i], seperate_width, seperate_height);
5379 elm_table_pack (_candidate_0_table, _seperate_0 [i],
5380 total_width - item_0_width - seperate_width,
5381 line_0*(_item_min_height+line_height) + (_item_min_height - seperate_height)/2,
5382 seperate_width, seperate_height);
5383 evas_object_show (_seperate_0 [i]);
5384 evas_object_show (_candidate_0 [i]);
5385 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5386 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);
5387 _candidate_display_number++;
5389 } else if ((_candidate_angle == 0 || _candidate_angle == 180) &&
5390 (_candidate_port_line > 1 && (line_0 + 1) < _candidate_port_line)) {
5392 scroll_0_width = _candidate_scroll_0_width_min;
5393 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5394 evas_object_show (_candidate_0 [i]);
5395 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5396 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
5397 total_width = item_0_width;
5398 _candidate_display_number++;
5400 _candidate_row_items.push_back (i - nLast);
5404 _candidate_row_items.push_back (i - nLast);
5410 if (!_candidate_0 [i]) {
5411 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5412 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));
5413 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5414 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_ITEMS));
5416 if (current_width > 0 && current_width + item_0_width > _candidate_scroll_width) {
5420 _candidate_row_items.push_back (i - nLast);
5422 if (cursor_pos >= i)
5425 if (current_width == 0 && !_line_items [i]) {
5426 _line_items [i] = edje_object_add (evas);
5427 edje_object_file_set (_line_items [i], _candidate_edje_file.c_str (), "popup_line");
5428 evas_object_size_hint_min_set (_line_items [i], line_width, line_height);
5430 y = line_count*(_item_min_height+line_height);
5431 elm_table_pack (_candidate_table, _line_items [i], x, y, line_width, line_height);
5432 evas_object_show (_line_items [i]);
5434 if (current_width != 0 && !_seperate_items [i]) {
5435 _seperate_items [i] = edje_object_add (evas);
5436 edje_object_file_set (_seperate_items [i], _candidate_edje_file.c_str (), "seperate_line");
5437 evas_object_size_hint_min_set (_seperate_items [i], seperate_width, seperate_height);
5439 y = line_count*(_item_min_height+line_height) + line_height + (_item_min_height - seperate_height)/2;
5440 elm_table_pack (_candidate_table, _seperate_items [i], x, y, seperate_width, seperate_height);
5441 evas_object_show (_seperate_items [i]);
5442 current_width += seperate_width;
5445 y = line_count*(_item_min_height+line_height) + line_height;
5446 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5447 evas_object_show (_candidate_0 [i]);
5448 elm_table_pack (_candidate_table, _candidate_0 [i], x, y, item_0_width, _item_min_height);
5449 current_width += item_0_width;
5451 if (candidate_expanded == false && !bHighLight)
5454 candidate_expanded = true;
5458 for (i = 1; i < _candidate_port_line; i++) {
5459 if ((_candidate_angle == 0 || _candidate_angle == 180)) {
5460 if (_line_0 [i] == NULL) {
5461 _line_0 [i] = edje_object_add (evas);
5462 edje_object_file_set (_line_0 [i], _candidate_edje_file.c_str (), "popup_line");
5463 evas_object_size_hint_min_set (_line_0 [i], line_width, line_height);
5465 y = i * (_item_min_height + line_height) - line_height;
5466 elm_table_pack (_candidate_0_table, _line_0 [i], x, y, line_width, line_height);
5467 evas_object_show (_line_0 [i]);
5470 // Create blank line
5471 if (line_0 + 1 < _candidate_port_line && i > line_0) {
5472 int nIndex = item_num + i;
5473 nIndex = nIndex < SCIM_LOOKUP_TABLE_MAX_PAGESIZE ? nIndex : SCIM_LOOKUP_TABLE_MAX_PAGESIZE - 1;
5474 _seperate_0 [nIndex] = edje_object_add (evas);
5475 edje_object_file_set (_seperate_0 [nIndex], _candidate_edje_file.c_str (), "seperate_line");
5476 evas_object_size_hint_min_set (_seperate_0 [nIndex], seperate_width, _item_min_height);
5477 elm_table_pack (_candidate_0_table, _seperate_0 [nIndex],
5478 0, i*(_item_min_height+line_height), seperate_width, _item_min_height);
5480 } else if (_line_0 [i]) {
5481 evas_object_del (_line_0 [i]);
5486 _candidate_row_items.push_back (item_num - nLast); /* Add the number of last row */
5487 _info_manager->update_displayed_candidate_number (_candidate_display_number);
5488 _info_manager->update_candidate_item_layout (_candidate_row_items);
5489 if (more_item_count == 0) {
5490 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
5491 evas_object_hide (_more_btn);
5492 evas_object_hide (_close_btn);
5493 } else if (!_candidate_area_2_visible) {
5494 evas_object_show (_more_btn);
5495 evas_object_hide (_close_btn);
5497 evas_object_hide (_more_btn);
5498 evas_object_show (_close_btn);
5502 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
5504 int line_h = _item_min_height + _v_padding;
5505 int cursor_y = cursor_line * line_h;
5507 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
5508 } else if (cursor_y >= y + h) {
5509 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
5514 #endif /* CANDIDATE */
5517 * @brief Update candidate table slot function for PanelAgent.
5519 * @param table The lookup table for candidate.
5521 static void slot_update_candidate_table (const LookupTable &table)
5523 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5525 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5526 _info_manager->update_helper_lookup_table (table);
5530 #if ISF_BUILD_CANDIDATE_UI
5531 if (_candidate_window == NULL)
5532 ui_create_candidate_window ();
5534 if (!_candidate_window || table.get_current_page_size () < 0)
5537 if (evas_object_visible_get (_candidate_area_2)) {
5538 candidate_expanded = true;
5540 candidate_expanded = false;
5543 update_table (ISF_CANDIDATE_TABLE, table);
5544 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
5545 ui_tts_focus_rect_hide ();
5546 #endif /* CANDIDATE */
5550 * @brief Send selected candidate index.
5552 * @param selected candidate string index number.
5554 static void slot_select_candidate (int index)
5556 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5557 _info_manager->select_candidate (index);
5561 * @brief Get candidate geometry slot function for PanelAgent.
5563 * @param info The data is used to store candidate position and size.
5565 static void slot_get_candidate_geometry (struct rectinfo &info)
5572 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5576 info.height = height;
5580 #if ISF_BUILD_CANDIDATE_UI
5581 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5582 /* Get candidate window position */
5583 /*ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);*/
5584 /* Get exact candidate window size */
5586 evas_object_geometry_get (_candidate_window, &x2, &y2, &width, &height);*/
5590 width = _candidate_width;
5591 height = _candidate_height;
5593 #endif /* CANDIDATE */
5598 info.height = height;
5600 LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5601 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5602 << " width:" << info.width << " height:" << info.height << "\n";
5606 * @brief Get input panel geometry slot function for PanelAgent.
5608 * @param info The data is used to store input panel position and size.
5610 static void slot_get_input_panel_geometry (struct rectinfo &info)
5612 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
5617 #if ISF_BUILD_CANDIDATE_UI
5618 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5619 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5620 info.width = _candidate_width;
5621 info.height = _candidate_height;
5623 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5624 info.width = _soft_candidate_width;
5625 info.height = _soft_candidate_height;
5627 int angle = efl_get_app_window_angle ();
5628 if (angle == 90 || angle == 270)
5629 info.pos_y = _screen_width - info.height;
5631 info.pos_y = _screen_height - info.height;
5633 info = get_ise_geometry ();
5634 if (_ise_state != WINDOW_STATE_SHOW) {
5638 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5639 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5640 int height = ui_candidate_get_valid_height ();
5642 if ((_candidate_height - height) > _ise_height) {
5643 info.pos_y = info.pos_y + info.height - _candidate_height;
5644 info.height = _candidate_height;
5646 info.pos_y -= height;
5647 info.height += height;
5652 #endif /* CANDIDATE */
5655 LOGD ("%d %d %d %d", info.pos_x, info.pos_y, info.width, info.height);
5656 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5657 << " width:" << info.width << " height:" << info.height << "\n";
5661 * @brief Get the recent input panel geometry slot function for PanelAgent.
5663 * @param angle the rotation angle of application window.
5664 * @param info The data is used to store input panel position and size.
5666 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info)
5668 LOGD ("slot_get_recent_ise_geometry");
5670 /* If we have geometry reported by ISE, use the geometry information */
5675 if (angle == 0 || angle == 180) {
5676 if (_portrait_recent_ise_geometry.valid) {
5677 info = _portrait_recent_ise_geometry.geometry;
5682 if (_landscape_recent_ise_geometry.valid) {
5683 info = _landscape_recent_ise_geometry.geometry;
5694 static bool slot_check_privilege_by_sockfd (int client_id, String privilege)
5696 PrivilegeChecker privilegeChecker (client_id);
5698 bool priv_ret = privilegeChecker.checkPrivilege (privilege.c_str ());
5700 if (priv_ret == false)
5701 LOGW ("Failed to check privilege (%s)", privilege.c_str ());
5703 LOGD ("Succeeded to check privilege (%s)", privilege.c_str ());
5709 * @brief Set active ISE slot function for PanelAgent.
5711 * @param uuid The active ISE's uuid.
5712 * @param changeDefault The flag for changing default ISE.
5714 static void slot_set_active_ise (const String &uuid, bool changeDefault)
5716 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << uuid << ")\n";
5718 bool invalid = false;
5720 #ifdef HAVE_PKGMGR_INFO
5721 /* When changing the active (default) keyboard, initialize ime_info DB if appid is invalid.
5722 This may be necessary if IME packages are changed while panel process is terminated. */
5723 pkgmgrinfo_appinfo_h handle = NULL;
5724 /* Try to get in global packages */
5725 int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
5726 if (ret != PMINFO_R_OK) {
5727 LOGW ("appid \"%s\" is invalid.", uuid.c_str ());
5728 /* This might happen if IME is uninstalled while the panel process is inactive.
5729 The variable uuid would be invalid, so set_active_ise() would return false. */
5734 pkgmgrinfo_appinfo_destroy_appinfo (handle);
5738 _initialize_ime_info ();
5739 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5741 else if (set_active_ise (uuid, _soft_keyboard_launched) == false) {
5742 if (_initial_ise_uuid.compare (uuid))
5743 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5748 * @brief Get all ISEs list slot function for PanelAgent.
5750 * @param list The list is used to store all ISEs.
5752 * @return true if this operation is successful, otherwise return false.
5754 static bool slot_get_ise_list (std::vector<String> &list)
5756 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5758 bool result = false;
5760 std::vector<String> uuids;
5761 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5762 uuids.push_back(iter->appid);
5764 if (_ime_info.size () > 0) {
5769 result = update_ise_list (list);
5776 * @brief Get all Helper ISE information from ime_info DB.
5778 * @param info This is used to store all Helper ISE information.
5780 * @return true if this operation is successful, otherwise return false.
5782 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info)
5784 bool result = false;
5785 String active_ime_appid;
5787 info.appid.clear ();
5788 info.label.clear ();
5789 info.is_enabled.clear ();
5790 info.is_preinstalled.clear ();
5791 info.has_option.clear ();
5793 if (_ime_info.size() == 0)
5794 isf_pkg_select_all_ime_info_db (_ime_info);
5796 //active_ime_appid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5797 if (_info_manager) {
5798 active_ime_appid = _info_manager->get_current_helper_uuid ();
5801 if (_ime_info.size () > 0) {
5802 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
5803 if (iter->mode == TOOLBAR_HELPER_MODE) {
5804 info.appid.push_back (iter->appid);
5805 info.label.push_back (iter->label);
5806 info.is_enabled.push_back (iter->is_enabled);
5807 info.is_preinstalled.push_back (iter->is_preinstalled);
5808 info.has_option.push_back (static_cast<uint32>(iter->has_option));
5818 * @brief Update "has_option" column of ime_info DB by Application ID
5820 * @param[in] appid Application ID of IME to enable or disable
5821 * @param[in] has_option @c true to have IME option(setting), otherwise @c false
5823 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option)
5825 if (appid.length() == 0) {
5826 LOGW ("Invalid appid");
5830 if (_ime_info.size() == 0)
5831 isf_pkg_select_all_ime_info_db(_ime_info);
5833 if (isf_db_update_has_option_by_appid(appid.c_str(), has_option)) { // Update ime_info DB
5834 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5835 if (appid == _ime_info[i].appid) {
5836 _ime_info[i].has_option = static_cast<uint32>(has_option); // Update global variable
5843 * @brief Update "is_enable" column of ime_info DB by Application ID
5845 * @param[in] appid Application ID of IME to enable or disable
5846 * @param[in] is_enabled @c true to enable the IME, otherwise @c false
5848 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled)
5850 if (appid.length() == 0) {
5851 LOGW ("Invalid appid");
5855 if (_ime_info.size() == 0)
5856 isf_pkg_select_all_ime_info_db(_ime_info);
5858 if (isf_db_update_is_enabled_by_appid(appid.c_str(), is_enabled)) { // Update ime_info DB
5859 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5860 if (appid == _ime_info[i].appid) {
5861 _ime_info[i].is_enabled = static_cast<uint32>(is_enabled); // Update global variable
5867 #ifdef HAVE_PKGMGR_INFO
5869 * @brief Finds appid with specific category
5871 * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative
5873 static int _find_appid_from_category (const pkgmgrinfo_appinfo_h handle, void *user_data)
5876 char **result = static_cast<char **>(user_data);
5881 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
5882 if (ret == PMINFO_R_OK) {
5883 *result = strdup (appid);
5886 LOGW ("pkgmgrinfo_appinfo_get_appid failed!");
5890 LOGW ("user_data is null!");
5893 return -1; // This callback is no longer called.
5898 * @brief Requests to open the installed IME list application.
5900 static void slot_show_helper_ise_list (void)
5902 // Launch IME List application; e.g., org.tizen.inputmethod-setting-list
5903 char *app_id = NULL;
5904 #ifdef HAVE_PKGMGR_INFO
5905 pkgmgrinfo_appinfo_filter_h handle;
5908 if (ime_list_app.length() < 1) {
5909 ret = pkgmgrinfo_appinfo_filter_create (&handle);
5910 if (ret == PMINFO_R_OK) {
5911 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-list");
5912 if (ret == PMINFO_R_OK) {
5913 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
5915 pkgmgrinfo_appinfo_filter_destroy (handle);
5918 ime_list_app = String (app_id);
5922 app_id = strdup (ime_list_app.c_str());
5926 app_control_launch (app_id);
5930 SECURE_LOGW ("AppID with http://tizen.org/category/ime-list category is not available.");
5935 * @brief Requests to open the installed IME selector application.
5937 static void slot_show_helper_ise_selector (void)
5939 // Launch IME Selector application; e.g., org.tizen.inputmethod-setting-selector
5940 char *app_id = NULL;
5941 #ifdef HAVE_PKGMGR_INFO
5942 pkgmgrinfo_appinfo_filter_h handle;
5945 if (ime_selector_app.length() < 1) {
5946 ret = pkgmgrinfo_appinfo_filter_create(&handle);
5947 if (ret == PMINFO_R_OK) {
5948 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
5949 if (ret == PMINFO_R_OK) {
5950 pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, _find_appid_from_category, &app_id);
5952 pkgmgrinfo_appinfo_filter_destroy(handle);
5955 ime_selector_app = String(app_id);
5959 app_id = strdup(ime_selector_app.c_str());
5963 app_control_launch (app_id);
5967 SECURE_LOGW ("AppID with http://tizen.org/category/ime-selector category is not available.");
5971 static bool slot_is_helper_ise_enabled (String appid, int &enabled)
5973 bool is_enabled = false;
5975 if (appid.length() == 0) {
5976 LOGW ("Invalid appid.");
5980 if (_ime_info.size() == 0)
5981 isf_pkg_select_all_ime_info_db(_ime_info);
5983 if (isf_db_select_is_enabled_by_appid(appid.c_str(), &is_enabled)) {
5984 enabled = static_cast<int>(is_enabled);
5993 * @brief Get the ISE's information.
5995 * @param uuid The ISE's uuid.
5996 * @param name The ISE's name.
5997 * @param language The ISE's language.
5998 * @param type The ISE's type.
5999 * @param option The ISE's option.
6001 * @return true if this operation is successful, otherwise return false.
6003 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name)
6005 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6007 if (uuid.length () > 0) {
6008 // update all ISE names according to the display languages
6009 // sometimes get_ise_information is called before vconf display language changed callback is called.
6010 update_ise_locale ();
6012 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6013 if (uuid == _ime_info[i].appid) {
6014 name = _ime_info[i].label;
6015 language = _ime_info[i].languages;
6016 type = _ime_info[i].mode;
6017 option = _ime_info[i].options;
6018 module_name = _ime_info[i].module_name;
6024 std::cerr << __func__ << " is failed!!!\n";
6029 * @brief Get keyboard ISEs list slot function for PanelAgent.
6031 * @param name_list The list is used to store keyboard ISEs.
6033 * @return true if this operation is successful, otherwise return false.
6035 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list)
6037 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6039 isf_load_ise_information (ALL_ISE, _config);
6041 std::vector<String> lang_list, uuid_list;
6042 isf_get_all_languages (lang_list);
6043 isf_get_keyboard_ises_in_languages (lang_list, uuid_list, name_list, false);
6045 _info_manager->update_ise_list (uuid_list);
6050 * @brief Get enable languages list slot function for PanelAgent.
6052 * @param list The list is used to store languages.
6054 static void slot_get_language_list (std::vector<String> &list)
6056 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6059 MapStringVectorSizeT::iterator iter = _groups.begin ();
6061 for (; iter != _groups.end (); iter++) {
6062 lang_name = scim_get_language_name (iter->first);
6063 list.push_back (lang_name);
6068 * @brief Get all languages list slot function for PanelAgent.
6070 * @param lang The list is used to store languages.
6072 static void slot_get_all_language (std::vector<String> &lang)
6074 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6076 isf_get_all_languages (lang);
6080 * @brief Get specific ISE language list slot function for PanelAgent.
6082 * @param name The ISE name.
6083 * @param list The list is used to store ISE languages.
6085 static void slot_get_ise_language (char *name, std::vector<String> &list)
6087 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6092 std::vector<String> list_tmp;
6094 for (unsigned int i = 0; i < _ime_info.size(); i++) {
6095 if (!strcmp (_ime_info[i].label.c_str (), name)) {
6096 scim_split_string_list (list_tmp, _ime_info[i].languages, ',');
6097 for (i = 0; i < list_tmp.size (); i++)
6098 list.push_back (scim_get_language_name (list_tmp[i]));
6105 * @brief Get ISE information slot function for PanelAgent.
6107 * @param uuid The ISE uuid.
6108 * @param info The variable is used to store ISE information.
6110 * @return true if this operation is successful, otherwise return false.
6112 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info)
6114 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6116 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6117 if (!uuid.compare (_ime_info[i].appid)) {
6118 info.uuid = _ime_info[i].appid;
6119 info.name = _ime_info[i].label;
6120 info.icon = _ime_info[i].iconpath;
6121 info.lang = _ime_info[i].languages;
6122 info.option = _ime_info[i].options;
6123 info.type = _ime_info[i].mode;
6132 * @brief Set keyboard ISE slot function for PanelAgent.
6134 * @param uuid The variable is ISE uuid.
6136 static void slot_set_keyboard_ise (const String &uuid)
6138 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << uuid << "\n";
6140 std::vector<String> uuids;
6141 std::vector<ImeInfoDB>::iterator iter;
6142 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
6143 uuids.push_back(iter->appid);
6146 if (uuid.length () <= 0 || std::find (uuids.begin (), uuids.end (), uuid) == uuids.end ())
6149 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6150 if (_ime_info[get_ise_index (default_uuid)].mode == TOOLBAR_KEYBOARD_MODE)
6153 uint32 ise_option = 0;
6154 String ise_uuid, ise_name;
6155 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
6156 if (ise_uuid == uuid)
6159 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
6160 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
6164 _info_manager->change_factory (uuid);
6168 * @brief Get current keyboard ISE name and uuid slot function for PanelAgent.
6170 * @param ise_name The variable is used to store ISE name.
6171 * @param ise_uuid The variable is used to store ISE uuid.
6173 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid)
6175 uint32 ise_option = 0;
6176 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
6178 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << ise_uuid << "\n";
6182 * @brief Accept connection slot function for PanelAgent.
6184 * @param fd The file descriptor to connect.
6186 static void slot_accept_connection (int fd)
6188 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6191 get_input_window ();
6196 * @brief Close connection slot function for PanelAgent.
6198 * @param fd The file descriptor to connect.
6200 static void slot_close_connection (int fd)
6202 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6206 * @brief Exit panel process slot function for PanelAgent.
6208 static void slot_exit (void)
6210 std::cerr << __FUNCTION__ << "...\n";
6211 ISF_SAVE_LOG ("exit");
6213 #if ISF_BUILD_CANDIDATE_UI
6216 ecore_main_loop_quit ();
6217 #endif /* CANDIDATE */
6220 static void delete_ise_check_pid_alive_timer(void)
6222 LOGD("deleting ise_check_alive_timer");
6223 if (_ise_check_pid_alive_timer) {
6224 ecore_timer_del(_ise_check_pid_alive_timer);
6225 _ise_check_pid_alive_timer = NULL;
6229 static Eina_Bool ise_check_pid_alive_timer(void *data)
6231 Eina_Bool ret = ECORE_CALLBACK_RENEW;
6232 Eina_Bool retry = EINA_FALSE;
6234 int status = aul_app_get_status (_ise_check_pid_alive_uuid.c_str ());
6235 LOGD ("STATUS : %d", status);
6236 if (status >= STATUS_LAUNCHING) {
6237 /* If the status is not one of STATUS_LAUNCHING, STATUS_VISIBLE, STATUS_BG */
6238 if (status >= STATUS_DYING) {
6239 LOGE ("aul_app_get_status reports %d", status);
6244 /* Status query not successful, the ISE could have failed launching */
6245 LOGE ("aul_app_get_status failed. %d", status);
6250 _soft_keyboard_launched = false;
6251 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
6252 /* The start_helper() function below will going to call slot_run_helper,
6253 which will going to assign a new timer handle to the _ise_check_pid_alive_timer variable.
6255 LOGW ("The previous attempt to launch %s seems to be failed, restarting",
6256 _ise_check_pid_alive_uuid.c_str ());
6257 if (_info_manager->start_helper (uuid))
6258 _soft_keyboard_launched = true;
6259 ret = ECORE_CALLBACK_CANCEL;
6265 static void slot_register_helper(int id, const HelperInfo& info)
6267 LOGD ("app id : %s", info.uuid.c_str ());
6268 /* Do we need to check whether the pid of this helper is the one we are watching? */
6269 if (info.uuid.compare(_ise_check_pid_alive_uuid) == 0) {
6270 delete_ise_check_pid_alive_timer();
6274 static void slot_register_helper_properties (int id, const PropertyList &props)
6276 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6278 /* WMSYNC, #2 Receiving X window ID from ISE */
6279 /* FIXME : We should add an API to set window id of ISE */
6280 Property prop = props[0];
6281 if (prop.get_label ().compare ("XID") == 0) {
6282 Ecore_X_Window xwindow = atoi (prop.get_key ().c_str ());
6283 _ise_window = xwindow;
6284 LOGD ("ISE XID : %x", _ise_window);
6286 /* Just in case for the helper sent this message later than show_ise request */
6287 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
6288 efl_set_transient_for_app_window (_ise_window);
6291 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_ISE_WINDOW");
6292 if (atom && _control_window && _ise_window) {
6293 ecore_x_window_prop_xid_set (_control_window, atom, ECORE_X_ATOM_WINDOW, &_ise_window, 1);
6295 #ifdef HAVE_NOTIFICATION
6296 delete_notification (&ise_selector_module_noti);
6302 #if ENABLE_REMOTE_INPUT
6303 static void slot_send_remote_input_message (const String &msg, bool len)
6305 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6307 String con = msg.c_str ();
6308 ISE_MESSAGE message = CISEMessageSerializer::deserialize(con);
6310 if (remote_input_impl == NULL) {
6311 remote_input_impl = Remote_Input::get_instance();
6314 if (remote_input_impl)
6315 remote_input_impl->handle_websocket_message(message);
6318 static void slot_recv_remote_surrounding_text (int cursor, const String &text)
6320 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6322 if (remote_input_impl == NULL) {
6323 remote_input_impl = Remote_Input::get_instance();
6326 if (remote_input_impl)
6327 remote_input_impl->handle_recv_panel_message(3, text.c_str (), cursor);
6331 static void slot_show_ise (void)
6333 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6335 /* If the current toolbar mode is not HELPER_MODE, do not proceed */
6336 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
6337 LOGD ("Current toolbar mode should be TOOLBAR_HELPER_MODE but is %d, returning",
6338 _info_manager->get_current_toolbar_mode ());
6342 LOGD ("slot_show_ise ()");
6344 delete_ise_hide_timer ();
6346 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
6347 // Unset conformant area
6348 Ecore_X_Window current_app_window = efl_get_app_window ();
6349 if (_app_window != current_app_window) {
6350 struct rectinfo info = {0, 0, 0, 0};
6351 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
6352 set_keyboard_geometry_atom_info (_app_window, info);
6353 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6354 LOGD ("Conformant reset for window %x", _app_window);
6355 _app_window = current_app_window;
6357 /* If the target window has changed but our ISE is still in visible state,
6358 update the keyboard geometry information */
6359 if (_ise_state == WINDOW_STATE_SHOW) {
6360 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6364 /* If the candidate was already in SHOW state, respect the current angle */
6365 if (_candidate_state != WINDOW_STATE_SHOW) {
6366 /* FIXME : Need to check if candidate_angle and window_angle should be left as separated */
6367 _candidate_angle = efl_get_app_window_angle ();
6369 /* If the ise was already in SHOW state, respect the current angle */
6370 if (_ise_state != WINDOW_STATE_SHOW) {
6371 _ise_angle = efl_get_app_window_angle ();
6374 ecore_x_event_mask_set (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
6375 efl_set_transient_for_app_window (_ise_window);
6377 /* Make clipboard window to have transient_for information on ISE window,
6378 so that the clipboard window will always be above ISE window */
6379 Ecore_X_Window clipboard_window = efl_get_clipboard_window ();
6380 if (_ise_window && clipboard_window) {
6381 ecore_x_icccm_transient_for_set (clipboard_window, _ise_window);
6384 /* If our ISE was already in SHOW state, skip state transition to WILL_SHOW */
6385 if (_ise_state != WINDOW_STATE_SHOW) {
6386 _ise_state = WINDOW_STATE_WILL_SHOW;
6390 #if ISF_BUILD_CANDIDATE_UI
6391 _candidate_angle = 0;
6392 #endif /* CANDIDATE */
6393 _ise_state = WINDOW_STATE_SHOW;
6395 #ifdef HAVE_NOTIFICATION
6396 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6397 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6398 show_ime_selector_notification ();
6405 static void slot_hide_ise (void)
6407 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6409 LOGD ("slot_hide_ise ()");
6411 if (!_ise_hide_timer)
6415 static void slot_will_hide_ack (void)
6417 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6419 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
6420 // WILL_HIDE_REQUEST_DONE Ack to WM
6421 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6422 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
6423 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)",
6424 root_window, _control_window);
6425 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6426 LOGD ("calling ui_candidate_hide (true, false)");
6427 ui_candidate_hide (true, false);
6430 /* WILL_HIDE_ACK means that the application finished redrawing the autoscroll area,
6431 now hide the candidate window right away if it is also in WILL_HIDE state */
6432 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6433 candidate_window_hide ();
6436 if (_off_prepare_done_timer) {
6437 ecore_timer_del (_off_prepare_done_timer);
6438 _off_prepare_done_timer = NULL;
6443 static void slot_candidate_will_hide_ack (void)
6445 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6447 LOGD ("candidate_will_hide_ack");
6448 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6449 candidate_window_hide ();
6454 static void slot_set_keyboard_mode (int mode)
6456 LOGD ("slot_set_keyboard_mode called (TOOLBAR_MODE : %d)", mode);
6458 change_keyboard_mode ((TOOLBAR_MODE_T)mode);
6461 static void slot_get_ise_state (int &state)
6463 if (_ise_state == WINDOW_STATE_SHOW ||
6464 ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (_candidate_state == WINDOW_STATE_SHOW))) {
6465 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6467 /* Currently we don't have WILL_HIDE / HIDE state distinction in Ecore_IMF */
6468 switch (_ise_state) {
6469 case WINDOW_STATE_SHOW :
6470 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6472 case WINDOW_STATE_WILL_SHOW :
6473 state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
6475 case WINDOW_STATE_WILL_HIDE :
6476 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6478 case WINDOW_STATE_HIDE :
6479 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6482 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6485 LOGD ("state = %d", state);
6486 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " state = " << state << "\n";
6489 static void slot_start_default_ise (void)
6491 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6493 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE)) {
6494 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6495 int pid = aul_app_get_pid (uuid.c_str ());
6497 if (STATUS_DYING == aul_app_get_status (uuid.c_str ()))
6500 if (_launch_ise_on_request && !_soft_keyboard_launched && pid < 0) {
6501 LOGD ("Start helper (%s)", uuid.c_str ());
6502 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
6504 if (_info_manager->start_helper (uuid))
6505 _soft_keyboard_launched = true;
6507 LOGW ("Failed to start helper (%s)", uuid.c_str ());
6512 static void slot_stop_default_ise (bool is_exist)
6514 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6517 if (_launch_ise_on_request && _auto_destroy_ise && _soft_keyboard_launched) {
6518 String uuid = _info_manager->get_current_helper_uuid ();
6520 if (uuid.length () > 0) {
6521 _info_manager->hide_helper (uuid);
6522 _info_manager->stop_helper (uuid);
6523 _soft_keyboard_launched = false;
6524 LOGD ("stop helper (%s)", uuid.c_str ());
6528 if (_soft_keyboard_launched)
6529 _soft_keyboard_launched = false;
6533 static void launch_helper (const char* exec, const char *name, const char *appid, const char *config, const char *display)
6539 if (pid < 0) return;
6542 const char *argv [] = { exec,
6545 "--display", display,
6546 const_cast<char*> (name),
6547 const_cast<char*> (appid),
6550 SCIM_DEBUG_MAIN (2) << " Call scim-helper-launcher.\n";
6551 ISF_SAVE_LOG ("Exec scim_helper_launcher(%s %s)", name, appid);
6553 unsetenv ("ELM_THEME");
6554 unsetenv ("ELM_SCALE");
6557 LOGD ("launch execpath : %s", exec);
6558 execv (exec, const_cast<char **>(argv));
6559 #if ISF_BUILD_CANDIDATE_UI
6562 ecore_main_loop_quit ();
6563 #endif /* CANDIDATE */
6567 static bool app_control_launch (const char *app_id)
6569 app_control_h app_control;
6572 ret = app_control_create (&app_control);
6573 if (ret != APP_CONTROL_ERROR_NONE) {
6574 LOGW ("app_control_create returned %08x", ret);
6578 ret = app_control_set_operation (app_control, APP_CONTROL_OPERATION_DEFAULT);
6579 if (ret != APP_CONTROL_ERROR_NONE) {
6580 LOGW ("app_control_set_operation returned %08x", ret);
6581 app_control_destroy (app_control);
6585 ret = app_control_set_app_id (app_control, app_id);
6586 if (ret != APP_CONTROL_ERROR_NONE) {
6587 LOGW ("app_control_set_app_id returned %08x", ret);
6588 app_control_destroy (app_control);
6594 if (tries != 0) usleep(1000000); /* If we are retrying to launch, pause for a while */
6595 ret = app_control_send_launch_request(app_control, NULL, NULL);
6596 LOGW ("app_control_send_launch_request returned %08x, app_id=%s", ret, app_id);
6597 } while (ret != APP_CONTROL_ERROR_NONE && (++tries) < 3);
6599 app_control_destroy (app_control);
6601 if (ret != APP_CONTROL_ERROR_NONE) {
6602 LOGW ("Failed to launch IME (%s)", app_id);
6604 LOGD ("Succeeded to launch IME (%s)", app_id);
6607 return (ret == APP_CONTROL_ERROR_NONE);
6610 static void add_ise_check_pid_alive_timer(const String &uuid) {
6611 delete_ise_check_pid_alive_timer ();
6612 LOGD ("Register check_alive timer for uuid : %s", uuid.c_str ());
6613 _ise_check_pid_alive_uuid = uuid;
6614 _ise_check_pid_alive_timer = ecore_timer_add (_ise_check_pid_alive_time,
6615 ise_check_pid_alive_timer, NULL);
6618 static void slot_run_helper (const String &uuid, const String &config, const String &display)
6620 ISF_SAVE_LOG ("time:%ld pid:%d %s %s uuid(%s)",
6621 time (0), getpid (), __FILE__, __func__, uuid.c_str ());
6623 String scim_helper_path;
6625 delete_ise_check_pid_alive_timer ();
6627 #ifdef HAVE_PKGMGR_INFO
6628 char *execpath = NULL;
6630 pkgmgrinfo_appinfo_h appinfo_handle;
6632 /* get app info handle */
6633 /* Try to get in global packages */
6634 ret = pkgmgr_get_appinfo (uuid.c_str (), &appinfo_handle);
6635 if (ret != PMINFO_R_OK) {
6636 LOGE ("pkgmgr_get_appinfo failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6637 add_ise_check_pid_alive_timer (uuid);
6642 ret = pkgmgrinfo_appinfo_get_exec (appinfo_handle, &execpath);
6643 if (ret != PMINFO_R_OK) {
6644 LOGE ("pkgmgrinfo_appinfo_get_exec failed. appid : %s, ret : %d ", uuid.c_str (), ret);
6645 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6646 add_ise_check_pid_alive_timer (uuid);
6650 LOGD ("exec path : %s %d", execpath, _ime_info.size ());
6651 scim_helper_path = String (execpath);
6653 if (appinfo_handle) {
6654 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6655 appinfo_handle = NULL;
6658 scim_helper_path = String (SCIM_HELPER_LAUNCHER_PROGRAM);
6661 for (size_t i = 0; i < _ime_info.size (); ++i) {
6662 if (_ime_info[i].appid == uuid && _ime_info[i].module_name.length ()) {
6663 if (scim_helper_path != String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
6664 /* Check if IME with the same AppID is alive */
6665 int status_ret = aul_app_get_status (uuid.c_str ());
6666 if (status_ret >= STATUS_LAUNCHING) {
6667 /* Request to terminate IME */
6668 int ime_pid = aul_app_get_pid (uuid.c_str ());
6669 status_ret = aul_terminate_pid (ime_pid);
6670 if (status_ret < AUL_R_OK) {
6671 LOGE ("aul_terminate_pid(%d) failed: %d", ime_pid, status_ret);
6674 LOGD ("Requested to terminate IME(%s)", uuid.c_str ());
6678 /* execute type IME */
6679 LOGD ("Try to launch IME (%s)", uuid.c_str ());
6680 app_control_launch (uuid.c_str ());
6682 /* ISE check alive only works for AUL based IMEs */
6683 add_ise_check_pid_alive_timer (uuid);
6686 /* shared object (so) type IME */
6687 launch_helper (scim_helper_path.c_str(), _ime_info[i].module_name.c_str (), uuid.c_str (), config.c_str (), display.c_str ());
6694 SCIM_DEBUG_MAIN (2) << " exit run_helper ().\n";
6697 static bool slot_launch_option_application (String ime_appid)
6699 String ime_setting_app = isf_pkg_get_setting_app (ime_appid);
6701 LOGD ("IME appid : %s, IME setting app id : %s", ime_appid.c_str (), ime_setting_app.c_str ());
6703 if (ime_setting_app.length () > 0) {
6704 app_control_launch (ime_setting_app.c_str ());
6711 //////////////////////////////////////////////////////////////////////
6712 // End of PanelAgent-Functions
6713 //////////////////////////////////////////////////////////////////////
6717 * @brief Callback function for abnormal signal.
6719 * @param sig The signal.
6721 static void signalhandler (int sig)
6723 std::cerr << __FUNCTION__ << " Signal=" << sig << "\n";
6724 ISF_SAVE_LOG ("Signal=%d", sig);
6726 #if ISF_BUILD_CANDIDATE_UI
6729 ecore_main_loop_quit ();
6730 #endif /* CANDIDATE */
6734 static void update_ise_locale (const char *language)
6739 strLang = String (language);
6742 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
6744 if (_locale_string.compare(lang_str) == 0) {
6749 strLang = String (lang_str);
6755 LOGD ("update all ISE names according to display language : %s", strLang.c_str ());
6756 set_language_and_locale (strLang.c_str ());
6758 bool need_to_init_db = false;
6759 #ifdef HAVE_PKGMGR_INFO
6763 pkgmgrinfo_appinfo_h handle = NULL;
6765 /* Read DB from ime_info table */
6766 isf_load_ise_information(ALL_ISE, _config);
6768 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6769 ret = pkgmgr_get_appinfo (_ime_info[i].appid.c_str(), &handle);
6771 if (ret == PMINFO_R_OK) {
6772 ret = pkgmgrinfo_appinfo_is_category_exist(handle, "http://tizen.org/category/ime", &exist);
6773 if (ret == PMINFO_R_OK && exist) {
6774 ret = pkgmgrinfo_appinfo_get_label(handle, &label);
6775 if (ret == PMINFO_R_OK && label) {
6776 _ime_info[i].label = String(label);
6777 /* Update label column in ime_info db table */
6778 if (isf_db_update_label_by_appid(_ime_info[i].appid.c_str(), label)) {
6779 _ime_info[i].label = label;
6784 // The appid is invalid.. Need to initialize ime_info DB.
6785 need_to_init_db = true;
6787 pkgmgrinfo_appinfo_destroy_appinfo(handle);
6790 // The appid is invalid.. Need to initialize ime_info DB.
6791 need_to_init_db = true;
6796 if (need_to_init_db) {
6797 _initialize_ime_info ();
6800 if (strLang.length () > 0) {
6801 isf_db_update_disp_lang (strLang.c_str ());
6802 _locale_string = strLang;
6807 * @brief Set language and locale.
6811 static void set_language_and_locale (const char *lang_str)
6813 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6818 LOGD ("language : %s", lang_str);
6819 #if ISF_BUILD_CANDIDATE_UI
6820 elm_language_set (lang_str);
6821 #endif /* CANDIDATE */
6823 snprintf (language, sizeof (language), "%s:en_US:en_GB:en", lang_str);
6824 setenv ("LANGUAGE", language, 1);
6825 setenv ("LANG", lang_str, 1);
6826 setlocale (LC_MESSAGES, lang_str);
6828 setenv ("LANG", "en_US.utf8", 1);
6829 setlocale (LC_MESSAGES, "en_US.utf8");
6834 * @brief Callback function for display language change.
6836 * @param key The key node.
6837 * @param data The data to pass to this callback.
6841 static void display_language_changed_cb (keynode_t *key, void* data)
6843 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6845 char *lang_str = vconf_keynode_get_str (key);
6846 LOGD ("lang : %s", lang_str);
6847 set_language_and_locale (lang_str);
6849 /* Update all ISE names according to display language */
6850 update_ise_locale ();
6852 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
6853 unsigned int ise_idx = get_ise_index (default_uuid);
6855 if (ise_idx < _ime_info.size ()) {
6856 String default_name = _ime_info[ise_idx].label;
6857 _info_manager->set_current_ise_name (default_name);
6863 * @brief Callback function for keyboard mode change.
6865 * @param key The key node.
6866 * @param data The data to pass to this callback.
6870 static void keyboard_mode_changed_cb (keynode_t *key, void* data)
6872 bool val = vconf_keynode_get_bool (key);
6875 _info_manager->reset_keyboard_ise ();
6876 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6877 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6883 * @brief Change keyboard mode.
6885 * @param mode The keyboard mode.
6889 static void change_keyboard_mode (TOOLBAR_MODE_T mode)
6891 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6894 bool _support_hw_keyboard_mode = false;
6896 unsigned int val = 0;
6900 int input_detect = false;
6903 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6904 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6905 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
6907 if (mode == TOOLBAR_KEYBOARD_MODE && _support_hw_keyboard_mode) {
6908 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6909 LOGD ("HARDWARE_KEYBOARD_MODE return");
6913 LOGD ("HARDWARE KEYBOARD MODE");
6914 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 1);
6917 if (_ime_info[get_ise_index(default_uuid)].mode == TOOLBAR_HELPER_MODE) {
6918 /* Get the keyboard ISE */
6919 isf_get_keyboard_ise (_config, uuid, name, option);
6920 if (option & SCIM_IME_NOT_SUPPORT_HARDWARE_KEYBOARD) {
6921 uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
6922 std::cerr << __FUNCTION__ << ": Keyboard ISE (" << name << ") can not support hardware keyboard!!!\n";
6924 /* Try to find reasonable keyboard ISE according to helper ISE language */
6925 if (uuid == String (SCIM_COMPOSE_KEY_FACTORY_UUID)) {
6926 String helper_language = _ime_info[get_ise_index(default_uuid)].languages;
6927 if (helper_language.length () > 0) {
6928 std::vector<String> ise_langs;
6929 scim_split_string_list (ise_langs, helper_language);
6930 for (size_t i = 0; i < _groups[ise_langs[0]].size (); ++i) {
6931 int j = _groups[ise_langs[0]][i];
6932 if (_ime_info[j].appid != uuid && _ime_info[j].mode == TOOLBAR_KEYBOARD_MODE) {
6933 uuid = _ime_info[j].appid;
6941 uuid = default_uuid;
6943 #if ISF_BUILD_CANDIDATE_UI
6944 _soft_candidate_width = 0;
6945 _soft_candidate_height = 0;
6946 #endif /* CANDIDATE */
6947 _ise_state = WINDOW_STATE_HIDE;
6948 _info_manager->set_current_toolbar_mode (TOOLBAR_KEYBOARD_MODE);
6949 _info_manager->hide_helper (helper_uuid);
6951 /* Check whether stop soft keyboard */
6952 if (_focus_in && (_ime_info[get_ise_index (helper_uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
6953 /* If focus in and soft keyboard can support hardware key event, then don't stop it */
6955 } else if (_launch_ise_on_request && _soft_keyboard_launched) {
6956 _info_manager->stop_helper (helper_uuid);
6957 _soft_keyboard_launched = false;
6960 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6963 #ifdef HAVE_NOTIFICATION
6965 notification_status_message_post (_("Input detected from hardware keyboard"));
6967 /* Read configuations for notification app (isf-kbd-mode-changer) */
6968 String kbd_mode_changer = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_KBD_MODE_CHANGER_PROGRAM), String (""));
6969 hwkbd_module_noti.launch_app = kbd_mode_changer;
6970 LOGD ("Create kbd_mode_changer notification with : %s", kbd_mode_changer.c_str ());
6971 create_notification (&hwkbd_module_noti);
6976 vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect);
6978 if (!input_detect) {
6979 if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 1) != 0)
6980 LOGW ("Failed to set vconf key");
6982 LOGD ("Succeeded to set vconf key");
6985 } else if (mode == TOOLBAR_HELPER_MODE) {
6986 LOGD ("SOFTWARE KEYBOARD MODE");
6987 /* When switching back to S/W keyboard mode, let's hide candidate window first */
6988 #if ISF_BUILD_CANDIDATE_UI
6989 LOGD ("calling ui_candidate_hide (true, true, true)");
6990 ui_candidate_hide (true, true, true);
6991 #endif /* CANDIDATE */
6992 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
6994 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6995 uuid = helper_uuid.length () > 0 ? helper_uuid : _initial_ise_uuid;
6996 if (_launch_ise_on_request) {
6997 if (set_active_ise (uuid, false) == false) {
6998 if (_initial_ise_uuid.compare(uuid))
6999 set_active_ise (_initial_ise_uuid, false);
7003 if (set_active_ise (uuid, true) == false) {
7004 if (_initial_ise_uuid.compare(uuid)) {
7005 LOGD ("Trying to launch initial IME (%s)", _initial_ise_uuid.c_str ());
7006 set_active_ise (_initial_ise_uuid, true);
7012 #ifdef HAVE_NOTIFICATION
7013 delete_notification (&hwkbd_module_noti);
7017 vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect);
7020 if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0) != 0)
7021 LOGW ("Failed to set vconf key");
7023 LOGD ("Succeeded to set vconf key");
7030 #ifdef HAVE_BLUETOOTH
7032 * @brief Callback function for the connection state of Bluetooth Keyboard
7034 * @param result The result of changing the connection state
7035 * @param connected The state to be changed. true means connected state, Otherwise, false.
7036 * @param remote_address The remote address
7037 * @param user_data The user data passed from the callback registration function
7041 static void _bt_cb_hid_state_changed (int result, bool connected, const char *remote_address, void *user_data)
7043 if (connected == false) {
7044 LOGD ("Bluetooth keyboard disconnected");
7045 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
7046 change_keyboard_mode (TOOLBAR_HELPER_MODE);
7052 #ifdef HAVE_NOTIFICATION
7053 static void show_ime_selector_notification ()
7057 if (!_MOBILE) return;
7059 unsigned int idx = get_ise_index (_info_manager->get_current_helper_uuid ());
7060 if (idx < _ime_info.size ())
7061 ise_name = _ime_info[idx].label;
7063 String noti_icon_path = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_QUICK_PANEL_ICON_PATH), String (SCIM_ICONDIR));
7064 noti_icon_path += ISF_ISE_SELECTOR_ICON_FILE;
7066 LOGD("IME selector icon path : %s", noti_icon_path.c_str ());
7068 ise_selector_module_noti.icon = noti_icon_path;
7069 ise_selector_module_noti.content = ise_name;
7071 /* Find IME Selector appid for notification */
7072 if (ime_selector_app.length () < 1) {
7073 char *app_id = NULL;
7074 pkgmgrinfo_appinfo_filter_h handle;
7075 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
7076 if (ret == PMINFO_R_OK) {
7077 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
7078 if (ret == PMINFO_R_OK) {
7079 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
7081 pkgmgrinfo_appinfo_filter_destroy (handle);
7084 ime_selector_app = String (app_id);
7091 if (ime_selector_app.length () > 0) {
7092 ise_selector_module_noti.launch_app = ime_selector_app;
7093 LOGD ("Create ise_selector notification with : %s", ime_selector_app.c_str ());
7094 create_notification (&ise_selector_module_noti);
7097 LOGW ("AppID with http://tizen.org/category/ime-selector category is not available");
7103 * @brief Callback function for ECORE_X_EVENT_WINDOW_PROPERTY.
7105 * @param data Data to pass when it is called.
7106 * @param ev_type The event type.
7107 * @param ev The information for current message.
7109 * @return ECORE_CALLBACK_PASS_ON
7111 static Eina_Bool x_event_window_property_cb (void *data, int ev_type, void *event)
7113 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7115 Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property *)event;
7118 return ECORE_CALLBACK_PASS_ON;
7120 if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
7121 if (ev->win == _control_window) {
7122 /* WMSYNC, #6 The keyboard window is displayed fully so set the conformant geometry */
7123 LOGD ("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE : win : %p, atom : %d", ev->win, ev->atom);
7124 Ecore_X_Virtual_Keyboard_State state;
7125 state = ecore_x_e_virtual_keyboard_state_get (ev->win);
7126 if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON) {
7127 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_ON");
7128 _ise_state = WINDOW_STATE_SHOW;
7130 /* Make sure that we have the same rotation angle with the keyboard window */
7132 _candidate_angle = efl_get_ise_window_angle ();
7133 _ise_angle = efl_get_ise_window_angle ();
7136 if (_candidate_show_requested) {
7137 LOGD ("calling ui_candidate_show (true)");
7138 ui_candidate_show (true);
7140 if (_candidate_area_1_visible) {
7141 LOGD ("calling ui_candidate_show (false)");
7142 ui_candidate_show (false);
7146 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7147 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7148 _info_manager->update_input_panel_event (
7149 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_SHOW);
7152 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW);
7155 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7156 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
7157 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
7159 #ifdef HAVE_NOTIFICATION
7160 show_ime_selector_notification ();
7165 _updated_hide_state_geometry = false;
7167 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
7168 } else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) {
7169 /* WMSYNC, #9 The keyboard window is hidden fully so send HIDE state */
7170 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF");
7171 // For now don't send HIDE signal here
7172 //_info_manager->update_input_panel_event (
7173 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
7174 _ise_state = WINDOW_STATE_HIDE;
7176 if (!_updated_hide_state_geometry) {
7177 /* When the ISE gets hidden by the window manager forcefully without OFF_PREPARE,
7178 the application might not have updated its autoscroll area */
7179 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7180 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7181 _info_manager->update_input_panel_event (
7182 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
7184 _updated_hide_state_geometry = true;
7186 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7187 LOGD ("calling ui_candidate_hide (true, false)");
7188 ui_candidate_hide (true, false);
7190 ui_settle_candidate_window ();
7194 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
7197 #ifdef HAVE_NOTIFICATION
7198 delete_notification (&ise_selector_module_noti);
7201 _ise_reported_geometry.valid = false;
7203 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
7205 ui_settle_candidate_window ();
7207 } else if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
7208 if (ev->win == efl_get_quickpanel_window ()) {
7209 int angle = efl_get_quickpanel_window_angle ();
7210 LOGD ("ev->win : %p, change window angle : %d", ev->win, angle);
7214 return ECORE_CALLBACK_PASS_ON;
7218 * @brief Callback function for X event client message.
7220 * @param data Data to pass when it is called.
7221 * @param type The event type.
7222 * @param event The information for current message.
7224 * @return ECORE_CALLBACK_RENEW
7226 static Eina_Bool x_event_client_message_cb (void *data, int type, void *event)
7228 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7230 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
7233 return ECORE_CALLBACK_RENEW;
7236 if ((ev->win == _control_window)) {
7237 if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST) {
7238 /* WMSYNC, #4 Send WILL_SHOW event when the keyboard window is about to displayed */
7239 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST");
7241 /* WMSYNC, #5 Let the Window Manager to actually show keyboard window */
7242 // WILL_SHOW_REQUEST_DONE Ack to WM
7243 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
7244 ecore_x_e_virtual_keyboard_on_prepare_done_send (root_window, _control_window);
7245 LOGD ("_ecore_x_e_virtual_keyboard_on_prepare_done_send (%x, %x)",
7246 root_window, _control_window);
7248 _info_manager->update_input_panel_event (
7249 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
7250 ui_create_candidate_window ();
7252 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_SHOW);
7253 } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST) {
7254 _ise_state = WINDOW_STATE_WILL_HIDE;
7255 /* WMSYNC, #7 Send WILL_HIDE event when the keyboard window is about to hidden */
7256 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST");
7257 // Clear conformant geometry information first
7259 if (_off_prepare_done_timer) {
7260 ecore_timer_del (_off_prepare_done_timer);
7261 _off_prepare_done_timer = NULL;
7263 _off_prepare_done_timer = ecore_timer_add (1.0, off_prepare_done_timeout, NULL);
7265 _ise_reported_geometry.valid = false;
7266 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7267 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7268 _updated_hide_state_geometry = true;
7270 /* If the input panel is getting hidden because of hw keyboard mode while
7271 the candidate window is still opened, it is considered to be an
7272 "input panel being resized" event instead of "input panel being hidden",
7273 since the candidate window will work as an "input panel" afterwards */
7274 bool send_input_panel_hide_event = true;
7275 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
7276 LOGD ("_candidate_state : %d", _candidate_state);
7277 if (_candidate_state == WINDOW_STATE_SHOW) {
7278 send_input_panel_hide_event = false;
7281 if (send_input_panel_hide_event) {
7282 _info_manager->update_input_panel_event (
7283 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
7285 // For now don't send WILL_HIDE signal here
7286 //_info_manager->update_input_panel_event (
7287 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_HIDE);
7288 // Instead send HIDE signal
7289 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_HIDE);
7290 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE) {
7291 /* WMSYNC, #10 Register size hints for candidate window and set conformant geometry */
7292 // PRE_ROTATE_DONE Ack to WM
7293 _candidate_angle = ev->data.l[1];
7294 _ise_angle = ev->data.l[1];
7295 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE : %d", _candidate_angle);
7297 if (_candidate_angle == 90 || _candidate_angle == 270) {
7298 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
7300 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
7302 if (_ise_state == WINDOW_STATE_SHOW) {
7303 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7304 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7306 ui_settle_candidate_window ();
7307 ui_candidate_window_rotate (_candidate_angle);
7308 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
7309 LOGD ("ecore_x_e_window_rotation_change_prepare_done_send (%d)", _candidate_angle);
7310 ecore_x_e_window_rotation_change_prepare_done_send (root_window,
7311 _control_window, _candidate_angle);
7312 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7313 int ise_angle = (int)ev->data.l[1];
7314 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST for ISE WINDOW : ISE angle : %d, Candidate angle : %d", ise_angle, _candidate_angle);
7315 _candidate_angle = ise_angle;
7316 _ise_angle = ise_angle;
7317 if (_ise_state == WINDOW_STATE_SHOW) {
7318 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
7319 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
7320 ui_settle_candidate_window ();
7323 } else if (ev->win == elm_win_xwindow_get (_candidate_window)) {
7324 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST || ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE) {
7325 /* WMSYNC, #11 Actual rotate the candidate window */
7326 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
7327 _candidate_angle = (int)ev->data.l[1];
7328 ui_candidate_window_rotate (_candidate_angle);
7329 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST : %d", _candidate_angle);
7330 } else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE &&
7331 _ise_state != WINDOW_STATE_SHOW) {
7332 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_TRUE);
7333 _candidate_angle = (int)ev->data.l[0];
7334 if (_candidate_angle == 90 || _candidate_angle == 270) {
7335 evas_object_resize (_candidate_window, _candidate_land_width, _candidate_land_height_min);
7337 evas_object_resize (_candidate_window, _candidate_port_width, _candidate_port_height_min);
7339 ui_candidate_window_rotate (_candidate_angle);
7340 ui_settle_candidate_window ();
7341 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_FALSE);
7342 LOGD ("ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE : %d", _candidate_angle);
7344 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " : ANGLE (" << _candidate_angle << ")\n";
7349 /* Screen reader feature */
7350 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL) {
7351 static int last_pos_x = -10000;
7352 static int last_pos_y = -10000;
7354 if (_candidate_window) {
7355 if ((unsigned int)ev->data.l[0] == elm_win_xwindow_get (_candidate_window)) {
7356 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE) {
7357 // 1 finger double tap
7358 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger double tap focus index = " << _candidate_tts_focus_index << "\n";
7359 ui_mouse_click (_candidate_tts_focus_index);
7360 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ) {
7362 // 1 finger touch & move
7363 last_pos_x = ev->data.l[2];
7364 last_pos_y = ev->data.l[3];
7365 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger touch & move (" << last_pos_x << ", " << last_pos_y << ")\n";
7366 ui_mouse_over (last_pos_x, last_pos_y);
7367 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT ||
7368 (unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV) {
7369 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT) {
7371 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick right\n";
7372 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_display_number - 1))
7373 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : 0;
7374 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7375 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7376 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
7377 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7378 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7379 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? 0 : _candidate_row_items[0];
7380 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7381 _candidate_tts_focus_index = _candidate_row_items[0];
7382 else if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < (g_isf_candidate_table.get_current_page_size () - 1))
7383 _candidate_tts_focus_index++;
7384 else if (_candidate_tts_focus_index == (g_isf_candidate_table.get_current_page_size () - 1))
7385 _candidate_tts_focus_index = 0;
7388 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick left\n";
7389 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == 0)
7390 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : _candidate_display_number - 1;
7391 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7392 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
7393 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
7394 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
7395 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
7396 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7397 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
7398 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
7399 else if (_candidate_tts_focus_index > 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ())
7400 _candidate_tts_focus_index--;
7401 else if (_candidate_tts_focus_index == 0)
7402 _candidate_tts_focus_index = g_isf_candidate_table.get_current_page_size () - 1;
7405 int x = 0, y = 0, w = 0, h = 0;
7406 _wait_stop_event = false;
7407 if (candidate_expanded) {
7409 int cursor_line = 0;
7410 for (unsigned int i = 0; i < _candidate_row_items.size (); i++) {
7411 total += _candidate_row_items [i];
7412 if (total > (int)_candidate_display_number && _candidate_tts_focus_index >= total)
7416 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
7418 int line_h = _item_min_height + _v_padding;
7419 int cursor_y = cursor_line * line_h;
7421 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
7422 _wait_stop_event = true;
7423 } else if (cursor_y >= y + h) {
7424 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
7425 _wait_stop_event = true;
7430 String strTts = String ("");
7431 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
7432 strTts = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (_candidate_tts_focus_index));
7433 if (_candidate_0 [_candidate_tts_focus_index])
7434 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
7435 } else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX) {
7436 strTts = String (_("more button"));
7437 evas_object_geometry_get (_more_btn, &x, &y, &w, &h);
7438 } else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX) {
7439 strTts = String (_("close button"));
7440 evas_object_geometry_get (_close_btn, &x, &y, &w, &h);
7442 LOGW ("TTS focus index = %d", _candidate_tts_focus_index);
7443 ui_tts_focus_rect_hide ();
7447 if (strTts.length () > 0)
7448 ui_play_tts (strTts.c_str ());
7450 if (w > 0 && h > 0) {
7451 if (!_wait_stop_event)
7452 ui_tts_focus_rect_show (x, y, w, h);
7454 ui_tts_focus_rect_hide ();
7461 return ECORE_CALLBACK_RENEW;
7465 Eina_Bool check_focus_out_by_popup_win ()
7467 Eina_Bool ret = EINA_FALSE;
7469 Ecore_X_Window focus_win = ecore_x_window_focus_get ();
7470 Ecore_X_Window_Type win_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
7472 if (!ecore_x_netwm_window_type_get (focus_win, &win_type))
7475 LOGD ("win type : %d", win_type);
7477 if (win_type == ECORE_X_WINDOW_TYPE_POPUP_MENU ||
7478 win_type == ECORE_X_WINDOW_TYPE_NOTIFICATION) {
7487 * @brief Callback function for focus out event of application window
7489 * @param data Data to pass when it is called.
7491 * @return ECORE_CALLBACK_RENEW
7493 static Eina_Bool x_event_window_focus_out_cb (void *data, int ev_type, void *event)
7495 Ecore_X_Event_Window_Focus_Out *e = (Ecore_X_Event_Window_Focus_Out*)event;
7497 if (e && e->win == _app_window) {
7498 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7499 if (check_focus_out_by_popup_win ())
7500 return ECORE_CALLBACK_RENEW;
7502 #if ENABLE_MULTIWINDOW_SUPPORT
7503 unsigned int layout = 0;
7504 LOGD ("Application window focus OUT!");
7505 delete_ise_hide_timer ();
7507 // Check multi window mode
7508 if (ecore_x_window_prop_card32_get (efl_get_app_window (), ECORE_X_ATOM_E_WINDOW_DESKTOP_LAYOUT, &layout, 1) != -1) {
7509 if (layout == 0 || layout == 1) {
7511 LOGD ("Multi window mode. start timer to hide IME");
7513 // Use timer not to hide and show IME again in focus-out and focus-in event between applications
7514 _ise_hide_timer = ecore_timer_add (ISF_ISE_HIDE_DELAY, ise_hide_timeout, NULL);
7518 if (!_ise_hide_timer) {
7519 LOGD ("Panel hides ISE");
7520 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7522 ui_candidate_hide (true, false, false);
7525 LOGD ("Application window focus OUT! Panel hides ISE");
7526 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7528 ui_candidate_hide (true, false, false);
7533 return ECORE_CALLBACK_RENEW;
7537 static void restore_config ()
7539 if (!_config.null ()) {
7540 String uuid = _initial_ise_uuid;
7542 String global_uuid = scim_global_config_read (String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String(""));
7543 if (global_uuid.length () > 0) uuid = global_uuid;
7545 String default_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
7546 if (default_uuid.length() > 0) uuid = default_uuid;
7548 if (global_uuid.length() == 0) {
7549 scim_global_config_write (String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), uuid);
7551 if (default_uuid.length() == 0) {
7552 _config->write (SCIM_CONFIG_DEFAULT_HELPER_ISE, uuid);
7555 scim_global_config_flush ();
7558 scim_global_config_reload ();
7564 * @brief : Launches default soft keyboard for performance enhancement (It's not mandatory)
7566 static void launch_default_soft_keyboard (keynode_t *key, void* data)
7568 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7571 if (!_config.null()) {
7572 helper_uuid = _config->read(SCIM_CONFIG_DEFAULT_HELPER_ISE, String(""));
7574 if (helper_uuid.length () > 0) {
7575 /* Start default ISE */
7576 change_keyboard_mode (TOOLBAR_HELPER_MODE);
7578 if (!_launch_ise_on_request) {
7579 set_temporary_ise (_initial_ise_uuid);
7585 static String sanitize_string (const char *str, int maxlen = 32)
7588 static char acceptables[] =
7589 "abcdefghijklmnopqrstuvwxyz"
7590 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7593 char *newstr = NULL;
7595 newstr = new char[maxlen + 1];
7599 memset (newstr, 0x00, sizeof (char) * (maxlen + 1));
7602 while (len < maxlen && str[len] != '\0' && strchr (acceptables, str[len]) != NULL) {
7603 newstr[len] = str[len];
7613 static Eina_Bool monitor_user_data_path_timer(void *data)
7615 const char *path = static_cast<const char*>(data);
7616 bool user_data_path_exists = ecore_file_exists (path);
7617 bool user_data_path_is_dir = ecore_file_is_dir (path);
7618 if (user_data_path_exists && user_data_path_is_dir) {
7619 LOGW ("'%s' exists : %d, is_dir : %d", path,
7620 (user_data_path_exists ? 1 : 0), (user_data_path_is_dir ? 1 : 0));
7622 scim_global_config_reload (true);
7626 /* Read all ime info from db */
7628 isf_pkg_select_all_ime_info_db (_ime_info);
7631 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
7634 if (_launch_ise_on_request) {
7637 String default_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
7639 set_active_ise (default_ise_uuid, launch);
7643 g_monitor_user_data_path_timer = NULL;
7644 return ECORE_CALLBACK_CANCEL;
7647 return ECORE_CALLBACK_RENEW;
7650 int main (int argc, char *argv [])
7652 struct tms tiks_buf;
7653 _clock_start = times (&tiks_buf);
7658 bool daemon = false;
7659 bool should_resident = true;
7662 char **new_argv = new char * [40];
7663 int display_name_c = 0;
7664 ConfigModule *config_module = NULL;
7665 String config_name = String ("simple");
7666 String display_name = String ();
7667 char buf[256] = {0};
7669 String user_data_path = String ();
7670 bool user_data_path_exists = false;
7671 bool user_data_path_is_dir = false;
7674 Ecore_Event_Handler *xclient_message_handler = NULL;
7675 Ecore_Event_Handler *xwindow_property_handler = NULL;
7676 Ecore_Event_Handler *xwindow_focus_out_handler = NULL;
7679 check_time ("\nStarting ISF Panel EFL...... ");
7680 ISF_SAVE_LOG ("Starting ISF Panel EFL......");
7682 DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
7683 DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
7685 /* Parse command options */
7691 if (String ("-c") == argv [i] || String ("--config") == argv [i]) {
7693 std::cerr << "no argument for option " << argv [i-1] << "\n";
7697 config_name = argv [i];
7701 if (String ("-h") == argv [i] || String ("--help") == argv [i]) {
7702 std::cout << "Usage: " << argv [0] << " [option]...\n\n"
7703 << "The options are: \n"
7704 << " --display DISPLAY Run on display DISPLAY.\n"
7705 << " -c, --config NAME Uses specified Config module.\n"
7706 << " -d, --daemon Run " << argv [0] << " as a daemon.\n"
7707 << " -ns, --no-stay Quit if no connected client.\n"
7709 << " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
7710 << " -o, --output FILE Output debug information into FILE.\n"
7712 << " -h, --help Show this help message.\n";
7717 if (String ("-d") == argv [i] || String ("--daemon") == argv [i]) {
7722 if (String ("-ns") == argv [i] || String ("--no-stay") == argv [i]) {
7723 should_resident = false;
7727 if (String ("-v") == argv [i] || String ("--verbose") == argv [i]) {
7729 std::cerr << "no argument for option " << argv [i-1] << "\n";
7733 DebugOutput::set_verbose_level (atoi (argv [i]));
7737 if (String ("-o") == argv [i] || String ("--output") == argv [i]) {
7739 std::cerr << "No argument for option " << argv [i-1] << "\n";
7743 DebugOutput::set_output (sanitize_string (argv [i]));
7747 if (String ("--display") == argv [i]) {
7749 std::cerr << "No argument for option " << argv [i-1] << "\n";
7753 display_name = sanitize_string (argv [i]);
7757 if (String ("--") == argv [i])
7760 std::cerr << "Invalid command line option: " << argv [i] << "\n";
7763 } /* End of command line parsing. */
7766 new_argv [new_argc ++] = argv [0];
7768 /* Store the rest argvs into new_argv. */
7769 for (++i; i < argc && new_argc < 37; ++i) {
7770 new_argv [new_argc ++] = argv [i];
7773 /* Make up DISPLAY env. */
7774 if (display_name.length ()) {
7775 new_argv [new_argc ++] = const_cast <char*> ("--display");
7776 display_name_c = new_argc;
7777 new_argv [new_argc ++] = strdup (display_name.c_str ());
7779 setenv ("DISPLAY", display_name.c_str (), 1);
7782 new_argv [new_argc] = 0;
7785 if (!config_name.length ()) {
7786 std::cerr << "No Config module is available!\n";
7791 /* Get current display. */
7793 const char *p = getenv ("DISPLAY");
7795 display_name = String (p);
7798 snprintf (buf, sizeof (buf), "config_name=%s display_name=%s", config_name.c_str (), display_name.c_str ());
7802 check_time ("ISF Panel EFL run as daemon");
7806 /* No loading default theme to reduce heap memory */
7807 setenv ("ELM_THEME", "", 1);
7809 #if ISF_BUILD_CANDIDATE_UI
7810 elm_init (argc, argv);
7813 ecore_app_args_set(argc, (const char **)argv);
7814 #endif /* CANDIDATE */
7816 check_time ("elm_init");
7820 #if ISF_BUILD_CANDIDATE_UI
7821 elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
7822 #endif /* CANDIDATE */
7824 if (config_name != "dummy") {
7825 /* Load config module */
7826 config_module = new ConfigModule (config_name);
7828 if (!config_module || !config_module->valid ()) {
7829 std::cerr << "Can not load " << config_name << " Config module.\n";
7834 _config = new DummyConfig ();
7837 /* Create config instance */
7838 if (_config.null () && config_module && config_module->valid ())
7839 _config = config_module->create_config ();
7840 if (_config.null ()) {
7841 std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
7845 ConfigBase::set (_config);
7846 check_time ("create config instance");
7849 if (!initialize_panel_agent (_config, display_name, should_resident)) {
7850 check_time ("Failed to initialize Panel Agent!");
7851 std::cerr << "Failed to initialize Panel Agent!\n";
7852 LOGE ("Failed to initialize Panel Agent!");
7856 } catch (scim::Exception & e) {
7857 std::cerr << e.what () << "\n";
7862 check_time ("initialize_panel_agent");
7864 #if ISF_BUILD_CANDIDATE_UI
7865 /* Initialize global variables and pointers for candidate items and etc. */
7866 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; i++) {
7867 _candidate_0 [i] = NULL;
7868 _seperate_0 [i] = NULL;
7869 _seperate_items [i] = NULL;
7871 _line_items [i] = NULL;
7872 _candidate_text [i] = NULL;
7873 _candidate_image [i] = NULL;
7874 _candidate_pop_image [i] = NULL;
7876 #endif /* CANDIDATE */
7878 /* Connect the configuration reload signal. */
7879 _config_connection = _config->signal_connect_reload (slot (config_reload_cb));
7882 if (!efl_create_control_window ()) {
7883 LOGW ("Failed to create control window");
7888 #if ISF_BUILD_CANDIDATE_UI
7889 efl_get_screen_resolution (_screen_width, _screen_height);
7891 _width_rate = (float)(_screen_width / 720.0);
7892 _height_rate = (float)(_screen_height / 1280.0);
7893 _blank_width = (int)(_blank_width * _width_rate);
7894 _item_min_width = (int)(_item_min_width * _width_rate);
7895 _item_min_height = (int)(_item_min_height * _height_rate);
7896 _candidate_width = (int)(_candidate_port_width * _width_rate);
7897 _candidate_height = (int)(_candidate_port_height_min * _height_rate);
7898 _indicator_height = (int)(_indicator_height * _height_rate);
7900 _aux_font_size = (int)(_aux_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7901 _candidate_font_size = (int)(_candidate_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7902 #endif /* CANDIDATE */
7904 /* Load ISF configuration */
7905 user_data_path = scim_get_user_data_dir ();
7906 user_data_path_exists = ecore_file_exists (user_data_path.c_str ());
7907 user_data_path_is_dir = ecore_file_is_dir (user_data_path.c_str ());
7908 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
7909 if (user_data_path_exists && user_data_path_is_dir) {
7912 LOGW ("'%s' exists : %d, is_dir : %d", user_data_path.c_str (),
7913 (user_data_path_exists ? 1 : 0), (user_data_path_is_dir ? 1 : 0));
7914 g_monitor_user_data_path_timer = ecore_timer_add (1.0, monitor_user_data_path_timer, user_data_path.c_str ());
7916 check_time("load_config");
7920 lang_str = vconf_get_str (VCONFKEY_LANGSET);
7921 set_language_and_locale (lang_str);
7925 /* Add callback function for input language and display language */
7926 vconf_notify_key_changed (VCONFKEY_LANGSET, display_language_changed_cb, NULL);
7927 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
7931 if (0 != register_edbus_signal_handler ())
7932 LOGW ("register edbus signal fail");
7936 /* Update ISE list */
7937 std::vector<String> list;
7938 update_ise_list (list);
7940 /* Load initial ISE information */
7941 _initial_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_INITIAL_ISE_UUID), String (SCIM_COMPOSE_KEY_FACTORY_UUID));
7943 /* Check if SCIM_CONFIG_DEFAULT_HELPER_ISE is available. If it's not, set it as _initial_ise_uuid.
7944 e.g., This might be necessary when the platform is upgraded from 2.3 to 2.4. */
7945 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
7946 if (_initial_ise_uuid.length() > 0 && helper_uuid != _initial_ise_uuid) {
7948 for (unsigned int u = 0; u < _ime_info.size (); u++) {
7949 if (_ime_info[u].mode == TOOLBAR_HELPER_MODE && helper_uuid == _ime_info[u].appid) {
7955 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), _initial_ise_uuid);
7959 /* Launches default soft keyboard when all conditions are satisfied */
7960 launch_default_soft_keyboard ();
7962 /* Update the name of each ISE according to display language */
7963 update_ise_locale ();
7964 } catch (scim::Exception & e) {
7965 std::cerr << e.what () << "\n";
7966 } catch (std::logic_error & e) {
7967 std::cerr << e.what () << "\n";
7970 xclient_message_handler = ecore_event_handler_add (ECORE_X_EVENT_CLIENT_MESSAGE, x_event_client_message_cb, NULL);
7971 xwindow_property_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, x_event_window_property_cb, NULL);
7972 xwindow_focus_out_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_FOCUS_OUT, x_event_window_focus_out_cb, NULL);
7975 #ifdef HAVE_BLUETOOTH
7976 /* Register the callback function of Bluetooth connection */
7977 ret = bt_initialize ();
7978 if (ret != BT_ERROR_NONE)
7979 LOGW ("Fail to init Bluetooth");
7981 ret = bt_hid_host_initialize (_bt_cb_hid_state_changed, NULL);
7982 if (ret != BT_ERROR_NONE)
7983 LOGW ("bt_hid_host_initialize failed");
7987 launch_remote_input = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_REMOTE_INPUT), launch_remote_input);
7989 /* Create remote input */
7990 if (launch_remote_input) {
7991 LOGD("remote input start");
7992 remote_input_impl = new Remote_Input();
7993 if (remote_input_impl) {
7994 remote_input_impl->init(_info_manager);
7999 #if ISF_BUILD_CANDIDATE_UI
8000 _system_scale = elm_config_scale_get ();
8002 /* Set elementary scale */
8003 if (_screen_width) {
8004 _app_scale = _screen_width / 720.0;
8005 elm_config_scale_set (_app_scale);
8007 snprintf (buf, sizeof (buf), "%4.3f", _app_scale);
8008 setenv ("ELM_SCALE", buf, 1);
8010 #endif /* CANDIDATE */
8012 signal (SIGQUIT, signalhandler);
8013 signal (SIGTERM, signalhandler);
8014 signal (SIGINT, signalhandler);
8015 signal (SIGHUP, signalhandler);
8017 check_time ("EFL Panel launch time");
8019 if (!isf_cynara_initialize())
8020 LOGW ("Failed to initialize cynara");
8022 #if ISF_BUILD_CANDIDATE_UI
8025 ecore_main_loop_begin ();
8026 #endif /* CANDIDATE */
8028 LOGW("out of loop");
8030 isf_cynara_finish();
8035 if (g_monitor_user_data_path_timer) {
8036 ecore_timer_del (g_monitor_user_data_path_timer);
8037 g_monitor_user_data_path_timer = NULL;
8040 #ifdef HAVE_BLUETOOTH
8041 /* deinitialize the callback function of Bluetooth connection */
8042 ret = bt_hid_host_deinitialize ();
8043 if (ret != BT_ERROR_NONE)
8044 LOGW ("bt_hid_host_deinitialize failed: %d", ret);
8046 ret = bt_deinitialize ();
8047 if (ret != BT_ERROR_NONE)
8048 LOGW ("bt_deinitialize failed: %d", ret);
8052 if (xclient_message_handler) {
8053 ecore_event_handler_del (xclient_message_handler);
8054 xclient_message_handler = NULL;
8057 if (xwindow_property_handler) {
8058 ecore_event_handler_del (xwindow_property_handler);
8059 xwindow_property_handler = NULL;
8062 if (xwindow_focus_out_handler) {
8063 ecore_event_handler_del (xwindow_focus_out_handler);
8064 xwindow_focus_out_handler = NULL;
8069 /* Remove callback function for input language and display language */
8070 vconf_ignore_key_changed (VCONFKEY_LANGSET, display_language_changed_cb);
8071 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
8075 #if ISF_BUILD_CANDIDATE_UI
8076 ui_destroy_candidate_window ();
8077 ui_candidate_delete_check_size_timer ();
8078 ui_candidate_delete_longpress_timer ();
8079 ui_candidate_delete_destroy_timer ();
8080 #endif /* CANDIDATE */
8081 #ifdef HAVE_PKGMGR_INFO
8083 package_manager_destroy (pkgmgr);
8087 delete_ise_check_pid_alive_timer();
8089 #if ISF_BUILD_CANDIDATE_UI
8096 unregister_edbus_signal_handler ();
8099 if (_info_manager) {
8101 _info_manager->stop ();
8102 } catch (scim::Exception & e) {
8103 std::cerr << "Exception is thrown from _info_manager->stop (), error is " << e.what () << "\n";
8105 delete _info_manager;
8107 _config_connection.disconnect ();
8108 if (!_config.null ())
8110 ConfigBase::set (0);
8113 delete config_module;
8115 #if ISF_BUILD_CANDIDATE_UI
8119 #endif /* CANDIDATE */
8122 if ((display_name_c > 0) && new_argv [display_name_c]) {
8123 free (new_argv [display_name_c]);
8128 ISF_SAVE_LOG ("ret=%d", ret);
8130 std::cerr << "Successfully exited.\n";
8133 std::cerr << "Abnormally exited.\n";
8139 vi:ts=4:nowrap:expandtab