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>
44 #include "scim_private.h"
46 #include "scim_stl_map.h"
52 #include <X11/Xatom.h>
55 #include <Ecore_Wayland.h>
57 #include <Elementary.h>
60 #include <vconf-keys.h>
64 #include <notification.h>
65 #include <notification_internal.h>
75 #include <bluetooth.h>
78 #include <package_manager.h>
79 #include <pkgmgr-info.h>
81 #include "isf_panel_efl.h"
82 #include "isf_panel_utility.h"
83 #include "isf_query_utility.h"
84 #include <app_control.h>
86 #include "privilege_checker.h"
91 /////////////////////////////////////////////////////////////////////////////
92 // Declaration of macro.
93 /////////////////////////////////////////////////////////////////////////////
94 #define EFL_CANDIDATE_THEME1 (SCIM_DATADIR "/isf_candidate_theme1.edj")
96 #define ISF_CANDIDATE_TABLE 0
99 #define ISF_EFL_CANDIDATE_0 2
100 #define ISF_EFL_CANDIDATE_ITEMS 3
102 #define ISE_DEFAULT_HEIGHT_PORTRAIT 444
103 #define ISE_DEFAULT_HEIGHT_LANDSCAPE 316
105 #define ISF_CANDIDATE_DESTROY_DELAY 3
106 #define ISF_ISE_HIDE_DELAY 0.15
108 #define ISF_PREEDIT_BORDER 16
109 #define ISE_LAUNCH_TIMEOUT 2.0
111 #define ISF_POP_PLAY_ICON_FILE "/usr/share/scim/icons/pop_play.png"
112 #define ISF_KEYBOARD_ICON_FILE "/usr/share/scim/icons/noti_icon_hwkbd_module.png"
113 #define ISF_ISE_SELECTOR_ICON_FILE "/usr/share/scim/icons/noti_icon_ise_selector.png"
115 #define HOST_BUS_NAME "org.tizen.usb.host"
116 #define HOST_OBJECT_PATH "/Org/Tizen/Usb/Host"
117 #define HOST_INTERFACE_NAME "org.tizen.usb.host"
118 #define HOST_KEYBOARD_SIGNAL "usbkeyboard"
119 #define HOST_ADDED "added"
120 #define HOST_REMOVED "removed"
122 #define E_PROP_DEVICEMGR_INPUTWIN "DeviceMgr Input Window"
124 #define SCIM_HELPER_LAUNCHER_PROGRAM (SCIM_LIBEXECDIR "/scim-helper-launcher")
126 /////////////////////////////////////////////////////////////////////////////
127 // Declaration of external variables.
128 /////////////////////////////////////////////////////////////////////////////
129 extern MapStringVectorSizeT _groups;
130 extern std::vector<ImeInfoDB> _ime_info;
132 extern EXAPI CommonLookupTable g_isf_candidate_table;
135 /////////////////////////////////////////////////////////////////////////////
136 // Declaration of internal data types.
137 /////////////////////////////////////////////////////////////////////////////
138 typedef enum _WINDOW_STATE {
139 WINDOW_STATE_HIDE = 0,
140 WINDOW_STATE_WILL_HIDE,
141 WINDOW_STATE_WILL_SHOW,
146 typedef struct NotiData
155 typedef std::vector < std::pair <String, uint32> > VectorPairStringUint32;
157 /////////////////////////////////////////////////////////////////////////////
158 // Declaration of internal functions.
159 /////////////////////////////////////////////////////////////////////////////
160 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect);
163 static void efl_set_transient_for_app_window (Ecore_X_Window window);
165 static int efl_get_app_window_angle (void);
166 static int efl_get_ise_window_angle (void);
168 static int efl_get_quickpanel_window_angle (void);
171 static int ui_candidate_get_valid_height (void);
172 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd = true, bool will_hide = false);
173 static void ui_destroy_candidate_window (void);
174 static void ui_settle_candidate_window (void);
175 static void ui_candidate_show (bool bSetVirtualKbd = true);
176 static void ui_create_candidate_window (void);
177 static void update_table (int table_type, const LookupTable &table);
178 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info);
179 static void set_soft_candidate_geometry (int x, int y, int width, int height);
180 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack);
181 static void ui_tts_focus_rect_hide (void);
183 static Evas_Object *get_candidate (const String& str, Evas_Object *parent, int *total_width, uint32 ForeGround, uint32 BackGround, bool HighLight, bool SetBack, int item_num, int item);
184 static bool tokenize_tag (const String& str, struct image *image_data);
186 static void launch_default_soft_keyboard (keynode_t *key = NULL, void* data = NULL);
188 /* PanelAgent related functions */
189 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident);
191 static void slot_reload_config (void);
192 static void slot_focus_in (void);
193 static void slot_focus_out (void);
194 static void slot_expand_candidate (void);
195 static void slot_contract_candidate (void);
196 static void slot_set_candidate_style (int portrait_line, int mode);
197 static void slot_update_input_context (int type, int value);
198 static void slot_update_ise_geometry (int x, int y, int width, int height);
199 static void slot_update_spot_location (int x, int y, int top_y);
200 static void slot_update_factory_info (const PanelFactoryInfo &info);
201 static void slot_show_preedit_string (void);
202 static void slot_show_aux_string (void);
203 static void slot_show_candidate_table (void);
204 static void slot_hide_preedit_string (void);
205 static void slot_hide_aux_string (void);
206 static void slot_hide_candidate_table (void);
207 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret);
208 static void slot_update_preedit_caret (int caret);
209 static void slot_update_aux_string (const String &str, const AttributeList &attrs);
210 static void slot_update_candidate_table (const LookupTable &table);
211 static void slot_select_candidate (int index);
212 static void slot_set_active_ise (const String &uuid, bool changeDefault);
213 static bool slot_get_ise_list (std::vector<String> &list);
214 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info);
215 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option);
216 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled);
217 static void slot_show_helper_ise_list (void);
218 static void slot_show_helper_ise_selector (void);
219 static bool slot_is_helper_ise_enabled (String appid, int &enabled);
220 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name);
221 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list);
222 static void slot_get_language_list (std::vector<String> &name);
223 static void slot_get_all_language (std::vector<String> &lang);
224 static void slot_get_ise_language (char *name, std::vector<String> &list);
225 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info);
226 static void slot_get_candidate_geometry (struct rectinfo &info);
227 static void slot_get_input_panel_geometry (struct rectinfo &info);
228 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info);
229 static bool slot_check_privilege_by_sockfd (int client_id, String privilege);
230 static void slot_set_keyboard_ise (const String &uuid);
231 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid);
232 static void slot_accept_connection (int fd);
233 static void slot_close_connection (int fd);
234 static void slot_exit (void);
236 static void slot_register_helper_properties (int id, const PropertyList &props);
237 static void slot_show_ise (void);
238 static void slot_hide_ise (void);
240 static void slot_will_hide_ack (void);
241 static void slot_candidate_will_hide_ack (void);
243 static void slot_set_keyboard_mode (int mode);
244 static void slot_get_ise_state (int &state);
245 static void slot_start_default_ise (void);
246 static void slot_stop_default_ise (void);
249 static Eina_Bool efl_create_control_window (void);
250 static Ecore_X_Window efl_get_app_window (void);
251 static Ecore_X_Window efl_get_quickpanel_window (void);
252 static Ecore_X_Window efl_get_global_navigation_window (void);
255 static void change_keyboard_mode (TOOLBAR_MODE_T mode);
256 static unsigned int get_ise_index (const String uuid);
257 static bool set_active_ise (const String &uuid, bool launch_ise);
258 static bool update_ise_list (std::vector<String> &list);
259 static void update_ise_locale ();
260 #ifdef HAVE_NOTIFICATION
261 static void delete_notification (NotificationData *noti_data);
262 static void create_notification (NotificationData *noti_data);
264 static void set_language_and_locale (void);
265 static void show_ime_selector_notification (void);
267 /////////////////////////////////////////////////////////////////////////////
268 // Declaration of internal variables.
269 /////////////////////////////////////////////////////////////////////////////
270 static Evas_Object *_candidate_window = 0;
271 static Evas_Object *_candidate_area_1 = 0;
272 static Evas_Object *_candidate_area_2 = 0;
273 static Evas_Object *_candidate_bg = 0;
274 static Evas_Object *_candidate_0_scroll = 0;
275 static Evas_Object *_candidate_scroll = 0;
276 static Evas_Object *_scroller_bg = 0;
277 static Evas_Object *_candidate_0_table = 0;
278 static Evas_Object *_candidate_table = 0;
279 static Evas_Object *_candidate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
280 static Evas_Object *_candidate_text [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
281 static Evas_Object *_candidate_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
282 static Evas_Object *_candidate_pop_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
283 static Evas_Object *_seperate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
284 static Evas_Object *_seperate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
285 static Evas_Object *_line_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
286 static Evas_Object *_line_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
287 static Evas_Object *_more_btn = 0;
288 static Evas_Object *_close_btn = 0;
289 static bool _candidate_show_requested = false;
290 static bool _updated_hide_state_geometry = false;
292 static int _candidate_x = 0;
293 static int _candidate_y = 0;
294 static int _candidate_width = 0;
295 static int _candidate_height = 0;
296 static int _soft_candidate_width = 0;
297 static int _soft_candidate_height = 0;
298 static int _candidate_valid_height = 0;
300 static bool _candidate_area_1_visible = false;
301 static bool _candidate_area_2_visible = false;
302 static bool _aux_area_visible = false;
304 static ISF_CANDIDATE_MODE_T _candidate_mode = SOFT_CANDIDATE_WINDOW;
305 static ISF_CANDIDATE_PORTRAIT_LINE_T _candidate_port_line = ONE_LINE_CANDIDATE;
307 static int _candidate_port_width = 480;
308 static int _candidate_port_height_min = 76;
309 static int _candidate_port_height_min_2 = 150;
310 static int _candidate_port_height_max = 286;
311 static int _candidate_port_height_max_2 = 350;
312 static int _candidate_land_width = 784;
313 static int _candidate_land_height_min = 84;
314 static int _candidate_land_height_min_2 = 168;
315 static int _candidate_land_height_max = 150;
316 static int _candidate_land_height_max_2 = 214;
317 static int _candidate_area_1_pos [2] = {0, 2};
318 static int _more_btn_pos [4] = {369, 11, 689, 11};
319 static int _close_btn_pos [4] = {362, 211, 682, 75};
320 static int _more_btn_width = 80;
321 static int _more_btn_height = 64;
323 static int _h_padding = 4;
324 static int _v_padding = 2;
325 static int _item_min_width = 99;
326 static int _item_min_height = 82;
328 static int _candidate_scroll_0_width_min = 350;
329 static int _candidate_scroll_0_width_max = 670;
331 static int _candidate_scroll_width = 453;
332 static int _candidate_scroll_width_min = 453;
333 static int _candidate_scroll_width_max = 663;
334 static int _candidate_scroll_height_min = 124;
335 static int _candidate_scroll_height_max = 190;
337 const int MORE_BUTTON_INDEX = -1;
338 const int CLOSE_BUTTON_INDEX = -2;
339 const int INVALID_TTS_FOCUS_INDEX = -100;
340 static int _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
341 static uint32 _candidate_display_number = 0;
342 static std::vector<uint32> _candidate_row_items;
343 static Evas_Object *_tts_focus_rect = 0;
344 static bool _wait_stop_event = false;
346 static Evas_Object *_preedit_window = 0;
347 static Evas_Object *_preedit_text = 0;
348 static int _preedit_width = 100;
349 static int _preedit_height = 54;
351 static Evas_Object *_aux_area = 0;
352 static Evas_Object *_aux_line = 0;
353 static Evas_Object *_aux_table = 0;
354 static int _aux_height = 0;
355 static int _aux_port_width = 444;
356 static int _aux_land_width = 764;
357 static std::vector<Evas_Object *> _aux_items;
358 static std::vector<Evas_Object *> _aux_seperates;
360 static Evas_Object *_tmp_preedit_text = 0;
361 static Evas_Object *_tmp_aux_text = 0;
362 static Evas_Object *_tmp_candidate_text = 0;
364 static int _spot_location_x = -1;
365 static int _spot_location_y = -1;
366 static int _spot_location_top_y = -1;
367 static int _candidate_angle = 0;
368 static int _ise_angle = -1;
370 static int _ise_x = 0;
371 static int _ise_y = 0;
372 static int _ise_width = 0;
373 static int _ise_height = 0;
374 static WINDOW_STATE _ise_state = WINDOW_STATE_HIDE;
375 static WINDOW_STATE _candidate_state = WINDOW_STATE_HIDE;
377 static int _indicator_height = 0;//24;
378 static int _screen_width = 720;
379 static int _screen_height = 1280;
380 static float _width_rate = 1.0;
381 static float _height_rate = 1.0;
382 static int _blank_width = 30;
384 static String _candidate_name = String ("candidate");
385 static String _candidate_edje_file = String (EFL_CANDIDATE_THEME1);
387 static String _candidate_font_name = String ("Tizen");
388 static int _candidate_font_size = 38;
389 static int _aux_font_size = 38;
390 static int _click_object = 0;
391 static int _click_down_pos [2] = {0, 0};
392 static int _click_up_pos [2] = {0, 0};
393 static bool _is_click = true;
394 static String _initial_ise_uuid = String ("");
395 static String _locale_string = String ("");
396 static ConfigPointer _config;
397 static InfoManager *_info_manager = 0;
399 static clock_t _clock_start;
401 static Ecore_Timer *_check_size_timer = NULL;
402 static Ecore_Timer *_longpress_timer = NULL;
403 static Ecore_Timer *_destroy_timer = NULL;
405 static Ecore_Timer *_off_prepare_done_timer = NULL;
407 static Ecore_Timer *_candidate_hide_timer = NULL;
408 static Ecore_Timer *_ise_hide_timer = NULL;
411 static Ecore_X_Window _ise_window = 0;
412 static Ecore_X_Window _app_window = 0;
413 static Ecore_X_Window _control_window = 0;
414 static Ecore_X_Window _input_win = 0;
418 static package_manager_h pkgmgr = NULL;
419 static VectorPairStringUint32 g_pkgids_to_be_uninstalled;
420 static Ecore_Timer *g_release_uninstalled_ime_info_timer = NULL;
421 static String g_stopped_helper_pkgid = "";
422 static Ecore_Timer *g_start_default_helper_timer = NULL;
423 static VectorPairStringUint32 g_pkgids_to_be_updated_and_installed;
424 static String g_updated_helper_pkgid = "";
427 static bool _launch_ise_on_request = false;
428 static bool _soft_keyboard_launched = false;
429 static bool _focus_in = false;
431 static bool candidate_expanded = false;
432 static int _candidate_image_count = 0;
433 static int _candidate_text_count = 0;
434 static int _candidate_pop_image_count = 0;
435 static int candidate_image_height = 38;
436 static int candidate_play_image_width_height = 19;
438 static const int CANDIDATE_TEXT_OFFSET = 2;
440 static double _app_scale = 1.0;
441 static double _system_scale = 1.0;
443 #ifdef HAVE_NOTIFICATION
444 static NotificationData hwkbd_module_noti = {"Input detected from hardware keyboard", "Tap to use virtual keyboard", ISF_KEYBOARD_ICON_FILE, "", 0};
445 static NotificationData ise_selector_module_noti = {"Select input method", NULL, ISF_ISE_SELECTOR_ICON_FILE, "", 0};
449 static tts_h _tts = NULL;
453 static bool feedback_initialized = false;
456 static E_DBus_Connection *edbus_conn;
457 static E_DBus_Signal_Handler *edbus_handler;
460 static Ecore_Event_Handler *_candidate_show_handler = NULL;
463 static String ime_selector_app = "";
464 static String ime_list_app = "";
467 EMOJI_IMAGE_WIDTH = 0,
470 EMOJI_IMAGE_TAG_FLAG,
471 EMOJI_IMAGE_POP_FLAG,
478 int emoji_option[EMOJI_IMAGE_END];
481 /* This structure stores the geometry information reported by ISE */
484 bool valid; /* Whether this information is currently valid */
485 int angle; /* For which angle this information is useful */
486 struct rectinfo geometry; /* Geometry information */
489 static struct GeometryCache _ise_reported_geometry = {0, 0, {0, 0, 0, 0}};
490 static struct GeometryCache _portrait_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
491 static struct GeometryCache _landscape_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
494 static void get_input_window (void)
497 Ecore_X_Atom atom = 0;
499 if (_input_win == 0) {
500 atom = ecore_x_atom_get (E_PROP_DEVICEMGR_INPUTWIN);
501 win_ret = ecore_x_window_prop_window_get (ecore_x_window_root_first_get (), atom, &_input_win, 1);
502 if (_input_win == 0 || win_ret < 1) {
503 LOGW ("Input window is NULL!\n");
505 ecore_x_event_mask_set (_input_win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
511 static void usb_keyboard_signal_cb (void *data, DBusMessage *msg)
517 LOGW ("No Message\n");
521 if (dbus_message_is_signal (msg, HOST_INTERFACE_NAME, HOST_KEYBOARD_SIGNAL) == 0) {
522 LOGW ("HOST_KEYBOARD_SIGNAL\n");
526 dbus_error_init (&err);
528 if (dbus_message_get_args (msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) {
529 LOGW ("DBUS_TYPE_INVALID\n");
535 if (!strncmp (str, HOST_ADDED, strlen (HOST_ADDED))) {
536 LOGD ("HOST_ADDED\n");
540 if (!strncmp (str, HOST_REMOVED, strlen (HOST_REMOVED))) {
541 LOGD ("HOST_REMOVED\n");
542 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
543 change_keyboard_mode (TOOLBAR_HELPER_MODE);
548 LOGW ("ERROR: msg (%s) is improper\n", str);
551 static void unregister_edbus_signal_handler (void)
554 LOGD ("unregister signal handler for keyboard\n");
556 e_dbus_signal_handler_del (edbus_conn, edbus_handler);
557 edbus_handler = NULL;
559 e_dbus_connection_close (edbus_conn);
565 static int register_edbus_signal_handler (void)
568 LOGD ("start register_edbus_signal_handler\n");
571 while (e_dbus_init () == 0) {
574 LOGW ("retry fail\n");
579 edbus_conn = e_dbus_bus_get (DBUS_BUS_SYSTEM);
581 LOGW ("connection fail\n");
585 edbus_handler = e_dbus_signal_handler_add (edbus_conn, NULL, HOST_OBJECT_PATH, HOST_INTERFACE_NAME, HOST_KEYBOARD_SIGNAL, usb_keyboard_signal_cb, NULL);
586 if (!edbus_handler) {
587 LOGW ("cannot register signal\n");
591 LOGD ("Success register\n");
596 #ifdef HAVE_NOTIFICATION
597 static void delete_notification (NotificationData *noti_data)
599 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
601 if (noti_data->noti_id != 0) {
602 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
603 LOGD ("deleted notification : %s\n", noti_data->launch_app.c_str ());
604 noti_data->noti_id = 0;
608 static void create_notification (NotificationData *noti_data)
610 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
612 notification_h notification = NULL;
615 if (noti_data->noti_id != 0) {
616 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
617 noti_data->noti_id = 0;
620 notification = notification_create (NOTIFICATION_TYPE_ONGOING);
621 if (notification != NULL) {
622 notification_set_pkgname (notification, "isf-panel-efl");
623 notification_set_layout (notification, NOTIFICATION_LY_NOTI_EVENT_SINGLE);
624 notification_set_image (notification, NOTIFICATION_IMAGE_TYPE_ICON, noti_data->icon);
625 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_TITLE, _(noti_data->title), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
626 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_CONTENT, _(noti_data->content), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
627 notification_set_display_applist (notification, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
629 app_control_h service = NULL;
630 if (app_control_create (&service) == APP_CONTROL_ERROR_NONE) {
631 app_control_set_operation (service, APP_CONTROL_OPERATION_DEFAULT);
632 app_control_set_app_id (service, noti_data->launch_app.c_str ());
634 notification_set_launch_option (notification, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)service);
635 ret = notification_insert (notification, ¬i_data->noti_id);
636 if (ret == NOTIFICATION_ERROR_PERMISSION_DENIED) {
637 LOGW ("Failed to insert notification due to permission denied\n");
639 app_control_destroy (service);
642 LOGW ("Failed to create appcontrol\n");
644 notification_free (notification);
647 LOGW ("Failed to create notification\n");
652 static bool tokenize_tag (const String& str, struct image *image_token)
654 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
655 if (str.length () <= 0) {
656 LOGW ("str is empty!!!\n");
660 char **tag_str = NULL;
662 tag_str = eina_str_split (str.c_str (), "\u3013", 0);
667 for (i = 0; tag_str [i]; i++) {
669 if (str.length () == strlen (tag_str[i])) {
679 image_token->path = String (tag_str[i]);
681 if (i - 1 < EMOJI_IMAGE_END)
682 image_token->emoji_option [i - 1] = atoi (tag_str[i]);
684 LOGW ("emoji option is more than EMOJI_IMAGE_END!!!\n");
696 static Evas_Object* get_candidate (const String& str, Evas_Object *parent, int *total_width, uint32 ForeGround, uint32 BackGround, bool HighLight, bool SetBack, int item_num, int item_index)
698 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
700 struct image image_data;
701 int object_width = 0, text_width = 0, image_width = 0, image_height = 0, max_width = 0, button_width = 0;
703 int image_get_width = 0, image_get_height = 0;
704 char image_key [10] = {0, };
705 char **splited_string = NULL;
706 char **sub_splited_string = NULL;
707 double image_rate = 0.0;
708 bool tokenize_result = false;
709 bool candidate_is_long = false;
711 Evas_Object *candidate_object_table = NULL;
712 Evas_Object *candidate_object_table_bg_rect = NULL;
713 Evas_Object *candidate_left_padding = NULL;
715 candidate_object_table = elm_table_add (parent);
717 candidate_left_padding = evas_object_rectangle_add (evas_object_evas_get (parent));
718 evas_object_size_hint_weight_set (candidate_left_padding, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
719 evas_object_size_hint_align_set (candidate_left_padding, EVAS_HINT_FILL, EVAS_HINT_FILL);
720 evas_object_size_hint_min_set (candidate_left_padding, _blank_width, 1);
721 evas_object_color_set (candidate_left_padding, 0, 0, 0, 0);
722 elm_table_pack (candidate_object_table, candidate_left_padding, 0, 0, _blank_width, 1);
723 evas_object_show (candidate_left_padding);
725 object_width += _blank_width;
726 if (item_num > 1 && item_index == 0)
727 button_width = 92 * _width_rate;
731 splited_string = eina_str_split (str.c_str (), "\uE000", 0);
732 if (splited_string) {
733 for (i = 0; splited_string [i]; i++) {
734 if (candidate_is_long)
736 sub_splited_string = eina_str_split (splited_string [i], "\uE001", 0);
737 if (sub_splited_string) {
738 for (j = 0; sub_splited_string [j]; j++) {
739 if (candidate_is_long)
741 tokenize_result = tokenize_tag (sub_splited_string [j], &image_data);
742 if (tokenize_result && _candidate_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
743 _candidate_image [_candidate_image_count] = elm_image_add (parent);
744 snprintf (image_key, sizeof (image_key), "%d",_candidate_image_count);
745 elm_image_file_set (_candidate_image [_candidate_image_count], image_data.path.c_str (), image_key);
746 elm_image_animated_set (_candidate_image [_candidate_image_count], EINA_TRUE);
747 elm_image_animated_play_set (_candidate_image [_candidate_image_count], EINA_TRUE);
748 elm_image_object_size_get (_candidate_image [_candidate_image_count], &image_get_width, &image_get_height);
749 LOGD ("image_path=%s, key=%s\n", image_data.path.c_str (), image_key);
751 if (image_get_height > image_get_width)
752 image_rate = ((double)candidate_image_height / (double)image_get_width);
754 image_rate = ((double)candidate_image_height / (double)image_get_height);
756 image_width = (int)((double)image_get_width * image_rate);
757 image_height = candidate_image_height;
759 if (_candidate_angle == 90 || _candidate_angle == 270)
760 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
762 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
764 if (image_width > max_width) {
765 Evas_Object *candidate_end = edje_object_add (evas_object_evas_get (parent));
766 edje_object_file_set (candidate_end, _candidate_edje_file.c_str (), _candidate_name.c_str ());
767 evas_object_show (candidate_end);
768 edje_object_part_text_set (candidate_end, "candidate", "...");
769 edje_object_scale_set (_candidate_text [_candidate_text_count], _height_rate);
771 text_width = max_width;
772 evas_object_size_hint_min_set (candidate_end, text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
773 if (HighLight || SetBack) {
774 set_highlight_color (candidate_end, ForeGround, BackGround, SetBack);
776 elm_table_pack (candidate_object_table, candidate_end, object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
777 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
779 if (_candidate_image [_candidate_image_count]) {
780 evas_object_del (_candidate_image [_candidate_image_count]);
781 _candidate_image [_candidate_image_count] = NULL;
783 candidate_is_long = true;
787 evas_object_resize (_candidate_image [_candidate_image_count], image_width, image_height);
788 evas_object_show (_candidate_image [_candidate_image_count]);
789 evas_object_size_hint_min_set (_candidate_image [_candidate_image_count], image_width, image_height);
791 elm_table_pack (candidate_object_table, _candidate_image [_candidate_image_count], object_width, 1, image_width, image_height);
792 object_width += image_width;
793 _candidate_image_count++;
795 if (image_data.emoji_option [EMOJI_IMAGE_POP_FLAG] == 1 && image_width > 0 && _candidate_pop_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
796 _candidate_pop_image [_candidate_pop_image_count] = elm_image_add (parent);
797 elm_image_file_set (_candidate_pop_image [_candidate_pop_image_count], ISF_POP_PLAY_ICON_FILE, image_key);
798 evas_object_resize (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
799 evas_object_show (_candidate_pop_image [_candidate_pop_image_count]);
800 evas_object_size_hint_min_set (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
802 elm_table_pack (candidate_object_table, _candidate_pop_image [_candidate_pop_image_count],
803 object_width - candidate_play_image_width_height, image_height - candidate_play_image_width_height - 2,
804 candidate_play_image_width_height, candidate_play_image_width_height);
806 _candidate_pop_image_count++;
809 } else if (strlen (sub_splited_string [j]) > 0 && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
810 _candidate_text [_candidate_text_count] = edje_object_add (evas_object_evas_get (parent));
811 edje_object_file_set (_candidate_text [_candidate_text_count], _candidate_edje_file.c_str (), _candidate_name.c_str ());
812 evas_object_show (_candidate_text [_candidate_text_count]);
813 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", sub_splited_string [j]);
814 edje_object_text_class_set (_candidate_text [_candidate_text_count], "tizen",
815 _candidate_font_name.c_str (), _candidate_font_size);
816 evas_object_text_text_set (_tmp_candidate_text, sub_splited_string [j]);
817 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &text_width, NULL);
819 if (_candidate_angle == 90 || _candidate_angle == 270)
820 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
822 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
824 if (text_width > max_width) {
825 candidate_is_long = true;
826 /* In order to avoid overlap issue, calculate show_string */
827 String show_string = String (sub_splited_string [j]);
828 int show_length = text_width;
829 while (show_length > max_width && show_string.length () > 1) {
830 show_string = show_string.substr (0, show_string.length () - 1);
831 evas_object_text_text_set (_tmp_candidate_text, (show_string + String ("...")).c_str ());
832 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &show_length, NULL);
834 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", (show_string + String ("...")).c_str ());
835 text_width = max_width;
838 evas_object_size_hint_min_set (_candidate_text [_candidate_text_count], text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
839 if (HighLight || SetBack) {
840 set_highlight_color (_candidate_text [_candidate_text_count], ForeGround, BackGround, SetBack);
842 elm_table_pack (candidate_object_table, _candidate_text [_candidate_text_count], object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
843 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
844 _candidate_text_count++;
850 if (splited_string [0])
851 free (splited_string [0]);
853 free (splited_string);
856 if (sub_splited_string) {
857 if (sub_splited_string [0])
858 free (sub_splited_string [0]);
860 free (sub_splited_string);
863 *total_width = object_width + _blank_width;
865 candidate_object_table_bg_rect = edje_object_add (evas_object_evas_get (parent));
866 edje_object_file_set (candidate_object_table_bg_rect, _candidate_edje_file.c_str (), "candidate_object_table");
867 evas_object_size_hint_weight_set (candidate_object_table_bg_rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
868 evas_object_size_hint_align_set (candidate_object_table_bg_rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
869 evas_object_size_hint_min_set (candidate_object_table_bg_rect, *total_width, _item_min_height);
870 elm_table_pack (candidate_object_table, candidate_object_table_bg_rect, 0, 0, *total_width ,_item_min_height);
871 evas_object_show (candidate_object_table_bg_rect);
873 evas_object_size_hint_align_set (candidate_object_table, EVAS_HINT_FILL, EVAS_HINT_FILL);
874 evas_object_size_hint_weight_set (candidate_object_table, EVAS_HINT_EXPAND, 0.0);
876 return candidate_object_table;
879 /////////////////////////////////////////////////////////////////////////////
880 // Implementation of internal functions.
881 /////////////////////////////////////////////////////////////////////////////
883 * @brief Print system time point for panel performance.
885 * @param strInfo The output information.
887 static void check_time (const char *strInfo)
889 gettime (_clock_start, strInfo);
890 ISF_LOG ("%s ppid=%d pid=%d\n", strInfo, getppid (), getpid ());
894 * @brief Flush memory for elm.
898 static void flush_memory (void)
900 elm_cache_all_flush ();
905 * @brief Get ISE geometry information.
906 * Returns the "expected" ISE geometry when kbd_state is ON, otherwise w/h set to 0
908 * @param info The data is used to store ISE position and size.
909 * @param kbd_state The keyboard state.
911 static struct rectinfo get_ise_geometry ()
913 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
915 struct rectinfo info = {0, 0, 0, 0};
919 Ecore_X_Window gnb_win = efl_get_global_navigation_window ();
921 ecore_x_window_size_get (gnb_win, &w, &h);
924 int win_w = _screen_width, win_h = _screen_height;
925 int angle = (_ise_angle == -1) ? efl_get_app_window_angle () : _ise_angle;
928 /* The height of global navigation bar */
931 if (angle == 90 || angle == 270) {
932 win_w = _screen_height;
933 win_h = _screen_width;
938 /* If we have geometry reported by ISE, use the geometry information */
939 if (_ise_reported_geometry.valid && _ise_reported_geometry.angle == angle) {
940 info = _ise_reported_geometry.geometry;
941 /* But still, if the current ISE is not in SHOW state, set w/h to 0 */
942 if (_ise_state != WINDOW_STATE_SHOW) {
943 info.pos_y = (win_h > win_w) ? win_h : win_w;
948 /* READ ISE's SIZE HINT HERE */
951 int pos_x, pos_y, width, height;
952 if (ecore_x_e_window_rotation_geometry_get (_ise_window, angle,
953 &pos_x, &pos_y, &width, &height)) {
957 if (angle == 90 || angle == 270) {
962 info.height = height;
965 info.pos_x = (int)info.width > win_w ? 0 : (win_w - info.width) / 2;
966 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
968 info.pos_y = (win_h > win_w) ? win_h : win_w;
972 if (_ise_state == WINDOW_STATE_SHOW) {
973 info.pos_y = win_h - info.height - gnb_height;
975 info.pos_y = (win_h > win_w) ? win_h : win_w;
981 LOGD ("angle : %d, w_angle : %d, mode : %d, Geometry : %d %d %d %d\n",
983 _info_manager->get_current_toolbar_mode (),
984 info.pos_x, info.pos_y, info.width, info.height);
993 // FIXME: Get the ISE's SIZE.
1001 _ise_width = info.width;
1002 _ise_height = info.height;
1009 * @brief Set keyboard geometry for autoscroll.
1010 * This includes the ISE geometry together with candidate window
1012 * @param kbd_state The keyboard state.
1014 static void set_keyboard_geometry_atom_info (Ecore_X_Window window, struct rectinfo ise_rect)
1016 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1018 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
1021 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1022 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1023 ise_rect.width = _candidate_width;
1024 ise_rect.height = _candidate_height;
1026 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
1027 ise_rect.width = _soft_candidate_width;
1028 ise_rect.height = _soft_candidate_height;
1031 int angle = efl_get_app_window_angle ();
1032 if (angle == 90 || angle == 270)
1033 ise_rect.pos_y = _screen_width - ise_rect.height;
1035 ise_rect.pos_y = _screen_height - ise_rect.height;
1037 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1038 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1039 _candidate_valid_height = ui_candidate_get_valid_height ();
1040 if ((_candidate_height - _candidate_valid_height) > _ise_height) {
1041 _candidate_valid_height = _candidate_height;
1042 ise_rect.pos_y = ise_rect.pos_y + ise_rect.height - _candidate_height;
1043 ise_rect.height = _candidate_height;
1045 ise_rect.pos_y -= _candidate_valid_height;
1046 ise_rect.height += _candidate_valid_height;
1052 ecore_x_e_illume_keyboard_geometry_set (window, ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1053 LOGD ("KEYBOARD_GEOMETRY_SET : %d %d %d %d\n", ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1054 SCIM_DEBUG_MAIN (3) << " KEYBOARD_GEOMETRY x=" << ise_rect.pos_x << " y=" << ise_rect.pos_y
1055 << " width=" << ise_rect.width << " height=" << ise_rect.height << "\n";
1057 /* even the kbd_state is OFF, consider the keyboard is still ON if we have candidate opened */
1058 if (ise_rect.width == 0 && ise_rect.height == 0) {
1059 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1061 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1063 if (_ise_angle == 0 || _ise_angle == 180) {
1064 _portrait_recent_ise_geometry.valid = true;
1065 _portrait_recent_ise_geometry.geometry = ise_rect;
1068 _landscape_recent_ise_geometry.valid = true;
1069 _landscape_recent_ise_geometry.geometry = ise_rect;
1076 * @brief Get ISE index according to uuid.
1078 * @param uuid The ISE uuid.
1080 * @return The ISE index
1082 static unsigned int get_ise_index (const String uuid)
1084 unsigned int index = 0;
1085 if (uuid.length () > 0) {
1086 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1087 if (uuid == _ime_info[i].appid) {
1097 static void set_keyboard_engine (String active_uuid)
1099 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
1100 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
1101 if (active_uuid != keyboard_uuid) {
1102 _info_manager->change_factory (active_uuid);
1103 _config->write (IMENGINE_KEY, active_uuid);
1108 static void _update_ime_info(void)
1110 std::vector<String> ise_langs;
1113 isf_pkg_select_all_ime_info_db(_ime_info);
1115 /* Update _groups */
1117 for (size_t i = 0; i < _ime_info.size (); ++i) {
1118 scim_split_string_list(ise_langs, _ime_info[i].languages);
1119 for (size_t j = 0; j < ise_langs.size (); j++) {
1120 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
1121 _groups[ise_langs[j]].push_back (i);
1127 static void _initialize_ime_info (void)
1129 std::vector<ImeInfoDB>::iterator iter;
1130 VectorPairStringUint32 ime_on_off;
1131 // Store is_enabled values of each keyboard
1132 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1133 if (iter->mode == TOOLBAR_HELPER_MODE) {
1134 ime_on_off.push_back (std::make_pair (iter->appid, iter->is_enabled));
1137 // Delete the whole ime_info DB and reload
1138 isf_db_delete_ime_info ();
1139 _update_ime_info ();
1140 // Restore is_enabled value to valid keyboards
1141 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1142 if (iter->mode == TOOLBAR_HELPER_MODE) {
1143 for (VectorPairStringUint32::iterator it = ime_on_off.begin (); it != ime_on_off.end (); it++) {
1144 if (it->first.compare (iter->appid) == 0) {
1145 if (it->second != iter->is_enabled) {
1146 iter->is_enabled = it->second;
1147 isf_db_update_is_enabled_by_appid (iter->appid.c_str (), static_cast<bool>(iter->is_enabled));
1149 ime_on_off.erase (it);
1157 #if HAVE_PKGMGR_INFO
1159 * @brief Insert or update ime_info data with pkgid.
1161 * @param pkgid pkgid to insert/update ime_info table.
1163 * @return 1 on successfull insert, 2 on successful update, -1 if pkgid is not IME package, otherwise return 0.
1165 static int _isf_insert_ime_info_by_pkgid(const char *pkgid)
1168 pkgmgrinfo_pkginfo_h handle = NULL;
1169 int result = 0; // 0: not IME, 1: Inserted, 2: Updated (because of the same appid)
1170 uid_t uid = getpid ();
1174 LOGW ("pkgid is null.\n");
1178 /* Try to get in global packages */
1179 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &handle);
1180 if (ret != PMINFO_R_OK) {
1181 /* Try to get in user packages */
1182 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, uid, &handle);
1183 if (ret != PMINFO_R_OK) {
1184 LOGW ("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d\n", pkgid, ret);
1193 /* Try to get in user packages */
1194 ret = pkgmgrinfo_appinfo_get_usr_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result, uid);
1197 /* Try to get in global packages */
1198 ret = pkgmgrinfo_appinfo_get_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result);
1201 if (ret != PMINFO_R_OK) {
1202 LOGW ("Failed to call %s failed(%d)\n", user ? "pkgmgrinfo_appinfo_get_usr_list" : "pkgmgrinfo_appinfo_get_list", ret);
1209 pkgmgrinfo_pkginfo_destroy_pkginfo (handle);
1215 * @brief Timer to start initial Helper ISE if the active (selected) 3rd party keyboard is uninstalled.
1217 * @param data User data
1219 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1220 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1222 static Eina_Bool _start_default_helper_timer(void *data)
1224 std::vector<String> total_appids;
1225 std::vector<ImeInfoDB>::iterator it;
1226 VectorPairStringUint32::iterator iter;
1228 /* Let panel know that ise is deleted... */
1229 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1230 total_appids.push_back(it->appid);
1232 if (total_appids.size() > 0)
1233 _info_manager->update_ise_list (total_appids);
1235 LOGD ("Try to start the initial helper\n");
1236 set_active_ise(_initial_ise_uuid, true);
1238 for (iter = g_pkgids_to_be_uninstalled.begin (); iter != g_pkgids_to_be_uninstalled.end (); iter++) {
1239 if (iter->first.compare(g_stopped_helper_pkgid) == 0) {
1240 g_pkgids_to_be_uninstalled.erase (iter);
1244 g_stopped_helper_pkgid = "";
1246 g_start_default_helper_timer = NULL;
1247 return ECORE_CALLBACK_CANCEL;
1251 * @brief Timer to release uninstalled IME related info; g_pkgids_to_be_uninstalled has appid and is_enabled.
1253 * @param data User data
1255 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1256 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1258 static Eina_Bool _release_uninstalled_pkginfo_timer(void *data)
1260 g_pkgids_to_be_uninstalled.clear ();
1261 g_release_uninstalled_ime_info_timer = NULL;
1262 return ECORE_CALLBACK_CANCEL;
1266 * @brief Called when the package is installed, uninstalled or updated, and the progress of the request to the package manager changes.
1268 * @param[in] type The type of the package to be installed, uninstalled or updated
1269 * @param[in] package The name of the package to be installed, uninstalled or updated
1270 * @param[in] event_type The type of the request to the package manager
1271 * @param[in] event_state The current state of the request to the package manager
1272 * @param[in] progress The progress for the request that is being processed by the package manager \n
1273 * The range of progress is from 0 to 100
1274 * @param[in] error The error code when the package manager failed to process the request
1275 * @param[in] user_data The user data passed from package_manager_set_event_cb()
1276 * @see package_manager_set_event_cb()
1277 * @see package_manager_unset_event_cb()
1279 INFO: Package install/update/uninstall scenario
1280 Install and Uninstall are obviously simple.
1281 Install: just INSTALL
1282 Uninstall: just UNINSTALL
1283 Update package (change the source codes in IME project and Run As again), there are four scenarios:
1286 2. UNINSTALL -> INSTALL
1287 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1288 and change Application ID in tizen-manifest.xml file and Run As.
1289 3. UPDATE -> INSTALL
1290 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1291 and change Application ID in tizen-manifest.xml file and Run As.
1292 At UPDATE event, pkgid (package parameter) is invalid...
1294 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1295 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1297 If multiple packages (including non-IME pkgs) are uninstalled and installed; Z300H UPS (ultra power saving) mode scenario.
1298 For example, A and B packages are uninstalled and installed, the package manager works in this order: A UNINSTALL -> B UNINSTALL -> A INSTALL -> B INSTALL
1300 Assuming IMEngine won't be changed through this. IMEngine might have multiple appids for one pkgid.
1301 Assuming preinstalled IME won't be changed through this.
1303 static void _package_manager_event_cb (const char *type, const char *package, package_manager_event_type_e event_type, package_manager_event_state_e event_state, int progress, package_manager_error_e error, void *user_data)
1305 String current_ime_appid; // now appid is uuid.
1306 std::vector<String> appids;
1307 std::vector<String> total_appids;
1308 std::vector<ImeInfoDB>::iterator it;
1309 std::vector<String>::iterator it2;
1310 VectorPairStringUint32::iterator it3;
1313 if (!package || !type)
1316 if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
1317 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1318 LOGD ("type=%s package=%s event_type=UPDATE event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1320 ret = _isf_insert_ime_info_by_pkgid (package); // If package is not IME, -1 would be returned.
1321 if (ret == 1) { // In case the package is updated with the changed appid. In this case, there will be two IMEs
1322 ret = isf_db_select_appids_by_pkgid (package, appids);
1324 if (_ime_info.size () > 0 && _ime_info [get_ise_index (appids.front ())].is_enabled)
1325 isf_db_update_is_enabled_by_appid(appids.back ().c_str (), true);
1326 isf_db_delete_ime_info_by_appid (appids.front ().c_str ());
1329 _update_ime_info ();
1331 /* Let panel know that ise list is changed... */
1332 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1333 total_appids.push_back(it->appid);
1335 if (total_appids.size() > 0)
1336 _info_manager->update_ise_list (total_appids);
1338 if (ret > 1 && _soft_keyboard_launched) { // If the previous appid of pkgid is the current IME, restart it with new appid.
1339 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1340 if (current_ime_appid.compare (appids.front ()) == 0) {
1341 LOGD ("Stop IME(%s)\n", current_ime_appid.c_str ());
1342 _info_manager->hide_helper (current_ime_appid);
1343 _info_manager->stop_helper (current_ime_appid);
1344 LOGD ("Start IME(%s)\n", appids.back ().c_str ());
1345 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids.back ());
1346 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1347 _info_manager->start_helper (appids.back ());
1351 else if (ret == 2) { // In case IME package is just updated...
1352 _update_ime_info ();
1354 if (_soft_keyboard_launched) { // If package is the current IME, restart it.
1355 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1356 if (isf_db_select_appids_by_pkgid(package, appids)) {
1357 if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the current ISE package is updated, restart it.
1358 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1359 if (it->mode == TOOLBAR_HELPER_MODE && it->appid.compare(current_ime_appid) == 0) { // Make sure it's Helper ISE...
1360 LOGD ("Restart IME(%s)\n", current_ime_appid.c_str ());
1361 _info_manager->hide_helper (current_ime_appid);
1362 _info_manager->stop_helper (current_ime_appid);
1363 _info_manager->start_helper (current_ime_appid);
1371 else if (ret == 0) { // For example, this happens if appid is changed in IME project and Run As again. Assuming only Helper (3rd party) might be updated and there is one appid per each pkgid...
1372 if (isf_db_select_appids_by_pkgid(package, appids) == 1) {
1373 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1374 if (it->pkgid.compare(package) == 0) {
1375 g_pkgids_to_be_updated_and_installed.push_back (std::make_pair (it->pkgid, it->is_enabled));
1379 if (it == _ime_info.end ()) // Probably not going to happen.
1380 g_pkgids_to_be_updated_and_installed.push_back(std::make_pair (String(package), 0));
1382 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1383 if (_soft_keyboard_launched && std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the updated IME is the current ISE...
1384 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1385 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1386 LOGD ("Stop IME(%s)\n", current_ime_appid.c_str ());
1387 _info_manager->hide_helper (current_ime_appid);
1388 _info_manager->stop_helper (current_ime_appid);
1389 _soft_keyboard_launched = false;
1390 g_updated_helper_pkgid = package;
1396 if (appids.size () > 0) // Probably appids size is 1.
1397 LOGD ("Delete IME(%s)\n", appids[0].c_str ());
1398 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1401 /* Let panel know that ise is deleted... */
1402 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1403 total_appids.push_back(it->appid);
1405 if (total_appids.size() > 0)
1406 _info_manager->update_ise_list (total_appids);
1410 LOGW ("isf_db_select_appids_by_pkgid returned %d.\n", ret);
1415 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL) {
1416 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1417 LOGD ("type=%s package=%s event_type=INSTALL event_state=COMPLETED progress=%d error=%d\n", type, package, progress, error);
1419 ///////////////// UNINSTALL -> INSTALL and if the uninstalled IME is reinstalled /////////////////
1420 if (g_stopped_helper_pkgid.compare(package) == 0 && g_start_default_helper_timer) {
1421 LOGD ("Cancel timer to start the default IME\n");
1422 ecore_timer_del(g_start_default_helper_timer);
1423 g_start_default_helper_timer = NULL;
1424 g_stopped_helper_pkgid = "";
1426 ret = _isf_insert_ime_info_by_pkgid(package);
1428 /* Find appid by pkgid. There might be multiple appid, but assume Helper always has one appid.
1429 And appid can be changed, but pkgid won't be changed. */
1430 ret = isf_db_select_appids_by_pkgid(package, appids);
1431 if (ret == 1 && appids.size () == 1) {
1432 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1433 if (it3->first.compare(package) == 0) {
1435 isf_db_update_is_enabled_by_appid(appids[0].c_str (), (bool)it3->second);
1439 /* Let panel know that ise is added... */
1440 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1441 total_appids.push_back(it->appid);
1443 if (total_appids.size() > 0)
1444 _info_manager->update_ise_list (total_appids);
1446 LOGD ("Restart IME(%s)\n", appids[0].c_str ());
1447 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids[0]);
1448 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1449 _info_manager->start_helper (appids[0]);
1450 _soft_keyboard_launched = true;
1452 g_pkgids_to_be_uninstalled.erase (it3);
1458 LOGW ("isf_db_select_appids_by_pkgid returned %d.\n", ret);
1462 /* Let panel know that ise is added... */
1463 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1464 total_appids.push_back(it->appid);
1466 if (total_appids.size() > 0)
1467 _info_manager->update_ise_list (total_appids);
1471 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.\n", ret);
1474 else { // If new package is installed...
1475 ret = _isf_insert_ime_info_by_pkgid(package); // If package is not IME, -1 would be returned.
1476 if (ret > 0) { // In case package is IME...
1477 ///////////////// INSTALL /////////////////
1480 /* Let panel know that ise is added... */
1481 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1482 total_appids.push_back(it->appid);
1484 if (total_appids.size() > 0)
1485 _info_manager->update_ise_list (total_appids);
1486 ///////////////// END /////////////////
1488 /* For example, the following happens if appid is changed in IME project and Run As again. The appid would be changed this time.
1489 Assuming only Helper (3rd party) might be installed after update or uninstall and there is one appid per each pkgid...*/
1491 ///////////////// UPDATE -> INSTALL /////////////////
1492 for (it3 = g_pkgids_to_be_updated_and_installed.begin (); it3 != g_pkgids_to_be_updated_and_installed.end (); it3++) {
1493 if (it3->first.compare(package) == 0) {
1495 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1496 if (it->pkgid.compare(package) == 0) {
1497 it->is_enabled = it3->second;
1498 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1503 g_pkgids_to_be_updated_and_installed.erase (it3);
1507 if (g_updated_helper_pkgid.compare(package) == 0) {
1508 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1509 if (it->mode == TOOLBAR_HELPER_MODE && it->pkgid.compare(package) == 0) {
1510 LOGD ("Start IME(%s)\n", it->appid.c_str ());
1511 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), it->appid);
1512 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1513 _info_manager->start_helper (it->appid);
1514 _soft_keyboard_launched = true;
1518 g_updated_helper_pkgid = "";
1521 ///////////////// END /////////////////
1523 ///////////////// UNINSTALL -> INSTALL /////////////////
1524 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1525 if (it3->first.compare(package) == 0) {
1527 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1528 if (it->pkgid.compare(package) == 0) {
1529 it->is_enabled = it3->second;
1530 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1535 g_pkgids_to_be_uninstalled.erase (it3);
1539 ///////////////// END /////////////////
1541 else if (ret == 0) {
1542 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.\n", ret);
1547 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL) {
1548 switch (event_state) {
1549 case PACKAGE_MANAGER_EVENT_STATE_STARTED:
1550 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=STARTED progress=%d error=%d\n", type, package, progress, error);
1552 // Need to check if there is "http://tizen.org/category/ime" category; it can be done by comparing pkgid with ime_info db.
1554 if (_ime_info.size() == 0)
1557 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1558 if (it->pkgid.compare(package) == 0 && it->is_preinstalled == 0) { // Ignore if it's preinstalled IME and IMEngine.
1565 // There might be more than one appid for one pkgid, but let's assume Helper always has one appid per a pkgid. Stop Helper ISE, but not delete it from ime_info db.
1566 LOGD ("%s for pkgid(\"%s\") is about to be deleted\n", it->appid.c_str (), package);
1567 g_pkgids_to_be_uninstalled.push_back(std::make_pair (String(package), it->is_enabled));
1569 if (_soft_keyboard_launched && isf_db_select_appids_by_pkgid(package, appids)) {
1570 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1571 if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the uninstalled IME is the current ISE... appids size is probably 1.
1572 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1573 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1574 LOGD ("Stop IME(%s)\n", current_ime_appid.c_str ());
1575 _info_manager->hide_helper (current_ime_appid);
1576 _info_manager->stop_helper (current_ime_appid);
1577 _soft_keyboard_launched = false;
1578 g_stopped_helper_pkgid = package;
1588 case PACKAGE_MANAGER_EVENT_STATE_COMPLETED:
1589 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=COMPLETED progress=%d error=%d\n", type, package, progress, error);
1591 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1592 if (it3->first.compare(package) == 0) {
1593 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1597 if (g_stopped_helper_pkgid.compare(package) == 0) { // If the uninstalled ISE is the current ISE, start the initial helper ISE by timer.
1598 if (g_start_default_helper_timer)
1599 ecore_timer_del(g_start_default_helper_timer);
1600 LOGD ("Add timer to start the default IME\n");
1601 g_start_default_helper_timer = ecore_timer_add(3.0, _start_default_helper_timer, NULL);
1603 else { // Need to clean up g_pkgids_to_be_uninstalled info unless the same package is installed again; e.g., UNINSTALL -> INSTALL case.
1604 if (g_release_uninstalled_ime_info_timer)
1605 ecore_timer_del(g_release_uninstalled_ime_info_timer);
1606 LOGD ("Add timer to release uninstalled IME pkg info\n");
1607 g_release_uninstalled_ime_info_timer = ecore_timer_add(7.0, _release_uninstalled_pkginfo_timer, NULL);
1610 /* Let panel know that ise is deleted... */
1611 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1612 total_appids.push_back(it->appid);
1614 if (total_appids.size() > 0)
1615 _info_manager->update_ise_list (total_appids);
1622 case PACKAGE_MANAGER_EVENT_STATE_FAILED:
1623 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=FAILED progress=%d error=%d\n", type, package, progress, error);
1625 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1626 if (it3->first.compare(package) == 0) {
1627 // Update _ime_info for sure...
1630 if (g_stopped_helper_pkgid.compare(package) == 0) {
1631 ret = isf_db_select_appids_by_pkgid(package, appids);
1632 if (ret == 1 && appids.size () == 1) {
1633 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1634 if (it->appid.compare(appids[0]) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1635 LOGD ("Restart IME(%s)\n", appids[0].c_str ());
1636 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1637 _info_manager->start_helper (appids[0]);
1638 _soft_keyboard_launched = true;
1644 LOGW ("isf_db_select_appids_by_pkgid returned %d.\n", ret);
1646 g_stopped_helper_pkgid = "";
1649 g_pkgids_to_be_uninstalled.erase (it3);
1663 * @brief Set keyboard ISE.
1665 * @param uuid The keyboard ISE's uuid.
1667 * @return false if keyboard ISE change is failed, otherwise return true.
1669 static bool set_keyboard_ise (const String &uuid)
1671 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1673 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1675 if (TOOLBAR_HELPER_MODE == mode) {
1676 String pre_uuid = _info_manager->get_current_helper_uuid ();
1677 _info_manager->hide_helper (pre_uuid);
1678 _info_manager->stop_helper (pre_uuid);
1679 _soft_keyboard_launched = false;
1680 } else if (TOOLBAR_KEYBOARD_MODE == mode) {
1681 uint32 kbd_option = 0;
1682 String kbd_uuid, kbd_name;
1683 isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
1684 if (kbd_uuid == uuid)
1688 _info_manager->change_factory (uuid);
1690 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
1691 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
1697 * @brief Set helper ISE.
1699 * @param uuid The helper ISE's uuid.
1700 * @param launch_ise The flag for launching helper ISE.
1702 * @return false if helper ISE change is failed, otherwise return true.
1704 static bool set_helper_ise (const String &uuid, bool launch_ise)
1706 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1708 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1709 String pre_uuid = _info_manager->get_current_helper_uuid ();
1710 LOGD ("pre_appid=%s, appid=%s, launch_ise=%d, %d\n", pre_uuid.c_str(), uuid.c_str(), launch_ise, _soft_keyboard_launched);
1711 if (pre_uuid == uuid && _soft_keyboard_launched)
1714 if (TOOLBAR_HELPER_MODE == mode && pre_uuid.length () > 0 && _soft_keyboard_launched) {
1715 _info_manager->hide_helper (pre_uuid);
1716 _info_manager->stop_helper (pre_uuid);
1717 _soft_keyboard_launched = false;
1718 LOGD ("stop helper : %s\n", pre_uuid.c_str ());
1722 LOGD ("Start helper (%s)\n", uuid.c_str ());
1724 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1725 if (_info_manager->start_helper (uuid))
1726 _soft_keyboard_launched = true;
1728 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), uuid);
1734 * @brief Set active ISE.
1736 * @param uuid The ISE's uuid.
1737 * @param launch_ise The flag for launching helper ISE.
1739 * @return false if ISE change is failed, otherwise return true.
1741 static bool set_active_ise (const String &uuid, bool launch_ise)
1743 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1744 LOGD ("set ISE (%s) %d\n", uuid.c_str(), launch_ise);
1746 if (uuid.length () <= 0)
1749 bool ise_changed = false, valid = false;
1751 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1752 if (!uuid.compare (_ime_info[i].appid)) {
1753 if (TOOLBAR_KEYBOARD_MODE == _ime_info[i].mode)
1754 ise_changed = set_keyboard_ise (_ime_info[i].appid);
1755 else if (TOOLBAR_HELPER_MODE == _ime_info[i].mode) {
1756 if (_ime_info[i].is_enabled) {
1757 if (_ime_info[i].exec == String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
1758 /* If IME so is deleted somehow, main() in scim_helper_launcher.cpp will return -1.
1759 Checking HelperModule validity seems necessary here. */
1760 HelperModule helper_module (_ime_info[i].module_name);
1761 if (helper_module.valid ())
1763 helper_module.unload ();
1766 /* executable type */
1771 ise_changed = set_helper_ise (_ime_info[i].appid, launch_ise);
1773 LOGW ("Helper ISE(appid=\"%s\",module_name=\"%s\") is not valid.\n", _ime_info[i].appid.c_str (), _ime_info[i].module_name.c_str ());
1776 LOGW ("Helper ISE(appid=\"%s\") is not enabled.\n", _ime_info[i].appid.c_str ());
1779 _info_manager->set_current_toolbar_mode (_ime_info[i].mode);
1781 _info_manager->set_current_helper_option (_ime_info[i].options);
1782 _info_manager->set_current_ise_name (_ime_info[i].label);
1785 _ise_state = WINDOW_STATE_HIDE;
1786 _candidate_mode = SOFT_CANDIDATE_WINDOW;
1787 _candidate_port_line = ONE_LINE_CANDIDATE;
1788 _soft_candidate_width = 0;
1789 _soft_candidate_height = 0;
1790 if (_candidate_window)
1791 ui_create_candidate_window ();
1793 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _ime_info[i].appid);
1794 scim_global_config_flush ();
1798 _info_manager->reload_config ();
1800 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
1811 * @brief Load ISF configuration and ISEs information.
1813 static void load_config (void)
1815 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1817 /* Read configurations. */
1818 if (!_config.null ()) {
1819 bool shared_ise = _config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), false);
1820 _info_manager->set_should_shared_ise (shared_ise);
1822 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
1824 isf_load_ise_information (ALL_ISE, _config);
1828 * @brief Reload config callback function for ISF panel.
1830 * @param config The config pointer.
1832 static void config_reload_cb (const ConfigPointer &config)
1834 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1836 /* load_config (); */
1839 //////////////////////////////////////////////////////////////////////
1840 // Start of Candidate Functions
1841 //////////////////////////////////////////////////////////////////////
1843 * @brief Get candidate window valid height for autoscroll.
1845 * @return The valid height.
1847 static int ui_candidate_get_valid_height (void)
1849 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
1854 if (_candidate_window) {
1855 if (_candidate_state == WINDOW_STATE_SHOW)
1856 angle = _candidate_angle;
1858 angle = efl_get_app_window_angle ();
1860 if (_aux_area_visible && _candidate_area_1_visible) {
1861 if (angle == 90 || angle == 270)
1862 height = _candidate_land_height_min_2;
1864 height = _candidate_port_height_min_2;
1866 if (angle == 90 || angle == 270)
1867 height = _candidate_land_height_min;
1869 height = _candidate_port_height_min;
1876 * @brief Resize candidate window size.
1878 * @param new_width New width for candidate window.
1879 * @param new_height New height for candidate window.
1881 static void ui_candidate_window_resize (int new_width, int new_height)
1883 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " width:" << new_width << " height:" << new_height << "\n";
1885 if (!_candidate_window)
1890 LOGD ("%s (w: %d, h: %d)\n", __func__, new_width, new_height);
1891 evas_object_resize (_aux_line, new_width, 2);
1892 _candidate_width = new_width;
1893 _candidate_height = new_height;
1894 if (_candidate_state == WINDOW_STATE_SHOW)
1895 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
1897 if (_candidate_state == WINDOW_STATE_SHOW && _candidate_mode == FIXED_CANDIDATE_WINDOW) {
1898 height = ui_candidate_get_valid_height ();
1899 if ((_ise_width == 0 && _ise_height == 0) ||
1900 (_ise_height > 0 && _candidate_valid_height != height) ||
1901 (_ise_height > 0 && (_candidate_height - height) > _ise_height) ||
1902 ((_candidate_angle == 90 || _candidate_angle == 270) && (_ise_width < _screen_height)) ||
1903 ((_candidate_angle == 0 || _candidate_angle == 180) && (_ise_width > _screen_width ))) {
1905 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
1907 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
1911 /* Get height for portrait and landscape */
1912 int port_width = _candidate_port_width;
1913 int port_height = _candidate_port_height_min;
1914 int land_width = _candidate_land_width;
1915 int land_height = _candidate_land_height_min;
1916 if (_candidate_angle == 90 || _candidate_angle == 270) {
1917 land_height = new_height;
1918 if (land_height == _candidate_land_height_min_2) {
1919 port_height = _candidate_port_height_min_2;
1920 } else if (land_height == _candidate_land_height_max) {
1921 port_height = _candidate_port_height_max;
1922 } else if (land_height == _candidate_land_height_max_2) {
1923 port_height = _candidate_port_height_max_2;
1926 port_height = new_height;
1927 if (port_height == _candidate_port_height_min_2) {
1928 land_height = _candidate_land_height_min_2;
1929 } else if (port_height == _candidate_port_height_max) {
1930 land_height = _candidate_land_height_max;
1931 } else if (port_height == _candidate_port_height_max_2) {
1932 land_height = _candidate_land_height_max_2;
1936 LOGD ("window_rotation_geometry_set (_candidate_window), port (%d, %d), land (%d, %d)\n",
1937 port_width, port_height, land_width, land_height);
1941 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
1942 0, 0, 0, port_width, port_height);
1943 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
1944 90, 0, 0, land_height, land_width);
1945 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
1946 180, 0, 0, port_width, port_height);
1947 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
1948 270, 0, 0, land_height, land_width);
1951 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
1952 0, 0, 0, port_width, port_height);
1953 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
1954 90, 0, 0, land_height, land_width);
1955 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
1956 180, 0, 0, port_width, port_height);
1957 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
1958 270, 0, 0, land_height, land_width);
1963 * @brief This function will show/hide widgets of candidate window,
1964 * and resize candidate window size according to aux_area/candidate_area.
1966 static void ui_candidate_window_adjust (void)
1968 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1969 if (!_candidate_window)
1972 int x, y, width, height;
1974 /* Get candidate window size */
1977 if (_candidate_angle == 90 || _candidate_angle == 270) {
1978 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
1979 &x, &y, &height, &width);
1981 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
1982 &x, &y, &width, &height);
1986 if (_candidate_angle == 90 || _candidate_angle == 270)
1987 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &height, &width);
1989 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
1992 if (_aux_area_visible && _candidate_area_2_visible) {
1993 evas_object_show (_aux_line);
1994 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
1995 if (_candidate_angle == 90 || _candidate_angle == 270) {
1996 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
1997 _ise_height > _candidate_land_height_max_2 - _candidate_land_height_min_2)
1998 ui_candidate_window_resize (width, _candidate_land_height_min_2 + _ise_height);
2000 ui_candidate_window_resize (width, _candidate_land_height_max_2);
2001 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2002 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min_2);
2003 evas_object_move (_scroller_bg, 0, _candidate_land_height_min_2);
2004 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2006 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2007 _ise_height > _candidate_port_height_max_2 - _candidate_port_height_min_2)
2008 ui_candidate_window_resize (width, _candidate_port_height_min_2 + _ise_height);
2010 ui_candidate_window_resize (width, _candidate_port_height_max_2);
2011 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2012 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min_2);
2013 evas_object_move (_scroller_bg, 0, _candidate_port_height_min_2);
2014 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2016 } else if (_aux_area_visible && _candidate_area_1_visible) {
2017 evas_object_show (_aux_line);
2018 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2019 if (_candidate_angle == 90 || _candidate_angle == 270) {
2020 ui_candidate_window_resize (width, _candidate_land_height_min_2);
2021 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2022 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2024 ui_candidate_window_resize (width, _candidate_port_height_min_2);
2025 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2026 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2028 } else if (_aux_area_visible) {
2029 evas_object_hide (_aux_line);
2030 ui_candidate_window_resize (width, _aux_height + 2);
2031 evas_object_resize (_candidate_bg, width, _aux_height + 2);
2032 } else if (_candidate_area_2_visible) {
2033 evas_object_hide (_aux_line);
2034 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2035 if (_candidate_angle == 90 || _candidate_angle == 270) {
2036 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2037 _ise_height > _candidate_land_height_max - _candidate_land_height_min)
2038 ui_candidate_window_resize (width, _candidate_land_height_min + _ise_height);
2040 ui_candidate_window_resize (width, _candidate_land_height_max);
2041 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3]);
2042 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min);
2043 evas_object_move (_scroller_bg, 0, _candidate_land_height_min);
2044 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2046 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2047 _ise_height > _candidate_port_height_max - _candidate_port_height_min)
2048 ui_candidate_window_resize (width, _candidate_port_height_min + _ise_height);
2050 ui_candidate_window_resize (width, _candidate_port_height_max);
2051 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
2052 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min);
2053 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
2054 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2057 evas_object_hide (_aux_line);
2058 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2059 if (_candidate_angle == 90 || _candidate_angle == 270) {
2060 ui_candidate_window_resize (width, _candidate_land_height_min);
2061 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3]);
2062 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2064 ui_candidate_window_resize (width, _candidate_port_height_min);
2065 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
2066 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2072 * @brief Rotate candidate window.
2074 * @param angle The angle of candidate window.
2076 static void ui_candidate_window_rotate (int angle)
2078 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2079 if (!_candidate_window)
2082 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
2084 if (angle == 90 || angle == 270) {
2085 _candidate_scroll_width = _candidate_scroll_width_max;
2086 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
2087 evas_object_resize (_aux_area, _aux_land_width, _aux_height);
2088 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_max, _item_min_height);
2089 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_min);
2090 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_min + 6);
2092 _candidate_scroll_width = _candidate_scroll_width_min;
2093 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
2094 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
2095 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
2096 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_max);
2097 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
2100 evas_object_hide (_candidate_area_2);
2101 _candidate_area_2_visible = false;
2102 ui_candidate_window_adjust ();
2103 if (_candidate_area_1_visible) {
2104 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2105 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
2106 ui_tts_focus_rect_hide ();
2112 * @brief This function is used to judge whether candidate window should be hidden.
2114 * @return true if candidate window should be hidden, otherwise return false.
2116 static bool ui_candidate_can_be_hide (void)
2118 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2120 if (_aux_area_visible || _candidate_area_1_visible || _candidate_area_2_visible)
2127 * @brief Delete check candidate window size timer.
2131 static void ui_candidate_delete_check_size_timer (void)
2133 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2135 if (_check_size_timer != NULL) {
2136 ecore_timer_del (_check_size_timer);
2137 _check_size_timer = NULL;
2142 * @brief Callback function for check candidate window size timer.
2144 * @param data Data to pass when it is called.
2146 * @return ECORE_CALLBACK_CANCEL
2148 static Eina_Bool ui_candidate_check_size_timeout (void *data)
2150 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2152 ui_candidate_delete_check_size_timer ();
2153 ui_candidate_window_resize (_candidate_width, _candidate_height);
2154 ui_settle_candidate_window ();
2155 return ECORE_CALLBACK_CANCEL;
2159 * @brief Delete longpress timer.
2163 static void ui_candidate_delete_longpress_timer (void)
2165 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2167 if (_longpress_timer != NULL) {
2168 ecore_timer_del (_longpress_timer);
2169 _longpress_timer = NULL;
2174 * @brief Callback function for candidate longpress timer.
2176 * @param data Data to pass when it is called.
2178 * @return ECORE_CALLBACK_CANCEL
2180 static Eina_Bool ui_candidate_longpress_timeout (void *data)
2182 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2184 int index = (int)GPOINTER_TO_INT (data);
2185 ui_candidate_delete_longpress_timer ();
2187 _info_manager->send_longpress_event (_click_object, index);
2188 return ECORE_CALLBACK_CANCEL;
2192 * @brief Delete destroy timer.
2196 static void ui_candidate_delete_destroy_timer (void)
2198 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2200 if (_destroy_timer != NULL) {
2201 ecore_timer_del (_destroy_timer);
2202 _destroy_timer = NULL;
2207 * @brief Callback function for destroy timer.
2209 * @param data Data to pass when it is called.
2211 * @return ECORE_CALLBACK_CANCEL
2213 static Eina_Bool ui_candidate_destroy_timeout (void *data)
2215 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2217 ui_candidate_delete_destroy_timer ();
2218 ui_destroy_candidate_window ();
2219 return ECORE_CALLBACK_CANCEL;
2224 * @brief Callback function for off_prepare_done.
2226 * @param data Data to pass when it is called.
2228 * @return ECORE_CALLBACK_CANCEL
2230 static Eina_Bool off_prepare_done_timeout (void *data)
2232 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2234 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
2235 // WILL_HIDE_REQUEST_DONE Ack to WM
2236 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
2237 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
2238 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)\n",
2239 root_window, _control_window);
2240 _off_prepare_done_timer = NULL;
2242 return ECORE_CALLBACK_CANCEL;
2247 * @brief Delete candidate hide timer.
2251 static void delete_candidate_hide_timer (void)
2253 LOGD ("deleting candidate_hide_timer\n");
2254 if (_candidate_hide_timer) {
2255 ecore_timer_del (_candidate_hide_timer);
2256 _candidate_hide_timer = NULL;
2260 static void candidate_window_hide (void)
2262 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2264 delete_candidate_hide_timer ();
2265 _candidate_state = WINDOW_STATE_HIDE;
2267 LOGD ("evas_object_hide (_candidate_window, %p)\n", elm_win_xwindow_get (_candidate_window));
2269 if (_candidate_window) {
2270 /* There are cases that when there are rapid ISE_HIDE and ISE_SHOW requests,
2271 candidate window should be displayed but STATE_OFF for the first ISE_HIDE
2272 calls this function, so when the candidate window is shown by the following
2273 STATE_ON message, a blank area is displayed in candidate window -
2274 so we let the _candidate_area_1 as the default area that would be displayed */
2275 //evas_object_hide (_candidate_area_1);
2276 //evas_object_hide (_more_btn);
2277 _candidate_area_1_visible = false;
2279 evas_object_hide (_candidate_window);
2280 SCIM_DEBUG_MAIN (3) << " Hide candidate window\n";
2285 * @brief Callback function for candidate hide timer
2287 * @param data Data to pass when it is called.
2289 * @return ECORE_CALLBACK_CANCEL
2291 static Eina_Bool candidate_hide_timer (void *data)
2293 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2295 LOGD ("calling candidate_window_hide ()\n");
2296 candidate_window_hide ();
2298 return ECORE_CALLBACK_CANCEL;
2303 * @brief Delete candidate show handler.
2307 static void delete_candidate_show_handler (void)
2309 if (_candidate_show_handler) {
2310 ecore_event_handler_del (_candidate_show_handler);
2311 _candidate_show_handler = NULL;
2316 * @brief Callback function for window show completion event
2318 * @param data Data to pass when it is called.
2320 * @return ECORE_CALLBACK_CANCEL
2323 static Eina_Bool x_event_window_show_cb (void *data, int ev_type, void *event)
2325 delete_candidate_show_handler ();
2327 Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
2328 if (_candidate_state == WINDOW_STATE_WILL_SHOW) {
2329 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2330 LOGD ("Candidate window show callback\n");
2332 /* If our candidate window is in WILL_SHOW state and this show callback was called,
2333 now we are finally displayed on to the screen */
2334 _candidate_state = WINDOW_STATE_SHOW;
2336 /* Update the geometry information for auto scrolling */
2337 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2338 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2339 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2341 /* And the state event */
2342 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2344 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2345 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2346 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2347 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2352 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2353 LOGD ("Candidate window show callback, but _candidate_state is %d\n", _candidate_state);
2357 return ECORE_CALLBACK_CANCEL;
2362 * @brief Show candidate window.
2364 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2366 static void ui_candidate_show (bool bSetVirtualKbd)
2368 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2370 delete_candidate_hide_timer ();
2372 if (!_candidate_window) return;
2373 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
2376 /* FIXME : SHOULD UNIFY THE METHOD FOR CHECKING THE HW KEYBOARD EXISTENCE */
2377 /* If the ISE is not visible currently, wait for the ISE to be opened and then show our candidate window */
2378 _candidate_show_requested = true;
2379 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) && (_ise_state != WINDOW_STATE_SHOW)) {
2380 LOGD ("setting _show_candidate_requested to TRUE\n");
2384 /* If the ISE angle is valid, respect the value to make sure
2385 the candidate window always have the same angle with ISE */
2386 if (_ise_angle != -1) {
2387 _candidate_angle = _ise_angle;
2389 ui_candidate_window_rotate (_candidate_angle);
2391 /* If the candidate window was about to hide, turn it back to SHOW state now */
2392 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
2393 _candidate_state = WINDOW_STATE_SHOW;
2396 /* Change to WILL_SHOW state only when we are not currently in SHOW state */
2397 if (_candidate_state != WINDOW_STATE_SHOW) {
2398 _candidate_state = WINDOW_STATE_WILL_SHOW;
2402 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2403 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
2404 // Unset conformant area
2405 Ecore_X_Window current_app_window = efl_get_app_window ();
2406 if (_app_window != current_app_window) {
2407 struct rectinfo info = {0, 0, 0, 0};
2408 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
2409 set_keyboard_geometry_atom_info (_app_window, info);
2410 LOGD ("Conformant reset for window %x\n", _app_window);
2411 _app_window = current_app_window;
2415 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2416 if (bSetVirtualKbd) {
2417 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2420 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
2423 ui_candidate_delete_check_size_timer ();
2424 _check_size_timer = ecore_timer_add (0.02, ui_candidate_check_size_timeout, NULL);
2426 SCIM_DEBUG_MAIN (3) << " Show candidate window\n";
2428 if (_ise_state == WINDOW_STATE_SHOW) {
2429 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
2430 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
2432 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
2433 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
2436 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2437 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2438 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2439 LOGD ("sending ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW\n");
2440 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
2444 if (_candidate_state != WINDOW_STATE_SHOW) {
2446 if (_candidate_show_handler) {
2447 LOGD ("Was still waiting for CANDIDATE_WINDOW_SHOW....\n");
2449 delete_candidate_show_handler ();
2450 LOGD ("Registering ECORE_X_EVENT_WINDOW_SHOW event, %d\n", _candidate_state);
2451 _candidate_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_window_show_cb, NULL);
2455 LOGD ("The candidate window was already in SHOW state, update geometry information\n");
2456 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2457 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2459 /* And the state event */
2460 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2462 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2463 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2464 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2465 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2470 evas_object_show (_candidate_window);
2474 * @brief Hide candidate window.
2476 * @param bForce The flag to hide candidate window by force.
2477 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2479 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd, bool will_hide)
2481 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " bForce:" << bForce << " bSetVirtualKbd:" << bSetVirtualKbd << " will_hide:" << will_hide << "...\n";
2483 if (!_candidate_window)
2487 if (_candidate_area_2 && _candidate_area_2_visible) {
2488 evas_object_hide (_candidate_area_2);
2489 _candidate_area_2_visible = false;
2490 evas_object_hide (_scroller_bg);
2491 evas_object_hide (_close_btn);
2492 _info_manager->candidate_more_window_hide ();
2493 ui_candidate_window_adjust ();
2497 if (bForce || ui_candidate_can_be_hide ()) {
2499 LOGD ("candidate_state = WILL_HIDE\n");
2500 _candidate_state = WINDOW_STATE_WILL_HIDE;
2502 delete_candidate_hide_timer ();
2503 _candidate_hide_timer = ecore_timer_add (2.0, candidate_hide_timer, NULL);
2506 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2507 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2508 /* FIXME : should check if bSetVirtualKbd flag is really needed in this case */
2510 if (_ise_state == WINDOW_STATE_SHOW) {
2511 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2513 if (bSetVirtualKbd) {
2514 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2518 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2519 _info_manager->update_input_panel_event
2520 ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_HIDE);
2524 /* Update the new keyboard geometry first, and then send the candidate hide event */
2525 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_HIDE);
2528 /* If we are not in will_hide state, hide the candidate window immediately */
2529 candidate_window_hide ();
2531 if (_preedit_window)
2532 evas_object_hide (_preedit_window);
2538 * @brief Callback function for more button.
2540 * @param data Data to pass when it is called.
2541 * @param e The evas for current event.
2542 * @param button The evas object for current event.
2543 * @param event_info The information for current event.
2545 static void ui_candidate_window_more_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2547 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2549 _info_manager->candidate_more_window_show ();
2551 if (candidate_expanded == false) {
2552 candidate_expanded = true;
2553 int number = SCIM_LOOKUP_TABLE_MAX_PAGESIZE;
2554 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
2555 if (_candidate_0 [i] == NULL) {
2560 if (g_isf_candidate_table.get_current_page_size () != number)
2561 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2564 if (_candidate_angle == 180) {
2565 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2566 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2567 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)\n", ee, 0, 0, 0, 0);
2568 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2570 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2571 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2572 * for avoiding this situation.
2574 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2575 ecore_evas_move_resize (ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2576 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)\n",
2577 ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2580 evas_object_show (_candidate_area_2);
2581 _candidate_area_2_visible = true;
2582 evas_object_show (_scroller_bg);
2583 evas_object_hide (_more_btn);
2584 evas_object_show (_close_btn);
2586 ui_candidate_window_adjust ();
2587 ui_settle_candidate_window ();
2592 * @brief Callback function for close button.
2594 * @param data Data to pass when it is called.
2595 * @param e The evas for current event.
2596 * @param button The evas object for current event.
2597 * @param event_info The information for current event.
2599 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2601 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2603 if (_candidate_area_2 == NULL || !_candidate_area_2_visible)
2606 _info_manager->candidate_more_window_hide ();
2608 evas_object_hide (_candidate_area_2);
2609 _candidate_area_2_visible = false;
2610 evas_object_hide (_scroller_bg);
2611 evas_object_hide (_close_btn);
2613 candidate_expanded = false;
2614 evas_object_show (_candidate_area_1);
2615 _candidate_area_1_visible = true;
2616 evas_object_show (_more_btn);
2618 elm_scroller_region_show (_candidate_area_2, 0, 0, _candidate_scroll_width, 100);
2619 if (_candidate_angle == 180) {
2620 Ecore_Evas *ee= ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2621 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2622 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)\n", ee, 0, 0, 0, 0);
2623 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2625 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2626 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2627 * for avoiding this situation.
2629 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2630 ecore_evas_move_resize (ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2631 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)\n",
2632 ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2635 ui_candidate_window_adjust ();
2636 ui_settle_candidate_window ();
2641 * @brief Callback function for mouse button press.
2643 * @param data Data to pass when it is called.
2644 * @param e The evas for current event.
2645 * @param button The evas object for current event.
2646 * @param event_info The information for current event.
2648 static void ui_mouse_button_pressed_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2650 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2652 _click_object = GPOINTER_TO_INT (data) & 0xFF;
2655 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
2658 _click_down_pos [0] = ev->canvas.x;
2659 _click_down_pos [1] = ev->canvas.y;
2661 if (_click_object == ISF_EFL_CANDIDATE_0 || _click_object == ISF_EFL_CANDIDATE_ITEMS) {
2662 int index = GPOINTER_TO_INT (data) >> 8;
2665 if (feedback_initialized) {
2666 int feedback_result = 0;
2667 bool sound_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_SOUND_FEEDBACK, false);
2669 if (sound_feedback) {
2670 feedback_result = feedback_play_type (FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_SIP);
2672 if (FEEDBACK_ERROR_NONE == feedback_result)
2673 LOGD ("Sound play successful\n");
2675 LOGW ("Cannot play feedback sound : %d\n", feedback_result);
2678 bool vibrate_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_VIBRATION_FEEDBACK, false);
2680 if (vibrate_feedback) {
2681 feedback_result = feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
2683 if (FEEDBACK_ERROR_NONE == feedback_result)
2684 LOGD ("Vibration play successful\n");
2686 LOGW ("Cannot play feedback vibration : %d\n", feedback_result);
2691 ui_candidate_delete_longpress_timer ();
2692 _longpress_timer = ecore_timer_add (1.0, ui_candidate_longpress_timeout, (void *)index);
2697 * @brief Callback function for mouse button release.
2699 * @param data Data to pass when it is called.
2700 * @param e The evas for current event.
2701 * @param button The evas object for current event.
2702 * @param event_info The information for current event.
2704 static void ui_mouse_button_released_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2706 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " index:" << GPOINTER_TO_INT (data) << "...\n";
2708 ui_candidate_delete_longpress_timer ();
2710 int index = GPOINTER_TO_INT (data);
2711 if (_click_object == ISF_EFL_AUX && _is_click) {
2713 const char *buf = edje_object_part_state_get (button, "aux", &ret);
2714 if (strcmp ("selected", buf)) {
2715 for (unsigned int i = 0; i < _aux_items.size (); i++) {
2716 buf = edje_object_part_state_get (_aux_items [i], "aux", &ret);
2717 if (!strcmp ("selected", buf))
2718 edje_object_signal_emit (_aux_items [i], "aux,state,unselected", "aux");
2720 edje_object_signal_emit (button, "aux,state,selected", "aux");
2721 _info_manager->select_aux (index);
2723 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
2724 edje_object_color_class_get (_aux_items [index], "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
2725 // Normal item is clicked
2726 if (!(r == 62 && g == 207 && b == 255)) {
2727 for (unsigned int i = 0; i < _aux_items.size (); i++) {
2728 edje_object_color_class_set (_aux_items [i], "text_color", 249, 249, 249, 255, r2, g2, b2, a2, r3, g3, b3, a3);
2730 edje_object_color_class_set (_aux_items [index], "text_color", 62, 207, 255, 255, r2, g2, b2, a2, r3, g3, b3, a3);
2731 _info_manager->select_aux (index);
2733 } else if (_click_object == ISF_EFL_CANDIDATE_0 && _is_click) {
2734 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
2735 _info_manager->select_candidate (index);
2736 } else if (_click_object == ISF_EFL_CANDIDATE_ITEMS && _is_click) {
2737 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
2738 _info_manager->select_candidate (index);
2743 * @brief Callback function for mouse move.
2745 * @param data Data to pass when it is called.
2746 * @param e The evas for current event.
2747 * @param button The evas object for current event.
2748 * @param event_info The information for current event.
2750 static void ui_mouse_moved_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2752 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2754 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
2757 _click_up_pos [0] = ev->canvas.x;
2758 _click_up_pos [1] = ev->canvas.y;
2760 if (abs (_click_up_pos [0] - _click_down_pos [0]) >= (int)(15 * _height_rate) ||
2761 abs (_click_up_pos [1] - _click_down_pos [1]) >= (int)(15 * _height_rate)) {
2763 ui_candidate_delete_longpress_timer ();
2769 * @brief Open TTS device.
2771 * @return false if open is failed, otherwise return true.
2773 static bool ui_open_tts (void)
2775 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2777 int r = tts_create (&_tts);
2778 if (TTS_ERROR_NONE != r) {
2779 LOGW ("tts_create FAILED : result (%d)\n", r);
2784 r = tts_set_mode (_tts, TTS_MODE_SCREEN_READER);
2785 if (TTS_ERROR_NONE != r) {
2786 LOGW ("tts_set_mode FAILED : result (%d)\n", r);
2789 tts_state_e current_state;
2790 r = tts_get_state (_tts, ¤t_state);
2791 if (TTS_ERROR_NONE != r) {
2792 LOGW ("tts_get_state FAILED : result (%d)\n", r);
2795 if (TTS_STATE_CREATED == current_state) {
2796 r = tts_prepare (_tts);
2797 if (TTS_ERROR_NONE != r) {
2798 LOGW ("tts_prepare FAILED : ret (%d)\n", r);
2805 * @brief Close TTS device.
2807 static void ui_close_tts (void)
2809 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2812 int r = tts_unprepare (_tts);
2813 if (TTS_ERROR_NONE != r) {
2814 LOGW ("tts_unprepare FAILED : result (%d)\n", r);
2817 r = tts_destroy (_tts);
2818 if (TTS_ERROR_NONE != r) {
2819 LOGW ("tts_destroy FAILED : result (%d)\n", r);
2825 * @brief Play string by TTS.
2827 * @param str The string for playing.
2829 static void ui_play_tts (const char* str)
2831 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << "\n";
2836 if (!ui_open_tts ())
2842 tts_state_e current_state;
2844 r = tts_get_state (_tts, ¤t_state);
2845 if (TTS_ERROR_NONE != r) {
2846 LOGW ("Fail to get state from TTS : ret (%d)\n", r);
2849 if (TTS_STATE_PLAYING == current_state) {
2850 r = tts_stop (_tts);
2851 if (TTS_ERROR_NONE != r) {
2852 LOGW ("Fail to stop TTS : ret (%d)\n", r);
2856 /* Get ISE language */
2857 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
2858 String language = String ("en_US");
2859 if (default_uuid.length () > 0) {
2860 language = _ime_info[get_ise_index (default_uuid)].languages;
2861 if (language.length () > 0) {
2862 std::vector<String> ise_langs;
2863 scim_split_string_list (ise_langs, language);
2864 language = ise_langs[0];
2867 LOGD ("TTS language:%s, str:%s\n", language.c_str (), str);
2869 r = tts_add_text (_tts, str, language.c_str (), TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &utt_id);
2870 if (TTS_ERROR_NONE == r) {
2871 r = tts_play (_tts);
2872 if (TTS_ERROR_NONE != r) {
2873 LOGW ("Fail to play TTS : ret (%d)\n", r);
2880 * @brief Show rect for candidate focus object when screen reader is enabled.
2882 * @param x Rect X position.
2883 * @param y Rect Y position.
2884 * @param w Rect width.
2885 * @param h Rect height.
2887 static void ui_tts_focus_rect_show (int x, int y, int w, int h)
2889 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2890 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
2893 if (_tts_focus_rect == NULL) {
2894 _tts_focus_rect = evas_object_rectangle_add (evas_object_evas_get ((Evas_Object*)_candidate_window));
2895 evas_object_color_set (_tts_focus_rect, 0, 0, 0, 0);
2896 elm_access_highlight_set (elm_access_object_register (_tts_focus_rect, (Evas_Object*)_candidate_window));
2898 evas_object_move (_tts_focus_rect, x, y);
2899 evas_object_resize (_tts_focus_rect, w, h);
2900 evas_object_raise (_tts_focus_rect);
2901 evas_object_show (_tts_focus_rect);
2905 * @brief Hide rect for candidate focus object when screen reader is enabled.
2907 static void ui_tts_focus_rect_hide (void)
2909 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2911 if (_tts_focus_rect) {
2912 //evas_object_hide (_tts_focus_rect);
2913 evas_object_move (_tts_focus_rect, -1000, -1000);
2918 * @brief Callback function for candidate scroller stop event.
2920 * @param data Data to pass when it is called.
2921 * @param obj The evas object for current event.
2922 * @param event_info The information for current event.
2924 static void ui_candidate_scroller_stop_cb (void *data, Evas_Object *obj, void *event_info)
2926 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2927 if (!_wait_stop_event)
2930 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
2931 if (_candidate_0 [_candidate_tts_focus_index]) {
2933 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
2934 ui_tts_focus_rect_show (x, y, w, h);
2937 _wait_stop_event = false;
2942 * @brief Mouse over (find focus object and play text by TTS) when screen reader is enabled.
2944 * @param mouse_x Mouse X position.
2945 * @param mouse_y Mouse Y position.
2947 static void ui_mouse_over (int mouse_x, int mouse_y)
2949 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2950 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
2953 int x, y, width, height;
2954 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
2955 if (_candidate_0 [i]) {
2956 evas_object_geometry_get (_candidate_0 [i], &x, &y, &width, &height);
2957 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
2958 /* FIXME: Should consider emoji case */
2959 String mbs = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (i));
2960 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " play candidate string: " << mbs << "\n";
2962 ui_play_tts (mbs.c_str ());
2964 _candidate_tts_focus_index = i;
2965 ui_tts_focus_rect_show (x, y, width, height);
2971 String strTts = String ("");
2972 if (_candidate_area_2_visible) {
2973 evas_object_geometry_get (_close_btn, &x, &y, &width, &height);
2974 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
2975 strTts = String (_("close button"));
2976 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
2977 ui_tts_focus_rect_show (x, y, width, height);
2980 evas_object_geometry_get (_more_btn, &x, &y, &width, &height);
2981 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
2982 strTts = String (_("more button"));
2983 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
2984 ui_tts_focus_rect_show (x, y, width, height);
2988 if (strTts.length () > 0)
2989 ui_play_tts (strTts.c_str ());
2994 * @brief Mouse click (find focus object and do click event) when screen reader is enabled.
2996 * @param focus_index focused candidate index.
2998 static void ui_mouse_click (int focus_index)
3000 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3001 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW || focus_index == INVALID_TTS_FOCUS_INDEX)
3004 if (focus_index >= 0 && focus_index < g_isf_candidate_table.get_current_page_size ()) {
3005 if (_candidate_0 [focus_index]) {
3006 int x, y, width, height;
3007 evas_object_geometry_get (_candidate_0 [focus_index], &x, &y, &width, &height);
3008 Evas_Event_Mouse_Down event_info;
3009 event_info.canvas.x = x + width / 2;
3010 event_info.canvas.y = y + height / 2;
3011 ui_mouse_button_pressed_cb (GINT_TO_POINTER ((focus_index << 8) + ISF_EFL_CANDIDATE_0), NULL, NULL, &event_info);
3012 ui_mouse_button_released_cb (GINT_TO_POINTER (focus_index), NULL, NULL, &event_info);
3014 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
3015 ui_tts_focus_rect_hide ();
3019 if (_candidate_area_2_visible) {
3020 if (focus_index == CLOSE_BUTTON_INDEX) {
3021 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
3022 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
3025 if (focus_index == MORE_BUTTON_INDEX) {
3026 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
3027 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
3034 * @brief Create preedit window.
3036 static void ui_create_preedit_window (void)
3038 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3040 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3043 _preedit_width = 100;
3044 _preedit_height = _preedit_height * _height_rate;
3045 if (_preedit_window == NULL) {
3046 _preedit_window = efl_create_window ("ISF Popup", "Preedit Window");
3047 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
3048 int rots [4] = {0, 90, 180, 270};
3049 elm_win_wm_rotation_available_rotations_set (_preedit_window, rots, 4);
3050 int preedit_font_size = (int)(32 * _width_rate);
3052 _preedit_text = edje_object_add (evas_object_evas_get (_preedit_window));
3053 edje_object_file_set (_preedit_text, _candidate_edje_file.c_str (), "preedit_text");
3054 evas_object_size_hint_fill_set (_preedit_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
3055 evas_object_size_hint_weight_set (_preedit_text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3056 elm_win_resize_object_add (_preedit_window, _preedit_text);
3057 evas_object_show (_preedit_text);
3059 _tmp_preedit_text = evas_object_text_add (evas_object_evas_get (_preedit_window));
3060 evas_object_text_font_set (_tmp_preedit_text, _candidate_font_name.c_str (), preedit_font_size);
3065 * @brief Create native style candidate window.
3067 static void ui_create_native_candidate_window (void)
3069 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3070 _more_btn_width = 80 * (_width_rate > 1 ? 1 : _width_rate);
3071 _more_btn_height = 64 * _height_rate;
3073 _candidate_port_width = _screen_width;
3074 _candidate_port_height_min = 84 * _height_rate * _candidate_port_line;
3075 _candidate_port_height_min_2 = 84 * _height_rate + _candidate_port_height_min;
3076 _candidate_port_height_max = 426 * _height_rate + _candidate_port_height_min;
3077 _candidate_port_height_max_2 = 84 * _height_rate + _candidate_port_height_max;
3078 _candidate_land_width = _screen_height;
3079 _candidate_land_height_min = 84 * _width_rate;
3080 _candidate_land_height_min_2 = 168 * _width_rate;
3081 _candidate_land_height_max = 342 * _width_rate;
3082 _candidate_land_height_max_2 = 426 * _width_rate;
3084 _candidate_scroll_0_width_min= _screen_width;
3085 _candidate_scroll_0_width_max= _screen_height;
3086 _candidate_scroll_width_min = _screen_width;
3087 _candidate_scroll_width_max = _screen_height;
3088 _candidate_scroll_height_min = 252 * _width_rate;
3089 _candidate_scroll_height_max = 420 * _height_rate;
3091 _candidate_area_1_pos [0] = 0 * _width_rate;
3092 _candidate_area_1_pos [1] = 2 * _height_rate;
3093 _more_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3094 _more_btn_pos [1] = 12 * _height_rate;
3095 _more_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3096 _more_btn_pos [3] = 12 * _width_rate;
3097 _close_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3098 _close_btn_pos [1] = 12 * _height_rate;
3099 _close_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3100 _close_btn_pos [3] = 12 * _width_rate;
3102 _aux_height = 84 * _height_rate - 2;
3103 _aux_port_width = _screen_width;
3104 _aux_land_width = _screen_height;
3106 _item_min_height = 84 * _height_rate - 2;
3108 /* Create candidate window */
3109 if (_candidate_window == NULL) {
3110 _candidate_window = efl_create_window ("ISF Popup", "Prediction Window");
3111 int rots [4] = {0, 90, 180, 270};
3112 elm_win_wm_rotation_available_rotations_set (_candidate_window, rots, 4);
3113 if (_candidate_angle == 90 || _candidate_angle == 270) {
3114 _candidate_width = _candidate_land_width;
3115 _candidate_height = _candidate_land_height_min;
3117 _candidate_width = _candidate_port_width;
3118 _candidate_height = _candidate_port_height_min;
3122 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3123 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3124 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3125 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3126 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3127 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3128 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3129 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3132 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3133 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3134 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3135 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3136 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3137 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3138 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3139 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3141 /* Add dim background */
3142 Evas_Object *dim_bg = elm_bg_add (_candidate_window);
3143 evas_object_color_set (dim_bg, 0, 0, 0, 153);
3144 elm_win_resize_object_add (_candidate_window, dim_bg);
3145 evas_object_show (dim_bg);
3147 /* Add candidate background */
3148 _candidate_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3149 edje_object_file_set (_candidate_bg, _candidate_edje_file.c_str (), "candidate_bg");
3150 evas_object_size_hint_weight_set (_candidate_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3151 evas_object_resize (_candidate_bg, _candidate_port_width, _candidate_port_height_min);
3152 evas_object_move (_candidate_bg, 0, 0);
3153 evas_object_show (_candidate_bg);
3155 /* Create _candidate_0 scroller */
3156 _candidate_0_scroll = elm_scroller_add (_candidate_window);
3157 elm_scroller_bounce_set (_candidate_0_scroll, EINA_TRUE, EINA_FALSE);
3158 elm_scroller_policy_set (_candidate_0_scroll, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3159 evas_object_resize (_candidate_0_scroll, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
3160 evas_object_move (_candidate_0_scroll, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3162 /* Create candidate table */
3163 _candidate_0_table = elm_table_add (_candidate_window);
3164 evas_object_size_hint_weight_set (_candidate_0_table, 0.0, 0.0);
3165 evas_object_size_hint_align_set (_candidate_0_table, 0.0, 0.0);
3166 elm_table_padding_set (_candidate_0_table, 0, 0);
3167 elm_object_content_set (_candidate_0_scroll, _candidate_0_table);
3168 evas_object_show (_candidate_0_table);
3169 _candidate_area_1 = _candidate_0_scroll;
3171 /* Create more button */
3172 _more_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3173 if (_ise_width == 0 && _ise_height == 0)
3174 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
3176 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
3177 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
3178 evas_object_resize (_more_btn, _more_btn_width, _more_btn_height);
3179 evas_object_event_callback_add (_more_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_more_button_cb, NULL);
3181 /* Add scroller background */
3182 _candidate_scroll_width = _candidate_scroll_width_min;
3183 _scroller_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3184 edje_object_file_set (_scroller_bg, _candidate_edje_file.c_str (), "scroller_bg");
3185 evas_object_size_hint_weight_set (_scroller_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3186 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3187 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
3189 /* Create vertical scroller */
3190 _candidate_scroll = elm_scroller_add (_candidate_window);
3191 elm_scroller_bounce_set (_candidate_scroll, 0, 1);
3192 elm_scroller_policy_set (_candidate_scroll, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
3193 evas_object_resize (_candidate_scroll, _candidate_scroll_width, _candidate_scroll_height_max);
3194 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3195 elm_scroller_page_size_set (_candidate_scroll, 0, _item_min_height+_v_padding);
3196 evas_object_move (_candidate_scroll, 0, _candidate_port_height_min);
3198 /* Create candidate table */
3199 _candidate_table = elm_table_add (_candidate_window);
3200 evas_object_size_hint_weight_set (_candidate_table, 0.0, 0.0);
3201 evas_object_size_hint_align_set (_candidate_table, 0.0, 0.0);
3202 elm_table_padding_set (_candidate_table, 0, 0);
3203 elm_object_content_set (_candidate_scroll, _candidate_table);
3204 evas_object_show (_candidate_table);
3205 _candidate_area_2 = _candidate_scroll;
3206 evas_object_smart_callback_add (_candidate_scroll, "scroll,anim,stop", ui_candidate_scroller_stop_cb, NULL);
3208 /* Create close button */
3209 _close_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3210 if (_ise_width == 0 && _ise_height == 0)
3211 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
3213 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
3214 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
3215 evas_object_resize (_close_btn, _more_btn_width, _more_btn_height);
3216 evas_object_event_callback_add (_close_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_close_button_cb, NULL);
3218 _tmp_candidate_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3219 evas_object_text_font_set (_tmp_candidate_text, _candidate_font_name.c_str (), _candidate_font_size);
3222 _aux_area = elm_scroller_add (_candidate_window);
3223 elm_scroller_bounce_set (_aux_area, 1, 0);
3224 elm_scroller_policy_set (_aux_area, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3225 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
3226 evas_object_move (_aux_area, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3228 _aux_table = elm_table_add (_candidate_window);
3229 elm_object_content_set (_aux_area, _aux_table);
3230 elm_table_padding_set (_aux_table, 0, 0);
3231 evas_object_size_hint_weight_set (_aux_table, 0.0, 0.0);
3232 evas_object_size_hint_align_set (_aux_table, 0.0, 0.0);
3233 evas_object_show (_aux_table);
3235 _aux_line = edje_object_add (evas_object_evas_get (_candidate_window));
3236 edje_object_file_set (_aux_line, _candidate_edje_file.c_str (), "popup_line");
3237 evas_object_resize (_aux_line, _candidate_port_width, 2);
3238 evas_object_move (_aux_line, 0, _aux_height + 2);
3240 _tmp_aux_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3241 evas_object_text_font_set (_tmp_aux_text, _candidate_font_name.c_str (), _aux_font_size);
3243 evas_object_hide (_candidate_window);
3250 * @brief Create candidate window.
3254 static void ui_create_candidate_window (void)
3256 check_time ("\nEnter ui_create_candidate_window");
3257 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3258 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3263 _candidate_angle = 0;
3265 ui_create_native_candidate_window ();
3268 unsigned int set = 1;
3270 ecore_x_window_prop_card32_set (elm_win_xwindow_get (_candidate_window),
3271 ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
3274 int angle = efl_get_app_window_angle ();
3275 if (_candidate_angle != angle) {
3276 _candidate_angle = angle;
3277 ui_candidate_window_rotate (angle);
3279 ui_settle_candidate_window ();
3282 candidate_expanded = false;
3284 check_time ("Exit ui_create_candidate_window");
3288 * @brief Destroy candidate window.
3292 static void ui_destroy_candidate_window (void)
3294 check_time ("Enter ui_destroy_candidate_window");
3295 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3297 /* Delete candidate items, popup lines and seperator items */
3298 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3299 if (_candidate_0 [i]) {
3300 evas_object_del (_candidate_0 [i]);
3301 _candidate_0 [i] = NULL;
3303 if (_seperate_0 [i]) {
3304 evas_object_del (_seperate_0 [i]);
3305 _seperate_0 [i] = NULL;
3307 if (_seperate_items [i]) {
3308 evas_object_del (_seperate_items [i]);
3309 _seperate_items [i] = NULL;
3312 evas_object_del (_line_0 [i]);
3315 if (_line_items [i]) {
3316 evas_object_del (_line_items [i]);
3317 _line_items [i] = NULL;
3321 _aux_items.clear ();
3322 _aux_seperates.clear ();
3323 /* Delete candidate window */
3324 if (_candidate_window) {
3325 LOGD ("calling ui_candidate_hide (true)\n");
3326 ui_candidate_hide (true);
3328 evas_object_del (_candidate_window);
3329 _candidate_window = NULL;
3331 _candidate_area_1 = NULL;
3332 _candidate_area_2 = NULL;
3335 if (_tts_focus_rect) {
3336 evas_object_del (_tts_focus_rect);
3337 _tts_focus_rect = NULL;
3340 if (_candidate_bg) {
3341 evas_object_del (_candidate_bg);
3342 _candidate_bg = NULL;
3346 evas_object_del (_more_btn);
3351 evas_object_del (_scroller_bg);
3352 _scroller_bg = NULL;
3356 evas_object_del (_close_btn);
3361 evas_object_del (_aux_line);
3365 if (_tmp_candidate_text) {
3366 evas_object_del (_tmp_candidate_text);
3367 _tmp_candidate_text = NULL;
3370 if (_tmp_preedit_text) {
3371 evas_object_del (_tmp_preedit_text);
3372 _tmp_preedit_text = NULL;
3375 if (_tmp_aux_text) {
3376 evas_object_del (_tmp_aux_text);
3377 _tmp_aux_text = NULL;
3380 if (_preedit_text) {
3381 evas_object_del (_preedit_text);
3382 _preedit_text = NULL;
3385 if (_preedit_window) {
3386 evas_object_hide (_preedit_window);
3387 evas_object_del (_preedit_window);
3388 _preedit_window = NULL;
3392 check_time ("Exit ui_destroy_candidate_window");
3396 * @brief Settle candidate window position.
3398 static void ui_settle_candidate_window (void)
3400 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3402 if (!_candidate_window)
3405 /* If both ISE and candidate window are going to be hidden,
3406 let's just not move our candidate window */
3407 if (_ise_state == WINDOW_STATE_WILL_HIDE && _candidate_state == WINDOW_STATE_WILL_HIDE)
3411 int x, y, width, height;
3412 int ise_width = 0, ise_height = 0;
3413 bool get_geometry_result = false;
3415 /* Get candidate window position */
3416 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
3420 int pos_x = 0, pos_y = 0;
3421 if (_candidate_angle == 90 || _candidate_angle == 270)
3422 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_height, &ise_width);
3424 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_width, &ise_height);
3429 ise_width = _ise_width;
3430 ise_height = _ise_height;
3431 get_geometry_result = true;
3433 if ((_ise_state != WINDOW_STATE_SHOW && _ise_state != WINDOW_STATE_WILL_HIDE) ||
3434 (get_geometry_result == false) || (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
3439 int height2 = ui_candidate_get_valid_height ();
3441 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
3442 if (_candidate_angle == 90) {
3443 spot_x = _screen_width - ise_height - height2;
3445 } else if (_candidate_angle == 270) {
3446 spot_x = ise_height - (_candidate_height - height2);
3448 } else if (_candidate_angle == 180) {
3450 spot_y = ise_height - (_candidate_height - height2);
3453 spot_y = _screen_height - ise_height - height2;
3456 spot_x = _spot_location_x;
3457 spot_y = _spot_location_y;
3459 rectinfo ise_rect = {0, 0, (uint32)ise_width, (uint32)ise_height};
3460 if (_candidate_angle == 90 || _candidate_angle == 270) {
3461 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32)_screen_width)
3462 ise_rect.height = ISE_DEFAULT_HEIGHT_LANDSCAPE * _width_rate;
3464 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32) _screen_height)
3465 ise_rect.height = ISE_DEFAULT_HEIGHT_PORTRAIT * _height_rate;
3468 int nOffset = _candidate_port_height_min / 3;
3469 if (_candidate_angle == 270) {
3470 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3471 spot_x = _screen_width - _spot_location_top_y - (_candidate_height - height2);
3473 spot_x = _screen_width - _spot_location_y - _candidate_height;
3475 } else if (_candidate_angle == 90) {
3476 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3477 spot_x = _spot_location_top_y - height2;
3481 } else if (_candidate_angle == 180) {
3482 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3483 spot_y = _screen_height - _spot_location_top_y - (_candidate_height - height2);
3485 spot_y = _screen_height - _spot_location_y - _candidate_height;
3488 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3489 spot_y = _spot_location_top_y - height2;
3496 if (_candidate_angle == 90) {
3497 spot_y = (_screen_height - _candidate_width) / 2;
3498 spot_x = spot_x < _indicator_height ? _indicator_height : spot_x;
3499 if (spot_x > _screen_width - _candidate_height)
3500 spot_x = _screen_width - _candidate_height;
3501 } else if (_candidate_angle == 270) {
3502 spot_y = (_screen_height - _candidate_width) / 2;
3503 spot_x = spot_x < 0 ? 0 : spot_x;
3504 if (spot_x > _screen_width - (_indicator_height+_candidate_height))
3505 spot_x = _screen_width - (_indicator_height+_candidate_height);
3506 } else if (_candidate_angle == 180) {
3507 spot_x = (_screen_width - _candidate_width) / 2;
3508 spot_y = spot_y < 0 ? 0 : spot_y;
3509 if (spot_y > _screen_height - (_indicator_height+_candidate_height))
3510 spot_y = _screen_height - (_indicator_height+_candidate_height);
3512 spot_x = (_screen_width - _candidate_width) / 2;
3513 spot_y = spot_y < _indicator_height ? _indicator_height : spot_y;
3514 if (spot_y > _screen_height - _candidate_height)
3515 spot_y = _screen_height - _candidate_height;
3518 if (spot_x != x || spot_y != y) {
3519 _candidate_x = spot_x;
3520 _candidate_y = spot_y;
3521 evas_object_move (_candidate_window, spot_x, spot_y);
3522 LOGD ("Moving candidate window to : %d %d\n", spot_x, spot_y);
3523 if (_preedit_window) {
3524 if (_candidate_angle == 90) {
3525 spot_x -= _preedit_height;
3526 spot_y = _screen_height - _preedit_width;
3527 } else if (_candidate_angle == 270) {
3529 } else if (_candidate_angle == 180) {
3530 spot_x = _screen_width - _preedit_width;
3533 spot_y -= _preedit_height;
3535 evas_object_move (_preedit_window, spot_x, spot_y);
3537 if (_candidate_state == WINDOW_STATE_SHOW) {
3538 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
3544 * @brief Set soft candidate geometry.
3546 * @param x The x position in screen.
3547 * @param y The y position in screen.
3548 * @param width The candidate window width.
3549 * @param height The candidate window height.
3551 static void set_soft_candidate_geometry (int x, int y, int width, int height)
3553 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
3555 LOGD ("candidate geometry x: %d , y: %d , width: %d , height: %d, _ise_state: %d, candidate_mode: %d\n", x, y, width, height, _ise_state, _candidate_mode);
3557 if ((_candidate_mode != SOFT_CANDIDATE_WINDOW) || (_info_manager->get_current_toolbar_mode () != TOOLBAR_KEYBOARD_MODE))
3560 _soft_candidate_width = width;
3561 _soft_candidate_height = height;
3563 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry());
3565 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
3569 //////////////////////////////////////////////////////////////////////
3570 // End of Candidate Functions
3571 //////////////////////////////////////////////////////////////////////
3574 * @brief Set transient for app window.
3576 * @param window The Ecore_X_Window handler of app window.
3578 static void efl_set_transient_for_app_window (Ecore_X_Window window)
3580 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3582 /* Set a transient window for window stack */
3583 Ecore_X_Window xAppWindow = efl_get_app_window ();
3584 ecore_x_icccm_transient_for_set (window, xAppWindow);
3586 LOGD ("win : %x, forwin : %x\n", window, xAppWindow);
3589 static int efl_get_window_rotate_angle (Ecore_X_Window win)
3591 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3596 unsigned char *prop_data = NULL;
3598 ret = ecore_x_window_prop_property_get (win,
3599 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
3600 if (ret && prop_data) {
3601 memcpy (&angle, prop_data, sizeof (int));
3602 LOGD ("WINDOW angle of %p is %d\n", win, angle);
3604 std::cerr << "ecore_x_window_prop_property_get () is failed!!!\n";
3605 LOGW ("WINDOW angle of %p FAILED!\n", win);
3614 * @brief Get angle for app window.
3616 * @param win_obj The Evas_Object handler of application window.
3618 * @return The angle of app window.
3620 static int efl_get_app_window_angle ()
3622 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3624 return efl_get_window_rotate_angle (efl_get_app_window ());
3632 * @brief Get angle for ise window.
3634 * @param win_obj The Evas_Object handler of ise window.
3636 * @return The angle of ise window.
3638 static int efl_get_ise_window_angle ()
3640 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3642 return efl_get_window_rotate_angle (_ise_window);
3651 * @brief Get angle of quickpanel window.
3653 * @return The angle of quickpanel window.
3655 static int efl_get_quickpanel_window_angle ()
3657 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3658 return efl_get_window_rotate_angle (efl_get_quickpanel_window ());
3663 * @brief Set showing effect for application window.
3665 * @param win The Evas_Object handler of application window.
3666 * @param strEffect The pointer of effect string.
3668 static void efl_set_showing_effect_for_app_window (Evas_Object *win, const char* strEffect)
3670 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3672 ecore_x_icccm_name_class_set (elm_win_xwindow_get (static_cast<Evas_Object*>(win)), strEffect, "ISF");
3677 * @brief Create elementary window.
3679 * @param strWinName The window name.
3680 * @param strEffect The window effect string.
3682 * @return The window pointer
3684 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect)
3686 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3688 Evas_Object *win = elm_win_add (NULL, strWinName, ELM_WIN_UTILITY);
3689 elm_win_title_set (win, strWinName);
3691 /* set window properties */
3692 elm_win_autodel_set (win, EINA_TRUE);
3693 elm_object_focus_allow_set (win, EINA_FALSE);
3694 elm_win_borderless_set (win, EINA_TRUE);
3695 elm_win_alpha_set (win, EINA_TRUE);
3696 elm_win_prop_focus_skip_set (win, EINA_TRUE);
3697 efl_set_showing_effect_for_app_window (win, strEffect);
3704 * @brief Create elementary control window.
3706 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3708 static Eina_Bool efl_create_control_window (void)
3710 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3712 /* WMSYNC, #1 Creating and registering control window */
3713 if (ecore_x_display_get () == NULL)
3716 Ecore_X_Window root = ecore_x_window_root_first_get ();
3717 _control_window = ecore_x_window_input_new (root, -100, -100, 1, 1);
3718 //ecore_x_e_virtual_keyboard_control_window_set (root, _control_window, 0, EINA_TRUE);
3720 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_CONTROL_WINDOW");
3721 ecore_x_window_prop_xid_set (root, atom, ECORE_X_ATOM_WINDOW, &_control_window, 1);
3727 * @brief Get an window's x window id.
3729 * @param name the property name.
3730 * @return X window id.
3732 static Ecore_X_Window efl_get_window (const char *name)
3734 /* Gets the XID of the window from the root window property */
3738 unsigned long nitems_return;
3739 unsigned long bytes_after_return;
3740 unsigned char *data = NULL;
3741 Ecore_X_Window window = 0;
3743 ret = XGetWindowProperty ((Display *)ecore_x_display_get (),
3744 ecore_x_window_root_get (_control_window),
3745 ecore_x_atom_get (name),
3746 0, G_MAXLONG, False, XA_WINDOW, &type_return,
3747 &format_return, &nitems_return, &bytes_after_return,
3750 if (ret == Success) {
3751 if ((type_return == XA_WINDOW) && (format_return == 32) && (data)) {
3752 window = *(Window *)data;
3757 std::cerr << "XGetWindowProperty () is failed!!!\n";
3764 * @brief Get app window's x window id.
3766 * @return the X window id of application to have focus or to request to show IME.
3768 static Ecore_X_Window efl_get_app_window (void)
3770 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3772 return efl_get_window ("_ISF_ACTIVE_WINDOW");
3776 * @brief Get clipboard window's x window id.
3778 * @return the X window id of clipboard.
3780 static Ecore_X_Window efl_get_clipboard_window (void)
3782 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3784 return efl_get_window ("CBHM_ELM_WIN");
3788 * @brief Get global natigation window's x window id.
3790 * @return the X window id of global navigation.
3792 static Ecore_X_Window efl_get_global_navigation_window (void)
3794 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3796 return efl_get_window ("GNB_WIN");
3800 * @brief Get app window's x window id.
3802 * @return the X window id of quick panel.
3804 static Ecore_X_Window efl_get_quickpanel_window (void)
3806 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3808 Ecore_X_Window rootWin = ecore_x_window_root_first_get ();
3809 Ecore_X_Window qpwin;
3810 ecore_x_window_prop_xid_get (rootWin, ecore_x_atom_get ("_E_ILLUME_QUICKPANEL_WINDOW_LIST"), ECORE_X_ATOM_WINDOW, &qpwin, 1);
3816 * @brief Get default zone geometry.
3818 * @param x The zone x position.
3819 * @param y The zone y position.
3820 * @param w The zone width.
3821 * @param h The zone height.
3823 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3825 static Eina_Bool efl_get_default_zone_geometry_info (Ecore_X_Window root, uint *x, uint *y, uint *w, uint *h)
3827 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3829 Ecore_X_Atom zone_geometry_atom;
3830 Ecore_X_Window *zone_lists;
3835 zone_geometry_atom = ecore_x_atom_get ("_E_ILLUME_ZONE_GEOMETRY");
3836 if (!zone_geometry_atom) {
3842 num_zone_lists = ecore_x_window_prop_window_list_get (root, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, &zone_lists);
3843 if (num_zone_lists > 0) {
3844 num_ret = ecore_x_window_prop_card32_get (zone_lists[0], zone_geometry_atom, geom, 4);
3846 if (x) *x = geom[0];
3847 if (y) *y = geom[1];
3848 if (w) *w = geom[2];
3849 if (h) *h = geom[3];
3855 /* if there is no zone available */
3860 /* We must free zone_lists */
3868 * @brief Get screen resolution.
3870 * @param width The screen width.
3871 * @param height The screen height.
3873 static void efl_get_screen_resolution (int &width, int &height)
3875 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3877 static Evas_Coord scr_w = 0, scr_h = 0;
3878 if (scr_w == 0 || scr_h == 0) {
3881 if (efl_get_default_zone_geometry_info (ecore_x_window_root_first_get (), NULL, NULL, &w, &h)) {
3885 ecore_x_window_size_get (ecore_x_window_root_first_get (), &scr_w, &scr_h);
3888 ecore_wl_screen_size_get(&scr_w, &scr_h);
3896 //////////////////////////////////////////////////////////////////////
3897 // Start of PanelAgent Functions
3898 //////////////////////////////////////////////////////////////////////
3901 * @brief Initialize panel agent.
3903 * @param config The config string for PanelAgent.
3904 * @param display The current display.
3905 * @param resident The variable indicates whether panel will be resident.
3907 * @return true if initialize is successful, otherwise return false.
3909 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident)
3911 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3913 LOGD ("initializing panel agent\n");
3915 _info_manager = new InfoManager ();
3917 if (!_info_manager || !_info_manager->initialize (_info_manager, config, display, resident)) {
3918 ISF_SAVE_LOG ("panel_agent initialize fail!\n");
3922 _info_manager->signal_connect_reload_config (slot (slot_reload_config));
3923 _info_manager->signal_connect_focus_in (slot (slot_focus_in));
3924 _info_manager->signal_connect_focus_out (slot (slot_focus_out));
3925 _info_manager->signal_connect_expand_candidate (slot (slot_expand_candidate));
3926 _info_manager->signal_connect_contract_candidate (slot (slot_contract_candidate));
3927 _info_manager->signal_connect_set_candidate_ui (slot (slot_set_candidate_style));
3928 _info_manager->signal_connect_update_factory_info (slot (slot_update_factory_info));
3929 _info_manager->signal_connect_update_spot_location (slot (slot_update_spot_location));
3930 _info_manager->signal_connect_update_input_context (slot (slot_update_input_context));
3931 _info_manager->signal_connect_update_ise_geometry (slot (slot_update_ise_geometry));
3932 _info_manager->signal_connect_show_preedit_string (slot (slot_show_preedit_string));
3933 _info_manager->signal_connect_show_aux_string (slot (slot_show_aux_string));
3934 _info_manager->signal_connect_show_lookup_table (slot (slot_show_candidate_table));
3935 _info_manager->signal_connect_hide_preedit_string (slot (slot_hide_preedit_string));
3936 _info_manager->signal_connect_hide_aux_string (slot (slot_hide_aux_string));
3937 _info_manager->signal_connect_hide_lookup_table (slot (slot_hide_candidate_table));
3938 _info_manager->signal_connect_update_preedit_string (slot (slot_update_preedit_string));
3939 _info_manager->signal_connect_update_preedit_caret (slot (slot_update_preedit_caret));
3940 _info_manager->signal_connect_update_aux_string (slot (slot_update_aux_string));
3941 _info_manager->signal_connect_update_lookup_table (slot (slot_update_candidate_table));
3942 _info_manager->signal_connect_select_candidate (slot (slot_select_candidate));
3943 _info_manager->signal_connect_get_candidate_geometry (slot (slot_get_candidate_geometry));
3944 _info_manager->signal_connect_get_input_panel_geometry (slot (slot_get_input_panel_geometry));
3945 _info_manager->signal_connect_set_active_ise_by_uuid (slot (slot_set_active_ise));
3946 _info_manager->signal_connect_get_ise_list (slot (slot_get_ise_list));
3947 _info_manager->signal_connect_get_all_helper_ise_info (slot (slot_get_all_helper_ise_info));
3948 _info_manager->signal_connect_set_has_option_helper_ise_info(slot (slot_set_has_option_helper_ise_info));
3949 _info_manager->signal_connect_set_enable_helper_ise_info (slot (slot_set_enable_helper_ise_info));
3950 _info_manager->signal_connect_show_helper_ise_list (slot (slot_show_helper_ise_list));
3951 _info_manager->signal_connect_show_helper_ise_selector (slot (slot_show_helper_ise_selector));
3952 _info_manager->signal_connect_is_helper_ise_enabled (slot (slot_is_helper_ise_enabled));
3953 _info_manager->signal_connect_get_ise_information (slot (slot_get_ise_information));
3954 _info_manager->signal_connect_get_keyboard_ise_list (slot (slot_get_keyboard_ise_list));
3955 _info_manager->signal_connect_get_language_list (slot (slot_get_language_list));
3956 _info_manager->signal_connect_get_all_language (slot (slot_get_all_language));
3957 _info_manager->signal_connect_get_ise_language (slot (slot_get_ise_language));
3958 _info_manager->signal_connect_get_ise_info_by_uuid (slot (slot_get_ise_info));
3959 _info_manager->signal_connect_set_keyboard_ise (slot (slot_set_keyboard_ise));
3960 _info_manager->signal_connect_get_keyboard_ise (slot (slot_get_keyboard_ise));
3961 _info_manager->signal_connect_accept_connection (slot (slot_accept_connection));
3962 _info_manager->signal_connect_close_connection (slot (slot_close_connection));
3963 _info_manager->signal_connect_exit (slot (slot_exit));
3965 _info_manager->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
3966 _info_manager->signal_connect_show_ise (slot (slot_show_ise));
3967 _info_manager->signal_connect_hide_ise (slot (slot_hide_ise));
3969 _info_manager->signal_connect_will_hide_ack (slot (slot_will_hide_ack));
3971 _info_manager->signal_connect_set_keyboard_mode (slot (slot_set_keyboard_mode));
3973 _info_manager->signal_connect_candidate_will_hide_ack (slot (slot_candidate_will_hide_ack));
3974 _info_manager->signal_connect_get_ise_state (slot (slot_get_ise_state));
3975 _info_manager->signal_connect_start_default_ise (slot (slot_start_default_ise));
3976 _info_manager->signal_connect_stop_default_ise (slot (slot_stop_default_ise));
3977 _info_manager->signal_connect_show_panel (slot (slot_show_helper_ise_selector));
3979 _info_manager->signal_connect_get_recent_ise_geometry (slot (slot_get_recent_ise_geometry));
3980 _info_manager->signal_connect_check_privilege_by_sockfd (slot (slot_check_privilege_by_sockfd));
3981 std::vector<String> load_ise_list;
3982 _info_manager->get_active_ise_list (load_ise_list);
3984 LOGD ("initializing panel agent succeeded\n");
3989 static void delete_ise_hide_timer (void)
3991 LOGD ("deleting ise_hide_timer\n");
3992 if (_ise_hide_timer) {
3993 ecore_timer_del (_ise_hide_timer);
3994 _ise_hide_timer = NULL;
3998 static void hide_ise ()
4000 LOGD ("send request to hide helper\n");
4001 String uuid = _info_manager->get_current_helper_uuid ();
4002 _info_manager->hide_helper (uuid);
4004 /* Only if we are not already in HIDE state */
4005 if (_ise_state != WINDOW_STATE_HIDE) {
4006 /* From this point, slot_get_input_panel_geometry should return hidden state geometry */
4007 _ise_state = WINDOW_STATE_WILL_HIDE;
4009 _updated_hide_state_geometry = false;
4013 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
4015 if (_candidate_window) {
4016 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)
4017 ui_candidate_hide (true, true, true);
4019 ui_candidate_hide (true, false, true);
4023 #if ENABLE_MULTIWINDOW_SUPPORT
4024 static Eina_Bool ise_hide_timeout (void *data)
4026 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4028 delete_ise_hide_timer ();
4031 return ECORE_CALLBACK_CANCEL;
4036 * @brief Insert data to ime_info table.
4038 * @param list The list to store uuid
4040 * @return true if it is successful, otherwise return false.
4042 static bool update_ise_list (std::vector<String> &list)
4044 std::vector<String> uuids;
4045 std::vector<TOOLBAR_MODE_T> modes;
4046 std::vector<ImeInfoDB>::iterator iter;
4049 if (_ime_info.size() == 0) {
4050 if (isf_pkg_select_all_ime_info_db(_ime_info) == 0)
4054 /* Update _groups */
4056 std::vector<String> ise_langs;
4057 for (size_t i = 0; i < _ime_info.size (); ++i) {
4058 scim_split_string_list(ise_langs, _ime_info[i].languages);
4059 for (size_t j = 0; j < ise_langs.size (); j++) {
4060 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
4061 _groups[ise_langs[j]].push_back (i);
4066 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
4067 uuids.push_back(iter->appid);
4068 modes.push_back(iter->mode);
4071 if (uuids.size() > 0) {
4075 _info_manager->update_ise_list (list);
4077 if (_initial_ise_uuid.length () > 0) {
4078 String active_uuid = _initial_ise_uuid;
4079 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
4080 if (std::find (uuids.begin (), uuids.end (), default_uuid) == uuids.end ()) {
4081 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (modes[get_ise_index (_initial_ise_uuid)] != TOOLBAR_KEYBOARD_MODE)) {
4082 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4084 if (set_active_ise (active_uuid, _soft_keyboard_launched) == false) {
4085 if (_initial_ise_uuid.compare (active_uuid))
4086 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
4088 } else if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) { // Check whether keyboard engine is installed
4089 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
4090 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
4091 if (std::find (uuids.begin (), uuids.end (), keyboard_uuid) == uuids.end ()) {
4092 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4093 _info_manager->change_factory (active_uuid);
4094 _config->write (IMENGINE_KEY, active_uuid);
4100 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
4102 if (_ime_info.size () > 0 && _ime_info[0].display_lang.compare(lang_str) == 0)
4103 _locale_string = String (lang_str);
4109 #if HAVE_PKGMGR_INFO
4111 int ret = package_manager_create (&pkgmgr);
4112 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4113 package_manager_set_event_cb (pkgmgr, _package_manager_event_cb, NULL);
4114 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4115 LOGD ("package_manager_set_event_cb succeeded.\n");
4118 LOGE ("package_manager_set_event_cb failed(%d)\n", ret);
4122 LOGE ("package_manager_create failed(%d)\n", ret);
4131 * @brief Reload config slot function for PanelAgent.
4133 static void slot_reload_config (void)
4135 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4137 if (!_config.null ())
4142 * @brief Focus in slot function for PanelAgent.
4144 static void slot_focus_in (void)
4146 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4149 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
4150 if (_launch_ise_on_request && !_soft_keyboard_launched) {
4151 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
4152 if (uuid.length () > 0 && (_ime_info[get_ise_index(uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
4153 LOGD ("Start helper (%s)\n", uuid.c_str ());
4155 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
4156 if (_info_manager->start_helper (uuid))
4157 _soft_keyboard_launched = true;
4162 ui_candidate_delete_destroy_timer ();
4166 * @brief Focus out slot function for PanelAgent.
4168 static void slot_focus_out (void)
4170 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4174 ui_candidate_delete_destroy_timer ();
4175 _destroy_timer = ecore_timer_add (ISF_CANDIDATE_DESTROY_DELAY, ui_candidate_destroy_timeout, NULL);
4179 * @brief Expand candidate slot function for PanelAgent.
4181 static void slot_expand_candidate (void)
4183 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4184 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4187 if (_candidate_area_2 && !_candidate_area_2_visible)
4188 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
4192 * @brief Contract candidate slot function for PanelAgent.
4194 static void slot_contract_candidate (void)
4196 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4198 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4201 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
4205 * @brief Set candidate style slot function for PanelAgent.
4207 * @param portrait_line The displayed line number for portrait.
4208 * @param mode The candidate mode.
4210 static void slot_set_candidate_style (int portrait_line, int mode)
4212 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " display_line:" << portrait_line << " mode:" << mode << "\n";
4213 if ((portrait_line != _candidate_port_line) || (mode != _candidate_mode)) {
4214 _candidate_mode = (ISF_CANDIDATE_MODE_T)mode;
4215 _candidate_port_line = (ISF_CANDIDATE_PORTRAIT_LINE_T)portrait_line;
4216 _soft_candidate_width = 0;
4217 _soft_candidate_height = 0;
4219 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4220 if (_candidate_window)
4221 ui_destroy_candidate_window ();
4226 if (_candidate_window)
4227 ui_create_candidate_window ();
4231 static unsigned int get_ise_count (TOOLBAR_MODE_T mode, bool valid_helper)
4233 unsigned int ise_count = 0;
4234 for (unsigned int i = 0; i < _ime_info.size (); i++) {
4235 if (mode == _ime_info[i].mode) {
4236 if (mode == TOOLBAR_KEYBOARD_MODE || !valid_helper)
4238 else if (_ime_info[i].is_enabled)
4247 * @brief Update keyboard ISE information slot function for PanelAgent.
4249 * @param info The information of current Keyboard ISE.
4251 static void slot_update_factory_info (const PanelFactoryInfo &info)
4253 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4255 String ise_name = info.name;
4256 String ise_icon = info.icon;
4258 String old_ise = _info_manager->get_current_ise_name ();
4259 if (old_ise != ise_name) {
4260 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && _candidate_window) {
4261 ui_destroy_candidate_window ();
4265 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
4267 if (TOOLBAR_HELPER_MODE == mode)
4268 ise_name = _ime_info[get_ise_index (_info_manager->get_current_helper_uuid())].label;
4270 if (ise_name.length () > 0)
4271 _info_manager->set_current_ise_name (ise_name);
4273 #ifdef HAVE_NOTIFICATION
4274 if (old_ise != ise_name) {
4275 if (TOOLBAR_KEYBOARD_MODE == mode) {
4276 char noti_msg[256] = {0};
4277 unsigned int keyboard_ise_count = get_ise_count (TOOLBAR_KEYBOARD_MODE, false);
4278 if (keyboard_ise_count == 0) {
4279 LOGD ("the number of keyboard ise is %d\n", keyboard_ise_count);
4282 else if (keyboard_ise_count >= 2) {
4283 snprintf (noti_msg, sizeof (noti_msg), _("%s selected"), ise_name.c_str ());
4285 else if (keyboard_ise_count == 1) {
4286 snprintf (noti_msg, sizeof (noti_msg), _("Only %s available"), ise_name.c_str ());
4289 notification_status_message_post (noti_msg);
4290 LOGD ("%s\n", noti_msg);
4297 * @brief Update cursor position slot function for PanelAgent.
4299 * @param x The x position of current cursor.
4300 * @param y The bottom y position of current cursor.
4301 * @param top_y The top y position of current cursor.
4303 static void slot_update_spot_location (int x, int y, int top_y)
4305 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4307 if (x >= 0 && x < _screen_height && y >= 0 && y < _screen_height) {
4308 _spot_location_x = x;
4309 _spot_location_y = y;
4310 _spot_location_top_y = top_y;
4312 ui_settle_candidate_window ();
4317 * @brief The input context of ISE is changed.
4319 * @param type The event type.
4320 * @param value The event value.
4322 static void slot_update_input_context (int type, int value)
4327 * @brief Update ise geometry.
4329 * @param x The x position in screen.
4330 * @param y The y position in screen.
4331 * @param width The ISE window width.
4332 * @param height The ISE window height.
4334 static void slot_update_ise_geometry (int x, int y, int width, int height)
4336 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
4338 LOGD ("x : %d , y : %d , width : %d , height : %d, _ise_state : %d\n", x, y, width, height, _ise_state);
4340 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
4341 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4342 /*IF ISE sent the ise_geometry information when the current_keyboard_mode is H/W mode and candidate_mode is SOFT_CANDIDATE,
4343 It means that given geometry information is for the candidate window */
4344 set_soft_candidate_geometry (x, y, width, height);
4352 _ise_height = height;
4354 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
4355 ui_settle_candidate_window ();
4358 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
4359 _ise_reported_geometry.valid = true;
4360 _ise_reported_geometry.angle = efl_get_ise_window_angle ();
4361 _ise_reported_geometry.geometry.pos_x = x;
4362 _ise_reported_geometry.geometry.pos_y = y;
4363 _ise_reported_geometry.geometry.width = width;
4364 _ise_reported_geometry.geometry.height = height;
4365 if (_ise_state == WINDOW_STATE_SHOW) {
4367 set_keyboard_geometry_atom_info (_app_window, _ise_reported_geometry.geometry);
4369 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
4375 * @brief Show preedit slot function for PanelAgent.
4377 static void slot_show_preedit_string (void)
4379 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4381 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4384 if (_preedit_window == NULL) {
4385 ui_create_preedit_window ();
4387 /* Move preedit window according to candidate window position */
4388 if (_candidate_window) {
4389 /* Get candidate window position */
4390 int x, y, width, height;
4391 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
4393 int height2 = ui_candidate_get_valid_height ();
4394 int angle = efl_get_app_window_angle ();
4397 x -= _preedit_height;
4398 y = _screen_height - _preedit_width;
4399 } else if (_candidate_angle == 270) {
4401 } else if (_candidate_angle == 180) {
4402 x = _screen_width - _preedit_width;
4405 y -= _preedit_height;
4408 if (_preedit_window)
4409 evas_object_move (_preedit_window, x, y);
4413 if (_preedit_window && evas_object_visible_get (_preedit_window))
4416 slot_show_candidate_table ();
4418 if (_preedit_window)
4419 evas_object_show (_preedit_window);
4423 * @brief Show aux slot function for PanelAgent.
4425 static void slot_show_aux_string (void)
4427 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4428 if (_candidate_window == NULL)
4429 ui_create_candidate_window ();
4431 if (_aux_area == NULL || _aux_area_visible)
4434 evas_object_show (_aux_area);
4435 _aux_area_visible = true;
4436 ui_candidate_window_adjust ();
4438 LOGD ("calling ui_candidate_show ()\n");
4439 ui_candidate_show ();
4440 ui_settle_candidate_window ();
4441 ui_candidate_delete_destroy_timer ();
4445 * @brief Show candidate table slot function for PanelAgent.
4447 static void slot_show_candidate_table (void)
4449 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4450 _info_manager->helper_candidate_show ();
4454 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4455 if (_candidate_window == NULL)
4456 ui_create_candidate_window ();
4459 if (_candidate_state == WINDOW_STATE_SHOW &&
4460 (_candidate_area_1_visible || _candidate_area_2_visible)) {
4461 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
4466 evas_object_show (_candidate_area_1);
4467 _candidate_area_1_visible = true;
4468 ui_candidate_window_adjust ();
4470 LOGD ("calling ui_candidate_show ()\n");
4471 ui_candidate_show ();
4472 ui_settle_candidate_window ();
4473 ui_candidate_delete_destroy_timer ();
4476 int feedback_result = feedback_initialize ();
4478 if (FEEDBACK_ERROR_NONE == feedback_result) {
4479 LOGD ("Feedback initialize successful\n");
4480 feedback_initialized = true;
4482 LOGW ("Feedback initialize fail : %d\n", feedback_result);
4483 feedback_initialized = false;
4489 * @brief Hide preedit slot function for PanelAgent.
4491 static void slot_hide_preedit_string (void)
4493 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4495 if (!_preedit_window || !evas_object_visible_get (_preedit_window))
4498 evas_object_hide (_preedit_window);
4502 * @brief Hide aux slot function for PanelAgent.
4504 static void slot_hide_aux_string (void)
4506 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4508 if (!_aux_area || !_aux_area_visible)
4511 evas_object_hide (_aux_area);
4512 _aux_area_visible = false;
4513 elm_scroller_region_show (_aux_area, 0, 0, 10, 10);
4514 ui_candidate_window_adjust ();
4516 LOGD ("calling ui_candidate_hide (false, true, true)\n");
4517 ui_candidate_hide (false, true, true);
4518 ui_settle_candidate_window ();
4520 if (ui_candidate_can_be_hide ()) {
4521 _candidate_show_requested = false;
4522 LOGD ("setting _show_candidate_requested to FALSE\n");
4527 * @brief Hide candidate table slot function for PanelAgent.
4529 static void slot_hide_candidate_table (void)
4531 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4533 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4534 _info_manager->helper_candidate_hide ();
4538 if (!_candidate_area_1 || _candidate_state == WINDOW_STATE_WILL_HIDE)
4541 if (_candidate_area_1_visible || _candidate_area_2_visible) {
4542 bool bForce = false;
4543 if (_candidate_area_1_visible) {
4544 if (_aux_area_visible) {
4545 evas_object_hide (_candidate_area_1);
4546 _candidate_area_1_visible = false;
4547 evas_object_hide (_more_btn);
4549 /* Let's not actually hide the _candidate_area_1 object, for the case that
4550 even if the application replies CANDIDATE_WILL_HIDE_ACK a little late,
4551 it is better to display the previous candidates instead of blank screen */
4552 _candidate_area_1_visible = false;
4556 if (_candidate_area_2_visible) {
4557 evas_object_hide (_candidate_area_2);
4558 _candidate_area_2_visible = false;
4559 evas_object_hide (_scroller_bg);
4560 evas_object_hide (_close_btn);
4561 _info_manager->candidate_more_window_hide ();
4563 ui_candidate_window_adjust ();
4565 LOGD ("calling ui_candidate_hide (%d, true, true)\n", bForce);
4566 ui_candidate_hide (bForce, true, true);
4567 ui_settle_candidate_window ();
4571 int feedback_result = feedback_deinitialize ();
4573 if (FEEDBACK_ERROR_NONE == feedback_result)
4574 LOGD ("Feedback deinitialize successful\n");
4576 LOGW ("Feedback deinitialize fail : %d\n", feedback_result);
4578 feedback_initialized = false;
4581 if (ui_candidate_can_be_hide ()) {
4582 _candidate_show_requested = false;
4583 LOGD ("setting _show_candidate_requested to FALSE\n");
4588 * @brief Update preedit slot function for PanelAgent.
4590 * @param str The new preedit string.
4591 * @param attrs The attribute list of new preedit string.
4593 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret)
4595 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " string=" << str << "\n";
4597 if (str.length () <= 0)
4600 if (_preedit_window == NULL || !evas_object_visible_get (_preedit_window)) {
4601 slot_show_preedit_string ();
4604 int x, y, width, height, candidate_width;
4605 evas_object_text_text_set (_tmp_preedit_text, str.c_str ());
4606 evas_object_geometry_get (_tmp_preedit_text, &x, &y, &width, &height);
4607 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &candidate_width, &height);
4608 _preedit_width = (width + ISF_PREEDIT_BORDER * 2) < candidate_width ? (width + ISF_PREEDIT_BORDER * 2) : candidate_width;
4610 /* Resize preedit window and avoid text blink */
4611 int old_width, old_height;
4612 evas_object_geometry_get (_preedit_window, &x, &y, &old_width, &old_height);
4613 if (old_width < _preedit_width) {
4614 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4615 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4617 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4618 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4621 /* Move preedit window */
4622 if (_candidate_angle == 90 || _candidate_angle == 180) {
4623 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_preedit_window)), &x, &y, &width, &height);
4624 if (_candidate_angle == 90) {
4625 y = _screen_height - _preedit_width;
4626 } else if (_candidate_angle == 180) {
4627 x = _screen_width - _preedit_width;
4629 evas_object_move (_preedit_window, x, y);
4634 * @brief Update caret slot function for PanelAgent.
4636 * @param caret The caret position.
4638 static void slot_update_preedit_caret (int caret)
4640 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " caret=" << caret << "\n";
4644 * @brief Set highlight text color and background color for edje object.
4646 * @param item The edje object pointer.
4647 * @param nForeGround The text color.
4648 * @param nBackGround The background color.
4649 * @param bSetBack The flag for background color.
4651 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack)
4653 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4655 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
4656 if (edje_object_color_class_get (item, "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4657 r = SCIM_RGB_COLOR_RED (nForeGround);
4658 g = SCIM_RGB_COLOR_GREEN (nForeGround);
4659 b = SCIM_RGB_COLOR_BLUE (nForeGround);
4660 edje_object_color_class_set (item, "text_color", r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
4662 if (bSetBack && edje_object_color_class_get (item, "rect_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4663 r = SCIM_RGB_COLOR_RED (nBackGround);
4664 g = SCIM_RGB_COLOR_GREEN (nBackGround);
4665 b = SCIM_RGB_COLOR_BLUE (nBackGround);
4666 edje_object_color_class_set (item, "rect_color", r, g, b, 255, r2, g2, b2, a2, r3, g3, b3, a3);
4671 * @brief Update aux slot function for PanelAgent.
4673 * @param str The new aux string.
4674 * @param attrs The attribute list of new aux string.
4676 static void slot_update_aux_string (const String &str, const AttributeList &attrs)
4678 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4679 if (_candidate_window == NULL)
4680 ui_create_candidate_window ();
4682 if (!_aux_area || (str.length () <= 0))
4685 if (!_aux_area_visible) {
4686 LOGD ("calling ui_candidate_show ()\n");
4687 ui_candidate_show ();
4688 slot_show_aux_string ();
4691 int x, y, width, height, item_width = 0;
4692 unsigned int window_width = 0, count = 0, i;
4694 Evas_Object *aux_edje = NULL;
4696 /* Get highlight item index */
4697 int aux_index = -1, aux_start = 0, aux_end = 0;
4698 String strAux = str;
4699 bool bSetBack = false;
4700 uint32 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
4701 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
4702 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4703 if (aux_index == -1 && ait->get_type () == SCIM_ATTR_DECORATE) {
4704 aux_index = ait->get_value ();
4705 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
4706 nForeGround = ait->get_value ();
4707 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
4708 nBackGround = ait->get_value ();
4713 std::vector<String> aux_list;
4714 scim_split_string_list (aux_list, strAux, '|');
4716 if (_aux_items.size () > 0) {
4717 for (i = 0; i < _aux_items.size (); i++)
4718 evas_object_del (_aux_items [i]);
4719 _aux_items.clear ();
4721 if (_aux_seperates.size () > 0) {
4722 for (i = 0; i < _aux_seperates.size (); i++)
4723 evas_object_del (_aux_seperates [i]);
4724 _aux_seperates.clear ();
4727 int seperate_width = 4;
4728 int seperate_height = 52 * _height_rate;
4729 Evas *evas = evas_object_evas_get (_candidate_window);
4730 for (i = 0; i < aux_list.size (); i++) {
4732 Evas_Object *seperate_item = edje_object_add (evas);
4733 edje_object_file_set (seperate_item, _candidate_edje_file.c_str (), "seperate_line");
4734 evas_object_size_hint_min_set (seperate_item, seperate_width, seperate_height);
4735 elm_table_pack (_aux_table, seperate_item, 2 * i - 1, 0, 1, 1);
4736 evas_object_show (seperate_item);
4737 _aux_seperates.push_back (seperate_item);
4741 aux_edje = edje_object_add (evas);
4742 edje_object_file_set (aux_edje, _candidate_edje_file.c_str (), "aux");
4743 edje_object_part_text_set (aux_edje, "aux", aux_list [i].c_str ());
4744 edje_object_text_class_set (aux_edje, "tizen", _candidate_font_name.c_str (), _aux_font_size);
4745 elm_table_pack (_aux_table, aux_edje, 2 * i, 0, 1, 1);
4746 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_AUX));
4747 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
4748 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_AUX));
4749 evas_object_show (aux_edje);
4750 _aux_items.push_back (aux_edje);
4751 /* if (i == (unsigned int)aux_index)
4752 edje_object_signal_emit (aux_edje, "aux,state,selected", "aux");
4754 edje_object_signal_emit (aux_edje, "aux,state,unselected", "aux");
4756 evas_object_text_text_set (_tmp_aux_text, aux_list [i].c_str ());
4757 evas_object_geometry_get (_tmp_aux_text, &x, &y, &width, &height);
4758 item_width = width + 2*_blank_width;
4759 item_width = item_width > _item_min_width ? item_width : _item_min_width;
4760 evas_object_size_hint_min_set (aux_edje, item_width, _aux_height);
4761 if (aux_index == (int)i || (aux_index == -1 && i == 0)) {
4762 aux_start = window_width;
4763 aux_end = window_width + item_width;
4765 window_width = window_width + item_width + 4;
4768 // Set highlight item
4769 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4770 if (ait->get_type () == SCIM_ATTR_DECORATE) {
4771 unsigned int index = ait->get_value ();
4772 if (index < _aux_items.size ())
4773 set_highlight_color (_aux_items [index], nForeGround, nBackGround, bSetBack);
4778 elm_scroller_region_get (_aux_area, &x, &y, &w, &h);
4779 item_width = aux_end - aux_start;
4780 if (item_width > 0) {
4781 if (item_width >= w)
4782 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4783 else if (aux_end > x + w)
4784 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4785 else if (aux_start < x)
4786 elm_scroller_region_show (_aux_area, aux_start, y, w, h);
4792 * @brief Update candidate/associate table.
4794 * @param table_type The table type.
4795 * @param table The lookup table for candidate or associate.
4797 static void update_table (int table_type, const LookupTable &table)
4799 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << table.get_current_page_size () << ")\n";
4801 int item_num = table.get_current_page_size ();
4808 AttributeList attrs;
4809 int i, x, y, item_0_width = 0;
4813 int seperate_width = 2;
4814 int seperate_height = 52 * _height_rate;
4815 int line_width = _candidate_scroll_width;
4816 int line_height = _v_padding;
4817 int total_width = 0;
4818 int current_width = 0;
4821 int more_item_count = 0;
4822 int scroll_0_width = _candidate_scroll_0_width_min;
4823 int cursor_pos = table.get_cursor_pos ();
4824 int cursor_line = 0;
4826 if (_candidate_angle == 90 || _candidate_angle == 270)
4827 scroll_0_width = _screen_height - _more_btn_width - _h_padding;
4829 scroll_0_width = _screen_width - _more_btn_width - _h_padding;
4831 _candidate_image_count = 0;
4832 _candidate_text_count = 0;
4833 _candidate_pop_image_count = 0;
4834 _candidate_display_number = 0;
4835 _candidate_row_items.clear ();
4837 Evas *evas = evas_object_evas_get (_candidate_window);
4838 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
4839 if (_candidate_0 [i]) {
4840 evas_object_del (_candidate_0 [i]);
4841 _candidate_0 [i] = NULL;
4843 if (_seperate_0 [i]) {
4844 evas_object_del (_seperate_0 [i]);
4845 _seperate_0 [i] = NULL;
4847 if (_seperate_items [i]) {
4848 evas_object_del (_seperate_items [i]);
4849 _seperate_items [i] = NULL;
4852 evas_object_del (_line_0 [i]);
4855 if (_line_items [i]) {
4856 evas_object_del (_line_items [i]);
4857 _line_items [i] = NULL;
4861 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
4863 bool bHighLight = false;
4864 bool bSetBack = false;
4865 uint32 nForeGround = SCIM_RGB_COLOR (249, 249, 249);
4866 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
4867 attrs = table.get_attributes_in_current_page (i);
4868 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4869 if (ait->get_type () == SCIM_ATTR_DECORATE && ait->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
4871 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
4872 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
4874 nForeGround = ait->get_value ();
4875 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
4877 nBackGround = ait->get_value ();
4881 wcs = table.get_candidate_in_current_page (i);
4882 mbs = utf8_wcstombs (wcs);
4884 if (!_candidate_0 [i] && total_width <= scroll_0_width) {
4885 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
4886 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_CANDIDATE_0));
4887 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
4888 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_0));
4890 /* Check whether this item is the last one */
4891 if (i == item_num - 1) {
4892 if (_candidate_angle == 90 || _candidate_angle == 270)
4893 scroll_0_width = _candidate_land_width;
4895 scroll_0_width = _candidate_port_width;
4898 /* Add first item */
4900 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
4901 evas_object_show (_candidate_0 [i]);
4902 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
4903 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, 0, item_0_width, _item_min_height);
4904 total_width += item_0_width;
4905 _candidate_display_number++;
4908 total_width += (item_0_width + seperate_width);
4909 if (total_width <= scroll_0_width) {
4910 _seperate_0 [i] = edje_object_add (evas);
4911 edje_object_file_set (_seperate_0 [i], _candidate_edje_file.c_str (), "seperate_line");
4912 evas_object_size_hint_min_set (_seperate_0 [i], seperate_width, seperate_height);
4913 elm_table_pack (_candidate_0_table, _seperate_0 [i],
4914 total_width - item_0_width - seperate_width,
4915 line_0*(_item_min_height+line_height) + (_item_min_height - seperate_height)/2,
4916 seperate_width, seperate_height);
4917 evas_object_show (_seperate_0 [i]);
4918 evas_object_show (_candidate_0 [i]);
4919 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
4920 elm_table_pack (_candidate_0_table, _candidate_0 [i], total_width - item_0_width, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
4921 _candidate_display_number++;
4923 } else if ((_candidate_angle == 0 || _candidate_angle == 180) &&
4924 (_candidate_port_line > 1 && (line_0 + 1) < _candidate_port_line)) {
4926 scroll_0_width = _candidate_scroll_0_width_min;
4927 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
4928 evas_object_show (_candidate_0 [i]);
4929 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
4930 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
4931 total_width = item_0_width;
4932 _candidate_display_number++;
4934 _candidate_row_items.push_back (i - nLast);
4938 _candidate_row_items.push_back (i - nLast);
4944 if (!_candidate_0 [i]) {
4945 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
4946 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_CANDIDATE_ITEMS));
4947 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
4948 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_ITEMS));
4950 if (current_width > 0 && current_width + item_0_width > _candidate_scroll_width) {
4954 _candidate_row_items.push_back (i - nLast);
4956 if (cursor_pos >= i)
4959 if (current_width == 0 && !_line_items [i]) {
4960 _line_items [i] = edje_object_add (evas);
4961 edje_object_file_set (_line_items [i], _candidate_edje_file.c_str (), "popup_line");
4962 evas_object_size_hint_min_set (_line_items [i], line_width, line_height);
4964 y = line_count*(_item_min_height+line_height);
4965 elm_table_pack (_candidate_table, _line_items [i], x, y, line_width, line_height);
4966 evas_object_show (_line_items [i]);
4968 if (current_width != 0 && !_seperate_items [i]) {
4969 _seperate_items [i] = edje_object_add (evas);
4970 edje_object_file_set (_seperate_items [i], _candidate_edje_file.c_str (), "seperate_line");
4971 evas_object_size_hint_min_set (_seperate_items [i], seperate_width, seperate_height);
4973 y = line_count*(_item_min_height+line_height) + line_height + (_item_min_height - seperate_height)/2;
4974 elm_table_pack (_candidate_table, _seperate_items [i], x, y, seperate_width, seperate_height);
4975 evas_object_show (_seperate_items [i]);
4976 current_width += seperate_width;
4979 y = line_count*(_item_min_height+line_height) + line_height;
4980 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
4981 evas_object_show (_candidate_0 [i]);
4982 elm_table_pack (_candidate_table, _candidate_0 [i], x, y, item_0_width, _item_min_height);
4983 current_width += item_0_width;
4985 if (candidate_expanded == false && !bHighLight)
4988 candidate_expanded = true;
4992 for (i = 1; i < _candidate_port_line; i++) {
4993 if ((_candidate_angle == 0 || _candidate_angle == 180)) {
4994 if (_line_0 [i] == NULL) {
4995 _line_0 [i] = edje_object_add (evas);
4996 edje_object_file_set (_line_0 [i], _candidate_edje_file.c_str (), "popup_line");
4997 evas_object_size_hint_min_set (_line_0 [i], line_width, line_height);
4999 y = i * (_item_min_height + line_height) - line_height;
5000 elm_table_pack (_candidate_0_table, _line_0 [i], x, y, line_width, line_height);
5001 evas_object_show (_line_0 [i]);
5004 // Create blank line
5005 if (line_0 + 1 < _candidate_port_line && i > line_0) {
5006 int nIndex = item_num + i;
5007 nIndex = nIndex < SCIM_LOOKUP_TABLE_MAX_PAGESIZE ? nIndex : SCIM_LOOKUP_TABLE_MAX_PAGESIZE - 1;
5008 _seperate_0 [nIndex] = edje_object_add (evas);
5009 edje_object_file_set (_seperate_0 [nIndex], _candidate_edje_file.c_str (), "seperate_line");
5010 evas_object_size_hint_min_set (_seperate_0 [nIndex], seperate_width, _item_min_height);
5011 elm_table_pack (_candidate_0_table, _seperate_0 [nIndex],
5012 0, i*(_item_min_height+line_height), seperate_width, _item_min_height);
5014 } else if (_line_0 [i]) {
5015 evas_object_del (_line_0 [i]);
5020 _candidate_row_items.push_back (item_num - nLast); /* Add the number of last row */
5021 _info_manager->update_displayed_candidate_number (_candidate_display_number);
5022 _info_manager->update_candidate_item_layout (_candidate_row_items);
5023 if (more_item_count == 0) {
5024 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
5025 evas_object_hide (_more_btn);
5026 evas_object_hide (_close_btn);
5027 } else if (!_candidate_area_2_visible) {
5028 evas_object_show (_more_btn);
5029 evas_object_hide (_close_btn);
5031 evas_object_hide (_more_btn);
5032 evas_object_show (_close_btn);
5036 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
5038 int line_h = _item_min_height + _v_padding;
5039 int cursor_y = cursor_line * line_h;
5041 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
5042 } else if (cursor_y >= y + h) {
5043 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
5050 * @brief Update candidate table slot function for PanelAgent.
5052 * @param table The lookup table for candidate.
5054 static void slot_update_candidate_table (const LookupTable &table)
5056 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5058 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5059 _info_manager->update_helper_lookup_table (table);
5063 if (_candidate_window == NULL)
5064 ui_create_candidate_window ();
5066 if (!_candidate_window || table.get_current_page_size () < 0)
5069 if (evas_object_visible_get (_candidate_area_2)) {
5070 candidate_expanded = true;
5072 candidate_expanded = false;
5075 update_table (ISF_CANDIDATE_TABLE, table);
5076 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
5077 ui_tts_focus_rect_hide ();
5081 * @brief Send selected candidate index.
5083 * @param selected candidate string index number.
5085 static void slot_select_candidate (int index)
5087 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5088 _info_manager->select_candidate (index);
5092 * @brief Get candidate geometry slot function for PanelAgent.
5094 * @param info The data is used to store candidate position and size.
5096 static void slot_get_candidate_geometry (struct rectinfo &info)
5103 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5107 info.height = height;
5111 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5112 /* Get candidate window position */
5113 /*ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);*/
5114 /* Get exact candidate window size */
5116 evas_object_geometry_get (_candidate_window, &x2, &y2, &width, &height);*/
5120 width = _candidate_width;
5121 height = _candidate_height;
5126 info.height = height;
5128 LOGD ("%d %d %d %d\n", info.pos_x, info.pos_y, info.width, info.height);
5129 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5130 << " width:" << info.width << " height:" << info.height << "\n";
5134 * @brief Get input panel geometry slot function for PanelAgent.
5136 * @param info The data is used to store input panel position and size.
5138 static void slot_get_input_panel_geometry (struct rectinfo &info)
5140 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
5145 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5146 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5147 info.width = _candidate_width;
5148 info.height = _candidate_height;
5150 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5151 info.width = _soft_candidate_width;
5152 info.height = _soft_candidate_height;
5154 int angle = efl_get_app_window_angle ();
5155 if (angle == 90 || angle == 270)
5156 info.pos_y = _screen_width - info.height;
5158 info.pos_y = _screen_height - info.height;
5160 info = get_ise_geometry ();
5161 if (_ise_state != WINDOW_STATE_SHOW) {
5165 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5166 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5167 int height = ui_candidate_get_valid_height ();
5169 if ((_candidate_height - height) > _ise_height) {
5170 info.pos_y = info.pos_y + info.height - _candidate_height;
5171 info.height = _candidate_height;
5173 info.pos_y -= height;
5174 info.height += height;
5181 LOGD ("%d %d %d %d\n", info.pos_x, info.pos_y, info.width, info.height);
5182 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5183 << " width:" << info.width << " height:" << info.height << "\n";
5187 * @brief Get the recent input panel geometry slot function for PanelAgent.
5189 * @param angle the rotation angle of application window.
5190 * @param info The data is used to store input panel position and size.
5192 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info)
5194 LOGD ("slot_get_recent_ise_geometry\n");
5196 /* If we have geometry reported by ISE, use the geometry information */
5201 if (angle == 0 || angle == 180) {
5202 if (_portrait_recent_ise_geometry.valid) {
5203 info = _portrait_recent_ise_geometry.geometry;
5208 if (_landscape_recent_ise_geometry.valid) {
5209 info = _landscape_recent_ise_geometry.geometry;
5220 static bool slot_check_privilege_by_sockfd (int client_id, String privilege)
5222 PrivilegeChecker privilegeChecker (client_id);
5224 bool priv_ret = privilegeChecker.checkPrivilege (privilege.c_str ());
5226 if (priv_ret == false)
5227 LOGW ("Failed to check privilege (%s)\n", privilege.c_str ());
5229 LOGD ("Succeeded to check privilege (%s)\n", privilege.c_str ());
5235 * @brief Set active ISE slot function for PanelAgent.
5237 * @param uuid The active ISE's uuid.
5238 * @param changeDefault The flag for changing default ISE.
5240 static void slot_set_active_ise (const String &uuid, bool changeDefault)
5242 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << uuid << ")\n";
5244 bool invalid = false;
5246 #if HAVE_PKGMGR_INFO
5247 /* When changing the active (default) keyboard, initialize ime_info DB if appid is invalid.
5248 This may be necessary if IME packages are changed while panel process is terminated. */
5249 pkgmgrinfo_appinfo_h handle = NULL;
5250 /* Try to get in global packages */
5251 int ret = pkgmgrinfo_appinfo_get_appinfo (uuid.c_str (), &handle);
5252 if (ret != PMINFO_R_OK) {
5253 /* Try to get in user packages */
5254 ret = pkgmgrinfo_appinfo_get_usr_appinfo (uuid.c_str (), getpid (), &handle);
5255 if (ret != PMINFO_R_OK) {
5256 LOGW ("appid \"%s\" is invalid.\n", uuid.c_str ());
5257 /* This might happen if IME is uninstalled while the panel process is inactive.
5258 The variable uuid would be invalid, so set_active_ise() would return false. */
5264 pkgmgrinfo_appinfo_destroy_appinfo (handle);
5268 _initialize_ime_info ();
5269 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5271 else if (set_active_ise (uuid, _soft_keyboard_launched) == false) {
5272 if (_initial_ise_uuid.compare (uuid))
5273 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5278 * @brief Get all ISEs list slot function for PanelAgent.
5280 * @param list The list is used to store all ISEs.
5282 * @return true if this operation is successful, otherwise return false.
5284 static bool slot_get_ise_list (std::vector<String> &list)
5286 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5288 bool result = false;
5290 std::vector<String> uuids;
5291 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5292 uuids.push_back(iter->appid);
5294 if (_ime_info.size () > 0) {
5299 result = update_ise_list (list);
5306 * @brief Get all Helper ISE information from ime_info DB.
5308 * @param info This is used to store all Helper ISE information.
5310 * @return true if this operation is successful, otherwise return false.
5312 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info)
5314 bool result = false;
5315 String active_ime_appid;
5317 info.appid.clear ();
5318 info.label.clear ();
5319 info.is_enabled.clear ();
5320 info.is_preinstalled.clear ();
5321 info.has_option.clear ();
5323 if (_ime_info.size() == 0)
5324 isf_pkg_select_all_ime_info_db (_ime_info);
5326 //active_ime_appid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5327 if (_info_manager) {
5328 active_ime_appid = _info_manager->get_current_helper_uuid ();
5331 if (_ime_info.size () > 0) {
5332 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
5333 if (iter->mode == TOOLBAR_HELPER_MODE) {
5334 info.appid.push_back (iter->appid);
5335 info.label.push_back (iter->label);
5336 info.is_enabled.push_back (iter->is_enabled);
5337 info.is_preinstalled.push_back (iter->is_preinstalled);
5338 info.has_option.push_back (static_cast<uint32>(iter->has_option));
5348 * @brief Update "has_option" column of ime_info DB by Application ID
5350 * @param[in] appid Application ID of IME to enable or disable
5351 * @param[in] has_option @c true to have IME option(setting), otherwise @c false
5353 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option)
5355 if (appid.length() == 0) {
5356 LOGW ("Invalid appid\n");
5360 if (_ime_info.size() == 0)
5361 isf_pkg_select_all_ime_info_db(_ime_info);
5363 if (isf_db_update_has_option_by_appid(appid.c_str(), has_option)) { // Update ime_info DB
5364 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5365 if (appid == _ime_info[i].appid) {
5366 _ime_info[i].has_option = static_cast<uint32>(has_option); // Update global variable
5373 * @brief Update "is_enable" column of ime_info DB by Application ID
5375 * @param[in] appid Application ID of IME to enable or disable
5376 * @param[in] is_enabled @c true to enable the IME, otherwise @c false
5378 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled)
5380 if (appid.length() == 0) {
5381 LOGW ("Invalid appid\n");
5385 if (_ime_info.size() == 0)
5386 isf_pkg_select_all_ime_info_db(_ime_info);
5388 if (isf_db_update_is_enabled_by_appid(appid.c_str(), is_enabled)) { // Update ime_info DB
5389 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5390 if (appid == _ime_info[i].appid) {
5391 _ime_info[i].is_enabled = static_cast<uint32>(is_enabled); // Update global variable
5397 #if HAVE_PKGMGR_INFO
5399 * @brief Finds appid with specific category
5401 * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative
5403 static int _find_appid_from_category (const pkgmgrinfo_appinfo_h handle, void *user_data)
5406 char **result = static_cast<char **>(user_data);
5411 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
5412 if (ret == PMINFO_R_OK) {
5413 *result = strdup (appid);
5416 LOGW ("pkgmgrinfo_appinfo_get_appid failed!\n");
5420 LOGW ("user_data is null!\n");
5423 return -1; // This callback is no longer called.
5428 * @brief Requests to open the installed IME list application.
5430 static void slot_show_helper_ise_list (void)
5432 // Launch IME List application; e.g., org.tizen.inputmethod-setting-list
5434 app_control_h app_control;
5435 char *app_id = NULL;
5436 #if HAVE_PKGMGR_INFO
5437 pkgmgrinfo_appinfo_filter_h handle;
5439 if (ime_list_app.length() < 1) {
5440 ret = pkgmgrinfo_appinfo_filter_create(&handle);
5441 if (ret == PMINFO_R_OK) {
5442 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-list");
5443 if (ret == PMINFO_R_OK) {
5444 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, _find_appid_from_category, &app_id);
5446 pkgmgrinfo_appinfo_filter_destroy(handle);
5449 ime_list_app = String(app_id);
5453 app_id = strdup(ime_list_app.c_str());
5457 ret = app_control_create (&app_control);
5458 if (ret != APP_CONTROL_ERROR_NONE) {
5459 LOGW ("app_control_create returned %d\n", ret);
5464 ret = app_control_set_operation (app_control, APP_CONTROL_OPERATION_DEFAULT);
5465 if (ret != APP_CONTROL_ERROR_NONE) {
5466 LOGW ("app_control_set_operation returned %d\n", ret);
5467 app_control_destroy(app_control);
5472 ret = app_control_set_app_id (app_control, app_id);
5473 if (ret != APP_CONTROL_ERROR_NONE) {
5474 LOGW ("app_control_set_app_id returned %d\n", ret);
5475 app_control_destroy(app_control);
5480 ret = app_control_send_launch_request(app_control, NULL, NULL);
5481 if (ret != APP_CONTROL_ERROR_NONE) {
5482 LOGW ("app_control_send_launch_request returned %d, app_id=%s\n", ret, app_id);
5483 app_control_destroy(app_control);
5488 app_control_destroy(app_control);
5489 SECURE_LOGD ("Launch %s\n", app_id);
5493 SECURE_LOGW ("AppID with http://tizen.org/category/ime-list category is not available.\n");
5498 * @brief Requests to open the installed IME selector application.
5500 static void slot_show_helper_ise_selector (void)
5502 // Launch IME Selector application; e.g., org.tizen.inputmethod-setting-selector
5504 app_control_h app_control;
5505 char *app_id = NULL;
5506 #if HAVE_PKGMGR_INFO
5507 pkgmgrinfo_appinfo_filter_h handle;
5509 if (ime_selector_app.length() < 1) {
5510 ret = pkgmgrinfo_appinfo_filter_create(&handle);
5511 if (ret == PMINFO_R_OK) {
5512 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
5513 if (ret == PMINFO_R_OK) {
5514 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, _find_appid_from_category, &app_id);
5516 pkgmgrinfo_appinfo_filter_destroy(handle);
5519 ime_selector_app = String(app_id);
5523 app_id = strdup(ime_selector_app.c_str());
5527 ret = app_control_create (&app_control);
5528 if (ret != APP_CONTROL_ERROR_NONE) {
5529 LOGW ("app_control_create returned %d\n", ret);
5534 ret = app_control_set_operation (app_control, APP_CONTROL_OPERATION_DEFAULT);
5535 if (ret != APP_CONTROL_ERROR_NONE) {
5536 LOGW ("app_control_set_operation returned %d\n", ret);
5537 app_control_destroy(app_control);
5542 ret = app_control_set_app_id (app_control, app_id);
5543 if (ret != APP_CONTROL_ERROR_NONE) {
5544 LOGW ("app_control_set_app_id returned %d\n", ret);
5545 app_control_destroy(app_control);
5550 ret = app_control_send_launch_request(app_control, NULL, NULL);
5551 if (ret != APP_CONTROL_ERROR_NONE) {
5552 LOGW ("app_control_send_launch_request returned %d, app_id=%s\n", ret, app_id);
5553 app_control_destroy(app_control);
5558 app_control_destroy(app_control);
5559 SECURE_LOGD ("Launch %s\n", app_id);
5563 SECURE_LOGW ("AppID with http://tizen.org/category/ime-selector category is not available.\n");
5567 static bool slot_is_helper_ise_enabled (String appid, int &enabled)
5569 bool is_enabled = false;
5571 if (appid.length() == 0) {
5572 LOGW ("Invalid appid.\n");
5576 if (_ime_info.size() == 0)
5577 isf_pkg_select_all_ime_info_db(_ime_info);
5579 if (isf_db_select_is_enabled_by_appid(appid.c_str(), &is_enabled)) {
5580 enabled = static_cast<int>(is_enabled);
5589 * @brief Get the ISE's information.
5591 * @param uuid The ISE's uuid.
5592 * @param name The ISE's name.
5593 * @param language The ISE's language.
5594 * @param type The ISE's type.
5595 * @param option The ISE's option.
5597 * @return true if this operation is successful, otherwise return false.
5599 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name)
5601 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5603 if (uuid.length () > 0) {
5604 // update all ISE names according to the display languages
5605 // sometimes get_ise_information is called before vconf display language changed callback is called.
5606 update_ise_locale ();
5608 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5609 if (uuid == _ime_info[i].appid) {
5610 name = _ime_info[i].label;
5611 language = _ime_info[i].languages;
5612 type = _ime_info[i].mode;
5613 option = _ime_info[i].options;
5614 module_name = _ime_info[i].module_name;
5620 std::cerr << __func__ << " is failed!!!\n";
5625 * @brief Get keyboard ISEs list slot function for PanelAgent.
5627 * @param name_list The list is used to store keyboard ISEs.
5629 * @return true if this operation is successful, otherwise return false.
5631 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list)
5633 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5635 isf_load_ise_information (ALL_ISE, _config);
5637 std::vector<String> lang_list, uuid_list;
5638 isf_get_all_languages (lang_list);
5639 isf_get_keyboard_ises_in_languages (lang_list, uuid_list, name_list, false);
5641 _info_manager->update_ise_list (uuid_list);
5646 * @brief Get enable languages list slot function for PanelAgent.
5648 * @param list The list is used to store languages.
5650 static void slot_get_language_list (std::vector<String> &list)
5652 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5655 MapStringVectorSizeT::iterator iter = _groups.begin ();
5657 for (; iter != _groups.end (); iter++) {
5658 lang_name = scim_get_language_name (iter->first);
5659 list.push_back (lang_name);
5664 * @brief Get all languages list slot function for PanelAgent.
5666 * @param lang The list is used to store languages.
5668 static void slot_get_all_language (std::vector<String> &lang)
5670 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5672 isf_get_all_languages (lang);
5676 * @brief Get specific ISE language list slot function for PanelAgent.
5678 * @param name The ISE name.
5679 * @param list The list is used to store ISE languages.
5681 static void slot_get_ise_language (char *name, std::vector<String> &list)
5683 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5688 std::vector<String> list_tmp;
5690 for (unsigned int i = 0; i < _ime_info.size(); i++) {
5691 if (!strcmp (_ime_info[i].label.c_str (), name)) {
5692 scim_split_string_list (list_tmp, _ime_info[i].languages, ',');
5693 for (i = 0; i < list_tmp.size (); i++)
5694 list.push_back (scim_get_language_name (list_tmp[i]));
5701 * @brief Get ISE information slot function for PanelAgent.
5703 * @param uuid The ISE uuid.
5704 * @param info The variable is used to store ISE information.
5706 * @return true if this operation is successful, otherwise return false.
5708 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info)
5710 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5712 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5713 if (!uuid.compare (_ime_info[i].appid)) {
5714 info.uuid = _ime_info[i].appid;
5715 info.name = _ime_info[i].label;
5716 info.icon = _ime_info[i].iconpath;
5717 info.lang = _ime_info[i].languages;
5718 info.option = _ime_info[i].options;
5719 info.type = _ime_info[i].mode;
5728 * @brief Set keyboard ISE slot function for PanelAgent.
5730 * @param uuid The variable is ISE uuid.
5732 static void slot_set_keyboard_ise (const String &uuid)
5734 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << uuid << "\n";
5736 std::vector<String> uuids;
5737 std::vector<ImeInfoDB>::iterator iter;
5738 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5739 uuids.push_back(iter->appid);
5742 if (uuid.length () <= 0 || std::find (uuids.begin (), uuids.end (), uuid) == uuids.end ())
5745 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5746 if (_ime_info[get_ise_index (default_uuid)].mode == TOOLBAR_KEYBOARD_MODE)
5749 uint32 ise_option = 0;
5750 String ise_uuid, ise_name;
5751 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5752 if (ise_uuid == uuid)
5755 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
5756 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
5760 _info_manager->change_factory (uuid);
5761 _info_manager->reload_config ();
5765 * @brief Get current keyboard ISE name and uuid slot function for PanelAgent.
5767 * @param ise_name The variable is used to store ISE name.
5768 * @param ise_uuid The variable is used to store ISE uuid.
5770 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid)
5772 uint32 ise_option = 0;
5773 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5775 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << ise_uuid << "\n";
5779 * @brief Accept connection slot function for PanelAgent.
5781 * @param fd The file descriptor to connect.
5783 static void slot_accept_connection (int fd)
5785 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5788 get_input_window ();
5793 * @brief Close connection slot function for PanelAgent.
5795 * @param fd The file descriptor to connect.
5797 static void slot_close_connection (int fd)
5799 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5804 * @brief Exit panel process slot function for PanelAgent.
5806 static void slot_exit (void)
5808 std::cerr << __FUNCTION__ << "...\n";
5809 ISF_SAVE_LOG ("exit\n");
5814 static void slot_register_helper_properties (int id, const PropertyList &props)
5816 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5818 /* WMSYNC, #2 Receiving X window ID from ISE */
5819 /* FIXME : We should add an API to set window id of ISE */
5820 Property prop = props[0];
5821 if (prop.get_label ().compare ("XID") == 0) {
5822 Ecore_X_Window xwindow = atoi (prop.get_key ().c_str ());
5823 _ise_window = xwindow;
5824 LOGD ("ISE XID : %x\n", _ise_window);
5826 /* Just in case for the helper sent this message later than show_ise request */
5827 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
5828 efl_set_transient_for_app_window (_ise_window);
5831 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_ISE_WINDOW");
5832 if (atom && _control_window && _ise_window) {
5833 ecore_x_window_prop_xid_set (_control_window, atom, ECORE_X_ATOM_WINDOW, &_ise_window, 1);
5835 #ifdef HAVE_NOTIFICATION
5836 delete_notification (&ise_selector_module_noti);
5842 static void slot_show_ise (void)
5844 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5846 /* If the current toolbar mode is not HELPER_MODE, do not proceed */
5847 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
5848 LOGD ("Current toolbar mode should be TOOLBAR_HELPER_MODE but is %d, returning\n",
5849 _info_manager->get_current_toolbar_mode ());
5853 LOGD ("slot_show_ise ()\n");
5855 delete_ise_hide_timer ();
5857 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
5858 // Unset conformant area
5859 Ecore_X_Window current_app_window = efl_get_app_window ();
5860 if (_app_window != current_app_window) {
5861 struct rectinfo info = {0, 0, 0, 0};
5862 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
5863 set_keyboard_geometry_atom_info (_app_window, info);
5864 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
5865 LOGD ("Conformant reset for window %x\n", _app_window);
5866 _app_window = current_app_window;
5868 /* If the target window has changed but our ISE is still in visible state,
5869 update the keyboard geometry information */
5870 if (_ise_state == WINDOW_STATE_SHOW) {
5871 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
5875 /* If the candidate was already in SHOW state, respect the current angle */
5876 if (_candidate_state != WINDOW_STATE_SHOW) {
5877 /* FIXME : Need to check if candidate_angle and window_angle should be left as separated */
5878 _candidate_angle = efl_get_app_window_angle ();
5880 /* If the ise was already in SHOW state, respect the current angle */
5881 if (_ise_state != WINDOW_STATE_SHOW) {
5882 _ise_angle = efl_get_app_window_angle ();
5885 ecore_x_event_mask_set (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
5886 efl_set_transient_for_app_window (_ise_window);
5888 /* Make clipboard window to have transient_for information on ISE window,
5889 so that the clipboard window will always be above ISE window */
5890 Ecore_X_Window clipboard_window = efl_get_clipboard_window ();
5891 if (_ise_window && clipboard_window) {
5892 ecore_x_icccm_transient_for_set (clipboard_window, _ise_window);
5895 /* If our ISE was already in SHOW state, skip state transition to WILL_SHOW */
5896 if (_ise_state != WINDOW_STATE_SHOW) {
5897 _ise_state = WINDOW_STATE_WILL_SHOW;
5901 _candidate_angle = 0;
5902 _ise_state = WINDOW_STATE_SHOW;
5904 show_ime_selector_notification ();
5908 static void slot_hide_ise (void)
5910 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5912 LOGD ("slot_hide_ise ()\n");
5914 if (!_ise_hide_timer)
5918 static void slot_will_hide_ack (void)
5920 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5922 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
5923 // WILL_HIDE_REQUEST_DONE Ack to WM
5924 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
5925 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
5926 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)\n",
5927 root_window, _control_window);
5928 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
5929 LOGD ("calling ui_candidate_hide (true, false)\n");
5930 ui_candidate_hide (true, false);
5933 /* WILL_HIDE_ACK means that the application finished redrawing the autoscroll area,
5934 now hide the candidate window right away if it is also in WILL_HIDE state */
5935 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
5936 candidate_window_hide ();
5939 if (_off_prepare_done_timer) {
5940 ecore_timer_del (_off_prepare_done_timer);
5941 _off_prepare_done_timer = NULL;
5946 static void slot_candidate_will_hide_ack (void)
5948 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5950 LOGD ("candidate_will_hide_ack\n");
5951 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
5952 candidate_window_hide ();
5957 static void slot_set_keyboard_mode (int mode)
5959 LOGD ("slot_set_keyboard_mode called (TOOLBAR_MODE : %d)\n",mode);
5961 change_keyboard_mode ((TOOLBAR_MODE_T)mode);
5964 static void slot_get_ise_state (int &state)
5966 if (_ise_state == WINDOW_STATE_SHOW ||
5967 ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (_candidate_state == WINDOW_STATE_SHOW))) {
5968 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
5970 /* Currently we don't have WILL_HIDE / HIDE state distinction in Ecore_IMF */
5971 switch (_ise_state) {
5972 case WINDOW_STATE_SHOW :
5973 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
5975 case WINDOW_STATE_WILL_SHOW :
5976 state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
5978 case WINDOW_STATE_WILL_HIDE :
5979 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
5981 case WINDOW_STATE_HIDE :
5982 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
5985 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
5988 LOGD ("state = %d\n", state);
5989 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " state = " << state << "\n";
5992 static void slot_start_default_ise (void)
5994 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5995 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE)) {
5996 if (_launch_ise_on_request && !_soft_keyboard_launched) {
5997 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
5999 LOGD ("Start helper (%s)\n", uuid.c_str ());
6001 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
6002 if (_info_manager->start_helper (uuid))
6003 _soft_keyboard_launched = true;
6008 static void slot_stop_default_ise (void)
6010 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6012 if (_launch_ise_on_request && _soft_keyboard_launched) {
6013 String uuid = _info_manager->get_current_helper_uuid ();
6015 if (uuid.length () > 0) {
6016 _info_manager->hide_helper (uuid);
6017 _info_manager->stop_helper (uuid);
6018 _soft_keyboard_launched = false;
6019 LOGD ("stop helper (%s)\n", uuid.c_str ());
6024 //////////////////////////////////////////////////////////////////////
6025 // End of PanelAgent-Functions
6026 //////////////////////////////////////////////////////////////////////
6030 * @brief Handler function for HelperManager input.
6032 * @param data The data to pass to this callback.
6033 * @param fd_handler The Ecore Fd handler.
6035 * @return ECORE_CALLBACK_RENEW
6037 static Eina_Bool helper_manager_input_handler (void *data, Ecore_Fd_Handler *fd_handler)
6039 if (_info_manager->has_helper_manager_pending_event ()) {
6040 if (!_info_manager->filter_helper_manager_event ()) {
6041 std::cerr << "_info_manager->filter_helper_manager_event () is failed!!!\n";
6042 LOGE ("_info_manager->filter_helper_manager_event () is failed!!!");
6047 std::cerr << "_info_manager->has_helper_manager_pending_event () is failed!!!\n";
6048 LOGE ("_info_manager->has_helper_manager_pending_event () is failed!!!");
6051 return ECORE_CALLBACK_RENEW;
6055 * @brief Callback function for abnormal signal.
6057 * @param sig The signal.
6059 static void signalhandler (int sig)
6061 std::cerr << __FUNCTION__ << " Signal=" << sig << "\n";
6062 ISF_SAVE_LOG ("Signal=%d\n", sig);
6068 static void update_ise_locale ()
6070 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
6071 if (lang_str && _locale_string.compare(lang_str) == 0) {
6076 LOGD ("update all ISE names according to display language\n");
6077 set_language_and_locale ();
6079 bool need_to_init_db = false;
6080 #if HAVE_PKGMGR_INFO
6084 pkgmgrinfo_appinfo_h handle = NULL;
6086 /* Read DB from ime_info table */
6087 isf_load_ise_information(ALL_ISE, _config);
6089 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6090 /* Try to get in global packages */
6091 ret = pkgmgrinfo_appinfo_get_appinfo(_ime_info[i].appid.c_str(), &handle);
6092 if (ret != PMINFO_R_OK) {
6093 /* Try to get in user packages */
6094 ret = pkgmgrinfo_appinfo_get_usr_appinfo(_ime_info[i].appid.c_str(), getpid (), &handle);
6097 if (ret == PMINFO_R_OK) {
6098 ret = pkgmgrinfo_appinfo_is_category_exist(handle, "http://tizen.org/category/ime", &exist);
6099 if (ret == PMINFO_R_OK && exist) {
6100 ret = pkgmgrinfo_appinfo_get_label(handle, &label);
6101 if (ret == PMINFO_R_OK && label) {
6102 _ime_info[i].label = String(label);
6103 /* Update label column in ime_info db table */
6104 if (isf_db_update_label_by_appid(_ime_info[i].appid.c_str(), label)) {
6105 _ime_info[i].label = label;
6110 // The appid is invalid.. Need to initialize ime_info DB.
6111 need_to_init_db = true;
6113 pkgmgrinfo_appinfo_destroy_appinfo(handle);
6116 // The appid is invalid.. Need to initialize ime_info DB.
6117 need_to_init_db = true;
6122 if (need_to_init_db) {
6123 _initialize_ime_info ();
6127 isf_db_update_disp_lang(lang_str);
6128 _locale_string = String (lang_str);
6134 * @brief Set language and locale.
6138 static void set_language_and_locale (void)
6140 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6142 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
6145 elm_language_set (lang_str);
6147 setenv ("LANG", lang_str, 1);
6148 setlocale (LC_MESSAGES, lang_str);
6151 setenv ("LANG", "en_US.utf8", 1);
6152 setlocale (LC_MESSAGES, "en_US.utf8");
6157 * @brief Callback function for display language change.
6159 * @param key The key node.
6160 * @param data The data to pass to this callback.
6164 static void display_language_changed_cb (keynode_t *key, void* data)
6166 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6168 set_language_and_locale ();
6170 /* Update all ISE names according to display language */
6171 update_ise_locale ();
6173 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
6174 unsigned int ise_idx = get_ise_index (default_uuid);
6176 if (ise_idx < _ime_info.size ()) {
6177 String default_name = _ime_info[ise_idx].label;
6178 _info_manager->set_current_ise_name (default_name);
6185 * @brief Change keyboard mode.
6187 * @param mode The keyboard mode.
6191 static void change_keyboard_mode (TOOLBAR_MODE_T mode)
6193 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6197 bool _support_hw_keyboard_mode = false;
6199 unsigned int val = 0;
6202 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6203 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6204 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
6206 if (mode == TOOLBAR_KEYBOARD_MODE && _support_hw_keyboard_mode) {
6207 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6208 LOGD ("HARDWARE_KEYBOARD_MODE return\n");
6212 LOGD ("HARDWARE KEYBOARD MODE\n");
6213 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 1);
6216 if (_ime_info[get_ise_index(default_uuid)].mode == TOOLBAR_HELPER_MODE) {
6217 /* Get the keyboard ISE */
6218 isf_get_keyboard_ise (_config, uuid, name, option);
6219 if (option & SCIM_IME_NOT_SUPPORT_HARDWARE_KEYBOARD) {
6220 uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
6221 std::cerr << __FUNCTION__ << ": Keyboard ISE (" << name << ") can not support hardware keyboard!!!\n";
6223 /* Try to find reasonable keyboard ISE according to helper ISE language */
6224 if (uuid == String (SCIM_COMPOSE_KEY_FACTORY_UUID)) {
6225 String helper_language = _ime_info[get_ise_index(default_uuid)].languages;
6226 if (helper_language.length () > 0) {
6227 std::vector<String> ise_langs;
6228 scim_split_string_list (ise_langs, helper_language);
6229 for (size_t i = 0; i < _groups[ise_langs[0]].size (); ++i) {
6230 int j = _groups[ise_langs[0]][i];
6231 if (_ime_info[j].appid != uuid && _ime_info[j].mode == TOOLBAR_KEYBOARD_MODE) {
6232 uuid = _ime_info[j].appid;
6240 uuid = default_uuid;
6242 _soft_candidate_width = 0;
6243 _soft_candidate_height = 0;
6244 _ise_state = WINDOW_STATE_HIDE;
6245 _info_manager->set_current_toolbar_mode (TOOLBAR_KEYBOARD_MODE);
6246 _info_manager->hide_helper (helper_uuid);
6247 _info_manager->reload_config ();
6250 #ifdef HAVE_NOTIFICATION
6251 delete_notification (&ise_selector_module_noti);
6255 /* Check whether stop soft keyboard */
6256 if (_focus_in && (_ime_info[get_ise_index (helper_uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
6257 /* If focus in and soft keyboard can support hardware key event, then don't stop it */
6259 } else if (_launch_ise_on_request && _soft_keyboard_launched) {
6260 _info_manager->stop_helper (helper_uuid);
6261 _soft_keyboard_launched = false;
6264 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6267 #ifdef HAVE_NOTIFICATION
6268 notification_status_message_post (_("Input detected from hardware keyboard"));
6270 /* Read configuations for notification app (isf-kbd-mode-changer) */
6271 String kbd_mode_changer = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_KBD_MODE_CHANGER_PROGRAM), String (""));
6272 hwkbd_module_noti.launch_app = kbd_mode_changer;
6273 LOGD ("Create kbd_mode_changer notification with : %s\n", kbd_mode_changer.c_str ());
6274 create_notification (&hwkbd_module_noti);
6278 /* Set input detected property for isf setting */
6280 ecore_x_window_prop_card32_set (_control_window, ecore_x_atom_get (PROP_X_EXT_KEYBOARD_INPUT_DETECTED), &val, 1);
6281 ecore_x_window_prop_card32_set (ecore_x_window_root_first_get (), ecore_x_atom_get (PROP_X_EXT_KEYBOARD_INPUT_DETECTED), &val, 1);
6283 } else if (mode == TOOLBAR_HELPER_MODE) {
6284 LOGD ("SOFTWARE KEYBOARD MODE\n");
6285 /* When switching back to S/W keyboard mode, let's hide candidate window first */
6286 LOGD ("calling ui_candidate_hide (true, true, true)\n");
6287 ui_candidate_hide (true, true, true);
6288 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
6290 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6291 uuid = helper_uuid.length () > 0 ? helper_uuid : _initial_ise_uuid;
6292 if (_launch_ise_on_request) {
6293 if (set_active_ise (uuid, false) == false) {
6294 if (_initial_ise_uuid.compare(uuid))
6295 set_active_ise (_initial_ise_uuid, false);
6299 if (set_active_ise (uuid, true) == false) {
6300 if (_initial_ise_uuid.compare(uuid))
6301 set_active_ise (_initial_ise_uuid, true);
6306 #ifdef HAVE_NOTIFICATION
6307 delete_notification (&hwkbd_module_noti);
6311 /* Set input detected property for isf setting */
6313 ecore_x_window_prop_card32_set (_control_window, ecore_x_atom_get (PROP_X_EXT_KEYBOARD_INPUT_DETECTED), &val, 1);
6314 ecore_x_window_prop_card32_set (ecore_x_window_root_first_get (), ecore_x_atom_get (PROP_X_EXT_KEYBOARD_INPUT_DETECTED), &val, 1);
6322 * @brief Callback function for the connection state of Bluetooth Keyboard
6324 * @param result The result of changing the connection state
6325 * @param connected The state to be changed. true means connected state, Otherwise, false.
6326 * @param remote_address The remote address
6327 * @param user_data The user data passed from the callback registration function
6331 static void _bt_cb_hid_state_changed (int result, bool connected, const char *remote_address, void *user_data)
6333 if (connected == false) {
6334 LOGD ("Bluetooth keyboard disconnected\n");
6335 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6336 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6342 static void show_ime_selector_notification ()
6344 #ifdef HAVE_NOTIFICATION
6346 unsigned int idx = get_ise_index (_info_manager->get_current_helper_uuid ());
6347 if (idx < _ime_info.size ())
6348 ise_name = _ime_info[idx].label;
6350 ise_selector_module_noti.content = ise_name.c_str ();
6352 /* Find IME Selector appid for notification */
6353 if (ime_selector_app.length () < 1) {
6354 char *app_id = NULL;
6355 pkgmgrinfo_appinfo_filter_h handle;
6356 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
6357 if (ret == PMINFO_R_OK) {
6358 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
6359 if (ret == PMINFO_R_OK) {
6360 ret = pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
6362 pkgmgrinfo_appinfo_filter_destroy (handle);
6365 ime_selector_app = String (app_id);
6371 if (ime_selector_app.length () > 0) {
6372 ise_selector_module_noti.launch_app = ime_selector_app;
6373 LOGD ("Create ise_selector notification with : %s\n", ime_selector_app.c_str ());
6374 create_notification (&ise_selector_module_noti);
6377 LOGW ("AppID with http://tizen.org/category/ime-selector category is not available\n");
6383 * @brief Callback function for ECORE_X_EVENT_WINDOW_PROPERTY.
6385 * @param data Data to pass when it is called.
6386 * @param ev_type The event type.
6387 * @param ev The information for current message.
6389 * @return ECORE_CALLBACK_PASS_ON
6391 static Eina_Bool x_event_window_property_cb (void *data, int ev_type, void *event)
6393 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6395 Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property *)event;
6398 return ECORE_CALLBACK_PASS_ON;
6400 if (ev->win == _input_win && ev->atom == ecore_x_atom_get (PROP_X_EXT_KEYBOARD_EXIST)) {
6401 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6402 unsigned int val = 0;
6403 if (ecore_x_window_prop_card32_get (_input_win, ecore_x_atom_get (PROP_X_EXT_KEYBOARD_EXIST), &val, 1) > 0) {
6405 _info_manager->reset_keyboard_ise ();
6406 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6407 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6408 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6411 } else if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
6412 if (ev->win == _control_window) {
6413 /* WMSYNC, #6 The keyboard window is displayed fully so set the conformant geometry */
6414 LOGD ("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE : win : %p, atom : %d\n", ev->win, ev->atom);
6415 Ecore_X_Virtual_Keyboard_State state;
6416 state = ecore_x_e_virtual_keyboard_state_get (ev->win);
6417 if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON) {
6418 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_ON\n");
6419 _ise_state = WINDOW_STATE_SHOW;
6421 /* Make sure that we have the same rotation angle with the keyboard window */
6423 _candidate_angle = efl_get_ise_window_angle ();
6424 _ise_angle = efl_get_ise_window_angle ();
6427 if (_candidate_show_requested) {
6428 LOGD ("calling ui_candidate_show (true)\n");
6429 ui_candidate_show (true);
6431 if (_candidate_area_1_visible) {
6432 LOGD ("calling ui_candidate_show (false)\n");
6433 ui_candidate_show (false);
6437 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6438 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6439 _info_manager->update_input_panel_event (
6440 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_SHOW);
6442 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW);
6444 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6445 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6446 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6448 show_ime_selector_notification ();
6452 _updated_hide_state_geometry = false;
6454 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
6455 } else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) {
6456 /* WMSYNC, #9 The keyboard window is hidden fully so send HIDE state */
6457 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF\n");
6458 // For now don't send HIDE signal here
6459 //_info_manager->update_input_panel_event (
6460 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6461 _ise_state = WINDOW_STATE_HIDE;
6463 if (!_updated_hide_state_geometry) {
6464 /* When the ISE gets hidden by the window manager forcefully without OFF_PREPARE,
6465 the application might not have updated its autoscroll area */
6466 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6467 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6468 _info_manager->update_input_panel_event (
6469 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6471 _updated_hide_state_geometry = true;
6473 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6474 LOGD ("calling ui_candidate_hide (true, false)\n");
6475 ui_candidate_hide (true, false);
6477 ui_settle_candidate_window ();
6480 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
6482 #ifdef HAVE_NOTIFICATION
6483 delete_notification (&ise_selector_module_noti);
6486 _ise_reported_geometry.valid = false;
6488 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
6490 ui_settle_candidate_window ();
6492 } else if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
6493 if (ev->win == efl_get_quickpanel_window ()) {
6494 int angle = efl_get_quickpanel_window_angle ();
6495 LOGD ("ev->win : %p, change window angle : %d\n", ev->win, angle);
6499 return ECORE_CALLBACK_PASS_ON;
6503 * @brief Callback function for X event client message.
6505 * @param data Data to pass when it is called.
6506 * @param type The event type.
6507 * @param event The information for current message.
6509 * @return ECORE_CALLBACK_RENEW
6511 static Eina_Bool x_event_client_message_cb (void *data, int type, void *event)
6513 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6515 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
6518 return ECORE_CALLBACK_RENEW;
6521 if ((ev->win == _control_window)) {
6522 if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST) {
6523 /* WMSYNC, #4 Send WILL_SHOW event when the keyboard window is about to displayed */
6524 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST\n");
6526 /* WMSYNC, #5 Let the Window Manager to actually show keyboard window */
6527 // WILL_SHOW_REQUEST_DONE Ack to WM
6528 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6529 ecore_x_e_virtual_keyboard_on_prepare_done_send (root_window, _control_window);
6530 LOGD ("_ecore_x_e_virtual_keyboard_on_prepare_done_send (%x, %x)\n",
6531 root_window, _control_window);
6533 _info_manager->update_input_panel_event (
6534 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
6535 ui_create_candidate_window ();
6537 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_SHOW);
6538 } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST) {
6539 _ise_state = WINDOW_STATE_WILL_HIDE;
6540 /* WMSYNC, #7 Send WILL_HIDE event when the keyboard window is about to hidden */
6541 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST\n");
6542 // Clear conformant geometry information first
6544 if (_off_prepare_done_timer) {
6545 ecore_timer_del (_off_prepare_done_timer);
6546 _off_prepare_done_timer = NULL;
6548 _off_prepare_done_timer = ecore_timer_add (1.0, off_prepare_done_timeout, NULL);
6550 _ise_reported_geometry.valid = false;
6551 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6552 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6553 _updated_hide_state_geometry = true;
6555 /* If the input panel is getting hidden because of hw keyboard mode while
6556 the candidate window is still opened, it is considered to be an
6557 "input panel being resized" event instead of "input panel being hidden",
6558 since the candidate window will work as an "input panel" afterwards */
6559 bool send_input_panel_hide_event = true;
6560 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6561 LOGD ("_candidate_state : %d", _candidate_state);
6562 if (_candidate_state == WINDOW_STATE_SHOW) {
6563 send_input_panel_hide_event = false;
6566 if (send_input_panel_hide_event) {
6567 _info_manager->update_input_panel_event (
6568 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6570 // For now don't send WILL_HIDE signal here
6571 //_info_manager->update_input_panel_event (
6572 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_HIDE);
6573 // Instead send HIDE signal
6574 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_HIDE);
6575 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE) {
6576 /* WMSYNC, #10 Register size hints for candidate window and set conformant geometry */
6577 // PRE_ROTATE_DONE Ack to WM
6578 _candidate_angle = ev->data.l[1];
6579 _ise_angle = ev->data.l[1];
6580 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE : %d\n", _candidate_angle);
6582 if (_candidate_angle == 90 || _candidate_angle == 270) {
6583 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
6585 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
6587 if (_ise_state == WINDOW_STATE_SHOW) {
6588 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6589 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6591 ui_settle_candidate_window ();
6592 ui_candidate_window_rotate (_candidate_angle);
6593 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6594 LOGD ("ecore_x_e_window_rotation_change_prepare_done_send (%d)\n", _candidate_angle);
6595 ecore_x_e_window_rotation_change_prepare_done_send (root_window,
6596 _control_window, _candidate_angle);
6597 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
6598 int ise_angle = (int)ev->data.l[1];
6599 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST for ISE WINDOW : ISE angle : %d, Candidate angle : %d\n", ise_angle, _candidate_angle);
6600 _candidate_angle = ise_angle;
6601 _ise_angle = ise_angle;
6602 if (_ise_state == WINDOW_STATE_SHOW) {
6603 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6604 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6605 ui_settle_candidate_window ();
6608 } else if (ev->win == elm_win_xwindow_get (_candidate_window)) {
6609 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST || ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE) {
6610 /* WMSYNC, #11 Actual rotate the candidate window */
6611 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
6612 _candidate_angle = (int)ev->data.l[1];
6613 ui_candidate_window_rotate (_candidate_angle);
6614 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST : %d\n", _candidate_angle);
6615 } else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE &&
6616 _ise_state != WINDOW_STATE_SHOW) {
6617 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_TRUE);
6618 _candidate_angle = (int)ev->data.l[0];
6619 if (_candidate_angle == 90 || _candidate_angle == 270) {
6620 evas_object_resize (_candidate_window, _candidate_land_width,_candidate_land_height_min);
6622 evas_object_resize (_candidate_window, _candidate_port_width,_candidate_port_height_min);
6624 ui_candidate_window_rotate (_candidate_angle);
6625 ui_settle_candidate_window ();
6626 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_FALSE);
6627 LOGD ("ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE : %d\n", _candidate_angle);
6629 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " : ANGLE (" << _candidate_angle << ")\n";
6634 /* Screen reader feature */
6635 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL) {
6636 static int last_pos_x = -10000;
6637 static int last_pos_y = -10000;
6639 if (_candidate_window) {
6640 if ((unsigned int)ev->data.l[0] == elm_win_xwindow_get (_candidate_window)) {
6641 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE) {
6642 // 1 finger double tap
6643 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger double tap focus index = " << _candidate_tts_focus_index << "\n";
6644 ui_mouse_click (_candidate_tts_focus_index);
6645 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ) {
6647 // 1 finger touch & move
6648 last_pos_x = ev->data.l[2];
6649 last_pos_y = ev->data.l[3];
6650 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger touch & move (" << last_pos_x << ", " << last_pos_y << ")\n";
6651 ui_mouse_over (last_pos_x, last_pos_y);
6652 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT ||
6653 (unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV) {
6654 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT) {
6656 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick right\n";
6657 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_display_number - 1))
6658 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : 0;
6659 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
6660 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
6661 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
6662 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
6663 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
6664 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? 0 : _candidate_row_items[0];
6665 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
6666 _candidate_tts_focus_index = _candidate_row_items[0];
6667 else if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < (g_isf_candidate_table.get_current_page_size () - 1))
6668 _candidate_tts_focus_index++;
6669 else if (_candidate_tts_focus_index == (g_isf_candidate_table.get_current_page_size () - 1))
6670 _candidate_tts_focus_index = 0;
6673 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick left\n";
6674 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == 0)
6675 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : _candidate_display_number - 1;
6676 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
6677 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
6678 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
6679 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
6680 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
6681 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
6682 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
6683 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
6684 else if (_candidate_tts_focus_index > 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ())
6685 _candidate_tts_focus_index--;
6686 else if (_candidate_tts_focus_index == 0)
6687 _candidate_tts_focus_index = g_isf_candidate_table.get_current_page_size () - 1;
6690 int x = 0, y = 0, w = 0, h = 0;
6691 _wait_stop_event = false;
6692 if (candidate_expanded) {
6694 int cursor_line = 0;
6695 for (unsigned int i = 0; i < _candidate_row_items.size (); i++) {
6696 total += _candidate_row_items [i];
6697 if (total > (int)_candidate_display_number && _candidate_tts_focus_index >= total)
6701 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
6703 int line_h = _item_min_height + _v_padding;
6704 int cursor_y = cursor_line * line_h;
6706 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
6707 _wait_stop_event = true;
6708 } else if (cursor_y >= y + h) {
6709 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
6710 _wait_stop_event = true;
6715 String strTts = String ("");
6716 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
6717 strTts = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (_candidate_tts_focus_index));
6718 if (_candidate_0 [_candidate_tts_focus_index])
6719 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
6720 } else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX) {
6721 strTts = String (_("more button"));
6722 evas_object_geometry_get (_more_btn, &x, &y, &w, &h);
6723 } else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX) {
6724 strTts = String (_("close button"));
6725 evas_object_geometry_get (_close_btn, &x, &y, &w, &h);
6727 LOGW ("TTS focus index = %d\n", _candidate_tts_focus_index);
6728 ui_tts_focus_rect_hide ();
6732 if (strTts.length () > 0)
6733 ui_play_tts (strTts.c_str ());
6735 if (w > 0 && h > 0) {
6736 if (!_wait_stop_event)
6737 ui_tts_focus_rect_show (x, y, w, h);
6739 ui_tts_focus_rect_hide ();
6746 return ECORE_CALLBACK_RENEW;
6750 Eina_Bool check_focus_out_by_popup_win ()
6752 Eina_Bool ret = EINA_FALSE;
6754 Ecore_X_Window focus_win = ecore_x_window_focus_get ();
6755 Ecore_X_Window_Type win_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
6757 if (!ecore_x_netwm_window_type_get (focus_win, &win_type))
6760 LOGD ("win type : %d\n", win_type);
6762 if (win_type == ECORE_X_WINDOW_TYPE_POPUP_MENU ||
6763 win_type == ECORE_X_WINDOW_TYPE_NOTIFICATION) {
6772 * @brief Callback function for focus out event of application window
6774 * @param data Data to pass when it is called.
6776 * @return ECORE_CALLBACK_RENEW
6778 static Eina_Bool x_event_window_focus_out_cb (void *data, int ev_type, void *event)
6780 Ecore_X_Event_Window_Focus_Out *e = (Ecore_X_Event_Window_Focus_Out*)event;
6782 if (e && e->win == _app_window) {
6783 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6784 if (check_focus_out_by_popup_win ())
6785 return ECORE_CALLBACK_RENEW;
6787 #if ENABLE_MULTIWINDOW_SUPPORT
6788 unsigned int layout = 0;
6789 LOGD ("Application window focus OUT!\n");
6790 delete_ise_hide_timer ();
6792 // Check multi window mode
6793 if (ecore_x_window_prop_card32_get (efl_get_app_window (), ECORE_X_ATOM_E_WINDOW_DESKTOP_LAYOUT, &layout, 1) != -1) {
6794 if (layout == 0 || layout == 1) {
6796 LOGD ("Multi window mode. start timer to hide IME\n");
6798 // Use timer not to hide and show IME again in focus-out and focus-in event between applications
6799 _ise_hide_timer = ecore_timer_add (ISF_ISE_HIDE_DELAY, ise_hide_timeout, NULL);
6803 if (!_ise_hide_timer) {
6804 LOGD ("Panel hides ISE\n");
6805 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
6807 ui_candidate_hide (true, false, false);
6810 LOGD ("Application window focus OUT! Panel hides ISE\n");
6811 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
6813 ui_candidate_hide (true, false, false);
6818 return ECORE_CALLBACK_RENEW;
6823 * @brief : Launches default soft keyboard for performance enhancement (It's not mandatory)
6825 static void launch_default_soft_keyboard (keynode_t *key, void* data)
6827 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6829 /* Start default ISE */
6830 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6833 static String sanitize_string (const char *str, int maxlen = 32)
6836 static char acceptables[] =
6837 "abcdefghijklmnopqrstuvwxyz"
6838 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
6841 char *newstr = NULL;
6843 newstr = new char[maxlen + 1];
6847 memset (newstr, 0x00, sizeof (char) * (maxlen + 1));
6850 while (len < maxlen && str[len] != '\0' && strchr (acceptables, str[len]) != NULL) {
6851 newstr[len] = str[len];
6861 static int launch_socket_frontend ()
6863 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
6864 LOGD ("Launching a ISF daemon with Socket FrontEnd");
6865 std::vector<String> engine_list;
6866 std::vector<String> helper_list;
6867 std::vector<String> load_engine_list;
6869 std::vector<String>::iterator it;
6871 std::cerr << "Launching a ISF daemon with Socket FrontEnd...\n";
6873 scim_get_imengine_module_list (engine_list);
6874 scim_get_helper_module_list (helper_list);
6876 for (it = engine_list.begin (); it != engine_list.end (); it++) {
6877 if (*it != "socket")
6878 load_engine_list.push_back (*it);
6880 for (it = helper_list.begin (); it != helper_list.end (); it++)
6881 load_engine_list.push_back (*it);
6883 return scim_launch (true,
6885 (load_engine_list.size () > 0 ? scim_combine_string_list (load_engine_list, ',') : "none"),
6890 int main (int argc, char *argv [])
6892 struct tms tiks_buf;
6893 _clock_start = times (&tiks_buf);
6898 bool daemon = false;
6899 bool should_resident = true;
6902 char **new_argv = new char * [40];
6903 int display_name_c = 0;
6904 ConfigModule *config_module = NULL;
6905 String config_name = String ("socket");
6906 String display_name = String ();
6907 char buf[256] = {0};
6909 Ecore_Fd_Handler *helper_manager_handler = NULL;
6911 Ecore_Event_Handler *xclient_message_handler = NULL;
6912 Ecore_Event_Handler *xwindow_property_handler = NULL;
6913 Ecore_Event_Handler *xwindow_focus_out_handler = NULL;
6916 check_time ("\nStarting ISF Panel EFL...... ");
6917 ISF_SAVE_LOG ("Starting ISF Panel EFL......\n");
6919 DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
6920 DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
6922 /* Parse command options */
6928 if (String ("-c") == argv [i] || String ("--config") == argv [i]) {
6930 std::cerr << "no argument for option " << argv [i-1] << "\n";
6934 config_name = argv [i];
6938 if (String ("-h") == argv [i] || String ("--help") == argv [i]) {
6939 std::cout << "Usage: " << argv [0] << " [option]...\n\n"
6940 << "The options are: \n"
6941 << " --display DISPLAY Run on display DISPLAY.\n"
6942 << " -c, --config NAME Uses specified Config module.\n"
6943 << " -d, --daemon Run " << argv [0] << " as a daemon.\n"
6944 << " -ns, --no-stay Quit if no connected client.\n"
6946 << " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
6947 << " -o, --output FILE Output debug information into FILE.\n"
6949 << " -h, --help Show this help message.\n";
6954 if (String ("-d") == argv [i] || String ("--daemon") == argv [i]) {
6959 if (String ("-ns") == argv [i] || String ("--no-stay") == argv [i]) {
6960 should_resident = false;
6964 if (String ("-v") == argv [i] || String ("--verbose") == argv [i]) {
6966 std::cerr << "no argument for option " << argv [i-1] << "\n";
6970 DebugOutput::set_verbose_level (atoi (argv [i]));
6974 if (String ("-o") == argv [i] || String ("--output") == argv [i]) {
6976 std::cerr << "No argument for option " << argv [i-1] << "\n";
6980 DebugOutput::set_output (argv [i]);
6984 if (String ("--display") == argv [i]) {
6986 std::cerr << "No argument for option " << argv [i-1] << "\n";
6990 display_name = sanitize_string (argv [i]);
6994 if (String ("--") == argv [i])
6997 std::cerr << "Invalid command line option: " << argv [i] << "\n";
7000 } /* End of command line parsing. */
7002 new_argv [new_argc ++] = argv [0];
7004 /* Store the rest argvs into new_argv. */
7005 for (++i; i < argc && new_argc < 37; ++i) {
7006 new_argv [new_argc ++] = argv [i];
7009 /* Make up DISPLAY env. */
7010 if (display_name.length ()) {
7011 new_argv [new_argc ++] = const_cast <char*> ("--display");
7012 display_name_c = new_argc;
7013 new_argv [new_argc ++] = strdup (display_name.c_str ());
7015 setenv ("DISPLAY", display_name.c_str (), 1);
7018 new_argv [new_argc] = 0;
7020 if (!config_name.length ()) {
7021 std::cerr << "No Config module is available!\n";
7026 /* Get current display. */
7028 const char *p = getenv ("DISPLAY");
7030 display_name = String (p);
7033 snprintf (buf, sizeof (buf), "config_name=%s display_name=%s", config_name.c_str (), display_name.c_str ());
7037 check_time ("ISF Panel EFL run as daemon");
7041 elm_init (argc, argv);
7042 check_time ("elm_init");
7044 elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
7046 //FIXME: frontend name shoule be got from paramter,set socket as dead code
7047 launch_socket_frontend ();
7049 if (config_name != "dummy") {
7050 /* Load config module */
7051 config_module = new ConfigModule (config_name);
7053 if (!config_module || !config_module->valid ()) {
7054 std::cerr << "Can not load " << config_name << " Config module.\n";
7059 _config = new DummyConfig ();
7062 /* Create config instance */
7063 if (_config.null () && config_module && config_module->valid ())
7064 _config = config_module->create_config ();
7065 if (_config.null ()) {
7066 std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
7070 check_time ("create config instance");
7073 if (!initialize_panel_agent (_config, display_name, should_resident)) {
7074 check_time ("Failed to initialize Panel Agent!");
7075 std::cerr << "Failed to initialize Panel Agent!\n";
7076 ISF_SAVE_LOG ("Failed to initialize Panel Agent!\n");
7081 } catch (scim::Exception & e) {
7082 std::cerr << e.what () << "\n";
7086 check_time ("initialize_panel_agent");
7088 /* Initialize global variables and pointers for candidate items and etc. */
7089 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; i++) {
7090 _candidate_0 [i] = NULL;
7091 _seperate_0 [i] = NULL;
7092 _seperate_items [i] = NULL;
7094 _line_items [i] = NULL;
7095 _candidate_text [i] = NULL;
7096 _candidate_image [i] = NULL;
7097 _candidate_pop_image [i] = NULL;
7101 _info_manager->send_display_name (display_name);
7102 } catch (scim::Exception & e) {
7103 std::cerr << e.what () << "\n";
7108 /* Connect the configuration reload signal. */
7109 _config->signal_connect_reload (slot (config_reload_cb));
7112 if (!efl_create_control_window ()) {
7113 LOGW ("Failed to create control window\n");
7118 efl_get_screen_resolution (_screen_width, _screen_height);
7120 _width_rate = (float)(_screen_width / 720.0);
7121 _height_rate = (float)(_screen_height / 1280.0);
7122 _blank_width = (int)(_blank_width * _width_rate);
7123 _item_min_width = (int)(_item_min_width * _width_rate);
7124 _item_min_height = (int)(_item_min_height * _height_rate);
7125 _candidate_width = (int)(_candidate_port_width * _width_rate);
7126 _candidate_height = (int)(_candidate_port_height_min * _height_rate);
7127 _indicator_height = (int)(_indicator_height * _height_rate);
7129 _aux_font_size = (int)(_aux_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7130 _candidate_font_size = (int)(_candidate_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7132 /* Load ISF configuration */
7134 check_time ("load_config");
7136 helper_manager_handler = ecore_main_fd_handler_add (_info_manager->get_helper_manager_id (), ECORE_FD_READ, helper_manager_input_handler, NULL, NULL, NULL);
7137 check_time ("run_info_manager");
7139 set_language_and_locale ();
7142 /* Add callback function for input language and display language */
7143 vconf_notify_key_changed (VCONFKEY_LANGSET, display_language_changed_cb, NULL);
7146 if (0 != register_edbus_signal_handler ())
7147 LOGW ("register edbus signal fail\n");
7150 /* Update ISE list */
7151 std::vector<String> list;
7152 update_ise_list (list);
7154 /* Load initial ISE information */
7155 _initial_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_INITIAL_ISE_UUID), String (SCIM_COMPOSE_KEY_FACTORY_UUID));
7157 /* Check if SCIM_CONFIG_DEFAULT_HELPER_ISE is available. If it's not, set it as _initial_ise_uuid.
7158 e.g., This might be necessary when the platform is upgraded from 2.3 to 2.4. */
7159 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
7160 if (helper_uuid.length() > 0 && _initial_ise_uuid.length() > 0 && helper_uuid != _initial_ise_uuid) {
7162 for (unsigned int u = 0; u < _ime_info.size (); u++) {
7163 if (_ime_info[u].mode == TOOLBAR_HELPER_MODE && helper_uuid == _ime_info[u].appid) {
7169 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), _initial_ise_uuid);
7173 /* Launches default soft keyboard when all conditions are satisfied */
7174 launch_default_soft_keyboard ();
7176 /* Update the name of each ISE according to display language */
7177 update_ise_locale ();
7178 } catch (scim::Exception & e) {
7179 std::cerr << e.what () << "\n";
7182 xclient_message_handler = ecore_event_handler_add (ECORE_X_EVENT_CLIENT_MESSAGE, x_event_client_message_cb, NULL);
7183 xwindow_property_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, x_event_window_property_cb, NULL);
7184 xwindow_focus_out_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_FOCUS_OUT, x_event_window_focus_out_cb, NULL);
7188 /* Register the callback function of Bluetooth connection */
7189 ret = bt_initialize ();
7190 if (ret != BT_ERROR_NONE)
7191 LOGW ("Fail to init Bluetooth\n");
7193 ret = bt_hid_host_initialize (_bt_cb_hid_state_changed, NULL);
7194 if (ret != BT_ERROR_NONE)
7195 LOGW ("bt_hid_host_initialize failed\n");
7198 _system_scale = elm_config_scale_get ();
7200 /* Set elementary scale */
7201 if (_screen_width) {
7202 _app_scale = _screen_width / 720.0;
7203 elm_config_scale_set (_app_scale);
7205 snprintf (buf, sizeof (buf), "%4.3f", _app_scale);
7206 setenv ("ELM_SCALE", buf, 1);
7209 signal (SIGQUIT, signalhandler);
7210 signal (SIGTERM, signalhandler);
7211 signal (SIGINT, signalhandler);
7212 signal (SIGHUP, signalhandler);
7214 check_time ("EFL Panel launch time");
7216 if (!isf_cynara_initialize())
7217 LOGW ("Failed to initialize cynara\n");
7221 isf_cynara_finish();
7227 /* deinitialize the callback function of Bluetooth connection */
7228 ret = bt_hid_host_deinitialize ();
7229 if (ret != BT_ERROR_NONE)
7230 LOGW ("bt_hid_host_deinitialize failed: %d\n", ret);
7232 ret = bt_deinitialize ();
7233 if (ret != BT_ERROR_NONE)
7234 LOGW ("bt_deinitialize failed: %d\n", ret);
7238 if (xclient_message_handler) {
7239 ecore_event_handler_del (xclient_message_handler);
7240 xclient_message_handler = NULL;
7243 if (xwindow_property_handler) {
7244 ecore_event_handler_del (xwindow_property_handler);
7245 xwindow_property_handler = NULL;
7248 if (xwindow_focus_out_handler) {
7249 ecore_event_handler_del (xwindow_focus_out_handler);
7250 xwindow_focus_out_handler = NULL;
7254 if (helper_manager_handler) {
7255 ecore_main_fd_handler_del (helper_manager_handler);
7256 helper_manager_handler = NULL;
7262 /* Remove callback function for input language and display language */
7263 vconf_ignore_key_changed (VCONFKEY_LANGSET, display_language_changed_cb);
7267 ui_destroy_candidate_window ();
7268 ui_candidate_delete_check_size_timer ();
7269 ui_candidate_delete_longpress_timer ();
7270 ui_candidate_delete_destroy_timer ();
7271 #if HAVE_PKGMGR_INFO
7273 package_manager_destroy (pkgmgr);
7282 unregister_edbus_signal_handler ();
7286 if (!_config.null ())
7289 delete config_module;
7290 if (_info_manager) {
7292 _info_manager->stop ();
7293 } catch (scim::Exception & e) {
7294 std::cerr << "Exception is thrown from _info_manager->stop (), error is " << e.what () << "\n";
7296 delete _info_manager;
7298 if ((display_name_c > 0) && new_argv [display_name_c]) {
7299 free (new_argv [display_name_c]);
7303 ISF_SAVE_LOG ("ret=%d\n", ret);
7305 std::cerr << "Successfully exited.\n";
7308 std::cerr << "Abnormally exited.\n";
7314 vi:ts=4:nowrap:expandtab