2 * ISF(Input Service Framework)
4 * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
5 * Copyright (c) 2012-2015 Samsung Electronics Co., Ltd.
7 * Contact: Haifeng Deng <haifeng.deng@samsung.com>, Jihoon Kim <jihoon48.kim@samsung.com>
9 * This library is free software; you can redistribute it and/or modify it under
10 * the terms of the GNU Lesser General Public License as published by the
11 * Free Software Foundation; either version 2.1 of the License, or (at your option)
14 * This library is distributed in the hope that it will be useful, but WITHOUT ANY
15 * WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
17 * License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this library; if not, write to the Free Software Foundation, Inc., 51
21 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
25 #define Uses_SCIM_CONFIG_PATH
26 #define Uses_SCIM_HELPER_MODULE
27 #define Uses_SCIM_PANEL_AGENT
28 #define Uses_SCIM_COMPOSE_KEY
29 #define Uses_SCIM_IMENGINE_MODULE
33 #include <sys/types.h>
35 #include <sys/times.h>
43 #include "scim_private.h"
45 #include "scim_stl_map.h"
46 #if ISF_BUILD_CANDIDATE_UI
48 #include <Elementary.h>
51 #include <Ecore_Wayland.h>
52 #endif /* HAVE_ECOREWL */
55 #endif /* HAVE_ECOREX */
58 #include <X11/Xatom.h>
65 #endif /* HAVE_FEEDBACK */
66 #endif /* CANDIDATE */
69 #include <vconf-keys.h>
72 #ifdef HAVE_NOTIFICATION
73 #include <notification.h>
74 #include <notification_internal.h>
78 #include <bluetooth.h>
80 #ifdef HAVE_PKGMGR_INFO
81 #include <package_manager.h>
82 #include <pkgmgr-info.h>
84 #include <app_control.h>
87 #include "isf_panel_efl.h"
88 #include "isf_panel_utility.h"
89 #include "isf_query_utility.h"
91 #include "privilege_checker.h"
92 #include "remote_input.h"
93 #include "tizen_profile.h"
98 /////////////////////////////////////////////////////////////////////////////
99 // Declaration of macro.
100 /////////////////////////////////////////////////////////////////////////////
101 #define EFL_CANDIDATE_THEME1 (SCIM_DATADIR "/isf_candidate_theme1.edj")
103 #define ISF_CANDIDATE_TABLE 0
105 #define ISF_EFL_AUX 1
106 #define ISF_EFL_CANDIDATE_0 2
107 #define ISF_EFL_CANDIDATE_ITEMS 3
109 #define ISE_DEFAULT_HEIGHT_PORTRAIT 444
110 #define ISE_DEFAULT_HEIGHT_LANDSCAPE 316
112 #define ISF_CANDIDATE_DESTROY_DELAY 3
113 #define ISF_ISE_HIDE_DELAY 0.15
115 #define ISF_PREEDIT_BORDER 16
116 #define ISE_LAUNCH_TIMEOUT 2.0
118 #define ISF_POP_PLAY_ICON_FILE (SCIM_ICONDIR "/pop_play.png")
119 #define ISF_KEYBOARD_ICON_FILE (SCIM_ICONDIR "/noti_keyboard_connected.png")
120 #define ISF_ISE_SELECTOR_ICON_FILE "/noti_keyboard.png"
122 #define HOST_BUS_NAME "org.tizen.usb.host"
123 #define HOST_OBJECT_PATH "/Org/Tizen/Usb/Host"
124 #define HOST_INTERFACE_NAME "org.tizen.usb.host"
125 #define HOST_KEYBOARD_SIGNAL "usbkeyboard"
126 #define HOST_ADDED "added"
127 #define HOST_REMOVED "removed"
129 #define E_PROP_DEVICEMGR_INPUTWIN "DeviceMgr Input Window"
132 /////////////////////////////////////////////////////////////////////////////
133 // Declaration of external variables.
134 /////////////////////////////////////////////////////////////////////////////
135 extern MapStringVectorSizeT _groups;
136 extern std::vector<ImeInfoDB> _ime_info;
138 CommonLookupTable g_isf_candidate_table;
141 /////////////////////////////////////////////////////////////////////////////
142 // Declaration of internal data types.
143 /////////////////////////////////////////////////////////////////////////////
144 typedef enum _WINDOW_STATE {
145 WINDOW_STATE_HIDE = 0,
146 WINDOW_STATE_WILL_HIDE,
147 WINDOW_STATE_WILL_SHOW,
152 typedef struct NotiData
161 typedef std::vector < std::pair <String, uint32> > VectorPairStringUint32;
163 /////////////////////////////////////////////////////////////////////////////
164 // Declaration of internal functions.
165 /////////////////////////////////////////////////////////////////////////////
166 #if ISF_BUILD_CANDIDATE_UI
167 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect);
168 #endif /* CANDIDATE */
171 static void efl_set_transient_for_app_window (Ecore_X_Window window);
173 #if ISF_BUILD_CANDIDATE_UI
174 static int efl_get_app_window_angle (void);
175 #endif /* CANDIDATE */
176 static int efl_get_ise_window_angle (void);
177 #if ISF_BUILD_CANDIDATE_UI
179 static int efl_get_quickpanel_window_angle (void);
180 #endif /* HAVE_ECOREX */
182 static int ui_candidate_get_valid_height (void);
183 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd = true, bool will_hide = false);
184 static void ui_destroy_candidate_window (void);
185 static void ui_settle_candidate_window (void);
186 static void ui_candidate_show (bool bSetVirtualKbd = true);
187 static void ui_create_candidate_window (void);
188 static void update_table (int table_type, const LookupTable &table);
189 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info);
190 #endif /* CANDIDATE */
191 static void set_soft_candidate_geometry (int x, int y, int width, int height);
192 #if ISF_BUILD_CANDIDATE_UI
193 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack);
194 static void ui_tts_focus_rect_hide (void);
195 #endif /* CANDIDATE */
197 #if ISF_BUILD_CANDIDATE_UI
198 static Evas_Object *get_candidate (const String& str, Evas_Object *parent, int *total_width, uint32 ForeGround, uint32 BackGround, bool HighLight, bool SetBack, int item_num, int item);
199 static bool tokenize_tag (const String& str, struct image *image_data);
200 #endif /* CANDIDATE */
202 static void launch_default_soft_keyboard (keynode_t *key = NULL, void* data = NULL);
204 /* PanelAgent related functions */
205 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident);
207 static void slot_focus_in (void);
208 static void slot_focus_out (void);
209 static void slot_expand_candidate (void);
210 static void slot_contract_candidate (void);
211 static void slot_set_candidate_style (int portrait_line, int mode);
212 static void slot_update_input_context (int type, int value);
213 static void slot_update_ise_geometry (int x, int y, int width, int height);
214 static void slot_update_spot_location (int x, int y, int top_y);
215 static void slot_update_factory_info (const PanelFactoryInfo &info);
216 static void slot_show_preedit_string (void);
217 static void slot_show_aux_string (void);
218 static void slot_show_candidate_table (void);
219 static void slot_hide_preedit_string (void);
220 static void slot_hide_aux_string (void);
221 static void slot_hide_candidate_table (void);
222 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret);
223 static void slot_update_preedit_caret (int caret);
224 static void slot_update_aux_string (const String &str, const AttributeList &attrs);
225 static void slot_update_candidate_table (const LookupTable &table);
226 static void slot_select_candidate (int index);
227 static void slot_set_active_ise (const String &uuid, bool changeDefault);
228 static bool slot_get_ise_list (std::vector<String> &list);
229 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info);
230 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option);
231 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled);
232 static void slot_show_helper_ise_list (void);
233 static void slot_show_helper_ise_selector (void);
234 static bool slot_is_helper_ise_enabled (String appid, int &enabled);
235 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name);
236 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list);
237 static void slot_get_language_list (std::vector<String> &name);
238 static void slot_get_all_language (std::vector<String> &lang);
239 static void slot_get_ise_language (char *name, std::vector<String> &list);
240 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info);
241 static void slot_get_candidate_geometry (struct rectinfo &info);
242 static void slot_get_input_panel_geometry (struct rectinfo &info);
243 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info);
244 static bool slot_check_privilege_by_sockfd (int client_id, String privilege);
245 static void slot_set_keyboard_ise (const String &uuid);
246 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid);
247 static void slot_accept_connection (int fd);
248 static void slot_close_connection (int fd);
249 static void slot_exit (void);
251 static void slot_register_helper_properties (int id, const PropertyList &props);
252 static void slot_show_ise (void);
253 static void slot_hide_ise (void);
255 static void slot_will_hide_ack (void);
256 static void slot_candidate_will_hide_ack (void);
258 static void slot_set_keyboard_mode (int mode);
259 static void slot_get_ise_state (int &state);
260 static void slot_start_default_ise (void);
261 static void slot_stop_default_ise (void);
262 static void slot_run_helper (const String &uuid, const String &config, const String &display);
263 static bool slot_launch_option_application (String ime_appid);
265 #if ENABLE_REMOTE_INPUT
266 static void slot_send_remote_input_message (const String &msg, bool len);
267 static void slot_recv_remote_surrounding_text (int cursor, const String &text);
271 static Eina_Bool efl_create_control_window (void);
272 static Ecore_X_Window efl_get_app_window (void);
273 static Ecore_X_Window efl_get_quickpanel_window (void);
274 static Ecore_X_Window efl_get_global_navigation_window (void);
277 static void change_keyboard_mode (TOOLBAR_MODE_T mode);
278 static unsigned int get_ise_index (const String uuid);
279 static bool set_active_ise (const String &uuid, bool launch_ise);
280 static bool update_ise_list (std::vector<String> &list);
281 static void update_ise_locale (const char *lang = NULL);
282 #ifdef HAVE_NOTIFICATION
283 static void delete_notification (NotificationData *noti_data);
284 static void create_notification (NotificationData *noti_data);
285 static void show_ime_selector_notification (void);
287 static void set_language_and_locale (const char *lang_str);
288 static void app_control_launch (const char *app_id);
290 /////////////////////////////////////////////////////////////////////////////
291 // Declaration of internal variables.
292 /////////////////////////////////////////////////////////////////////////////
293 #if ISF_BUILD_CANDIDATE_UI
294 static Evas_Object *_candidate_window = 0;
295 static Evas_Object *_candidate_area_1 = 0;
296 static Evas_Object *_candidate_area_2 = 0;
297 static Evas_Object *_candidate_bg = 0;
298 static Evas_Object *_candidate_0_scroll = 0;
299 static Evas_Object *_candidate_scroll = 0;
300 static Evas_Object *_scroller_bg = 0;
301 static Evas_Object *_candidate_0_table = 0;
302 static Evas_Object *_candidate_table = 0;
303 static Evas_Object *_candidate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
304 static Evas_Object *_candidate_text [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
305 static Evas_Object *_candidate_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
306 static Evas_Object *_candidate_pop_image [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
307 static Evas_Object *_seperate_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
308 static Evas_Object *_seperate_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
309 static Evas_Object *_line_0 [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
310 static Evas_Object *_line_items [SCIM_LOOKUP_TABLE_MAX_PAGESIZE];
311 static Evas_Object *_more_btn = 0;
312 static Evas_Object *_close_btn = 0;
313 static bool _candidate_show_requested = false;
314 #endif /* CANDIDATE */
315 static bool _updated_hide_state_geometry = false;
316 #if ISF_BUILD_CANDIDATE_UI
317 static int _candidate_x = 0;
318 static int _candidate_y = 0;
319 static int _candidate_width = 0;
320 static int _candidate_height = 0;
321 #endif /* CANDIDATE */
322 static int _soft_candidate_width = 0;
323 static int _soft_candidate_height = 0;
324 #if ISF_BUILD_CANDIDATE_UI
325 static int _candidate_valid_height = 0;
327 static bool _candidate_area_1_visible = false;
328 static bool _candidate_area_2_visible = false;
329 static bool _aux_area_visible = false;
330 #endif /* CANDIDATE */
332 static ISF_CANDIDATE_MODE_T _candidate_mode = SOFT_CANDIDATE_WINDOW;
333 static ISF_CANDIDATE_PORTRAIT_LINE_T _candidate_port_line = ONE_LINE_CANDIDATE;
335 #if ISF_BUILD_CANDIDATE_UI
336 static int _candidate_port_width = 480;
337 static int _candidate_port_height_min = 76;
338 static int _candidate_port_height_min_2 = 150;
339 static int _candidate_port_height_max = 286;
340 static int _candidate_port_height_max_2 = 350;
341 static int _candidate_land_width = 784;
342 static int _candidate_land_height_min = 84;
343 static int _candidate_land_height_min_2 = 168;
344 static int _candidate_land_height_max = 150;
345 static int _candidate_land_height_max_2 = 214;
346 static int _candidate_area_1_pos [2] = {0, 2};
347 static int _more_btn_pos [4] = {369, 11, 689, 11};
348 static int _close_btn_pos [4] = {362, 211, 682, 75};
349 static int _more_btn_width = 80;
350 static int _more_btn_height = 64;
352 static int _h_padding = 4;
353 static int _v_padding = 2;
354 static int _item_min_width = 99;
355 static int _item_min_height = 82;
357 static int _candidate_scroll_0_width_min = 350;
358 static int _candidate_scroll_0_width_max = 670;
360 static int _candidate_scroll_width = 453;
361 static int _candidate_scroll_width_min = 453;
362 static int _candidate_scroll_width_max = 663;
363 static int _candidate_scroll_height_min = 124;
364 static int _candidate_scroll_height_max = 190;
366 const int MORE_BUTTON_INDEX = -1;
367 const int CLOSE_BUTTON_INDEX = -2;
368 const int INVALID_TTS_FOCUS_INDEX = -100;
369 static int _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
370 static uint32 _candidate_display_number = 0;
371 static std::vector<uint32> _candidate_row_items;
372 static Evas_Object *_tts_focus_rect = 0;
373 static bool _wait_stop_event = false;
375 static Evas_Object *_preedit_window = 0;
376 static Evas_Object *_preedit_text = 0;
377 static int _preedit_width = 100;
378 static int _preedit_height = 54;
380 static Evas_Object *_aux_area = 0;
381 static Evas_Object *_aux_line = 0;
382 static Evas_Object *_aux_table = 0;
383 static int _aux_height = 0;
384 static int _aux_port_width = 444;
385 static int _aux_land_width = 764;
386 static std::vector<Evas_Object *> _aux_items;
387 static std::vector<Evas_Object *> _aux_seperates;
389 static Evas_Object *_tmp_preedit_text = 0;
390 static Evas_Object *_tmp_aux_text = 0;
391 static Evas_Object *_tmp_candidate_text = 0;
393 static int _spot_location_x = -1;
394 static int _spot_location_y = -1;
395 static int _spot_location_top_y = -1;
396 static int _candidate_angle = 0;
397 #endif /* CANDIDATE */
399 static int _ise_angle = -1;
400 static int _ise_x = 0;
401 static int _ise_y = 0;
402 static int _ise_width = 0;
403 static int _ise_height = 0;
404 static WINDOW_STATE _ise_state = WINDOW_STATE_HIDE;
405 static WINDOW_STATE _candidate_state = WINDOW_STATE_HIDE;
407 #if ISF_BUILD_CANDIDATE_UI
408 static int _indicator_height = 0;//24;
409 static int _screen_width = 720;
410 static int _screen_height = 1280;
411 static float _width_rate = 1.0;
412 static float _height_rate = 1.0;
413 static int _blank_width = 30;
415 static String _candidate_name = String ("candidate");
416 static String _candidate_edje_file = String (EFL_CANDIDATE_THEME1);
418 static String _candidate_font_name = String ("Tizen");
419 static int _candidate_font_size = 38;
420 static int _aux_font_size = 38;
421 static int _click_object = 0;
422 static int _click_down_pos [2] = {0, 0};
423 static int _click_up_pos [2] = {0, 0};
424 static bool _is_click = true;
425 #endif /* CANDIDATE */
426 static String _initial_ise_uuid = String ("");
427 static String _locale_string = String ("");
428 static ConfigPointer _config;
429 static Connection _config_connection;
431 static InfoManager *_info_manager = 0;
433 static clock_t _clock_start;
435 #if ISF_BUILD_CANDIDATE_UI
436 static Ecore_Timer *_check_size_timer = NULL;
437 static Ecore_Timer *_longpress_timer = NULL;
438 static Ecore_Timer *_destroy_timer = NULL;
439 #endif /* CANDIDATE */
441 static Ecore_Timer *_off_prepare_done_timer = NULL;
443 #if ISF_BUILD_CANDIDATE_UI
444 static Ecore_Timer *_candidate_hide_timer = NULL;
445 #endif /* CANDIDATE */
446 static Ecore_Timer *_ise_hide_timer = NULL;
449 static Ecore_X_Window _ise_window = 0;
450 static Ecore_X_Window _app_window = 0;
451 static Ecore_X_Window _control_window = 0;
452 static Ecore_X_Window _input_win = 0;
455 #ifdef HAVE_PKGMGR_INFO
456 static package_manager_h pkgmgr = NULL;
457 static VectorPairStringUint32 g_pkgids_to_be_uninstalled;
458 static Ecore_Timer *g_release_uninstalled_ime_info_timer = NULL;
459 static String g_stopped_helper_pkgid = "";
460 static Ecore_Timer *g_start_default_helper_timer = NULL;
461 static VectorPairStringUint32 g_pkgids_to_be_updated_and_installed;
462 static String g_updated_helper_pkgid = "";
465 static bool _launch_ise_on_request = false;
466 static bool _soft_keyboard_launched = false;
467 static bool _focus_in = false;
469 #if ISF_BUILD_CANDIDATE_UI
470 static bool candidate_expanded = false;
471 static int _candidate_image_count = 0;
472 static int _candidate_text_count = 0;
473 static int _candidate_pop_image_count = 0;
474 static int candidate_image_height = 38;
475 static int candidate_play_image_width_height = 19;
477 static const int CANDIDATE_TEXT_OFFSET = 2;
479 static double _app_scale = 1.0;
480 static double _system_scale = 1.0;
481 #endif /* CANDIDATE */
483 #ifdef HAVE_NOTIFICATION
484 static NotificationData hwkbd_module_noti = {"Input detected from hardware keyboard", "Tap to use virtual keyboard", ISF_KEYBOARD_ICON_FILE, "", 0};
485 static NotificationData ise_selector_module_noti = {"Select input method", NULL, "", "", 0};
488 #if ISF_BUILD_CANDIDATE_UI
490 static tts_h _tts = NULL;
494 static bool feedback_initialized = false;
496 #endif /* CANDIDATE */
498 static E_DBus_Connection *edbus_conn;
499 static E_DBus_Signal_Handler *edbus_handler;
501 #if ENABLE_REMOTE_INPUT
502 static Remote_Input* remote_input_impl = NULL;
503 static bool launch_remote_input = false;
506 #if ISF_BUILD_CANDIDATE_UI
508 static Ecore_Event_Handler *_candidate_show_handler = NULL;
510 #endif /* CANDIDATE */
512 static String ime_selector_app = "";
513 static String ime_list_app = "";
516 EMOJI_IMAGE_WIDTH = 0,
519 EMOJI_IMAGE_TAG_FLAG,
520 EMOJI_IMAGE_POP_FLAG,
527 int emoji_option[EMOJI_IMAGE_END];
530 /* This structure stores the geometry information reported by ISE */
533 bool valid; /* Whether this information is currently valid */
534 int angle; /* For which angle this information is useful */
535 struct rectinfo geometry; /* Geometry information */
538 static struct GeometryCache _ise_reported_geometry = {0, 0, {0, 0, 0, 0}};
539 static struct GeometryCache _portrait_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
540 static struct GeometryCache _landscape_recent_ise_geometry = {0, 0, {0, 0, 0, 0}};
543 static void get_input_window (void)
546 Ecore_X_Atom atom = 0;
548 if (_input_win == 0) {
549 atom = ecore_x_atom_get (E_PROP_DEVICEMGR_INPUTWIN);
550 win_ret = ecore_x_window_prop_window_get (ecore_x_window_root_first_get (), atom, &_input_win, 1);
551 if (_input_win == 0 || win_ret < 1) {
552 LOGW ("Input window is NULL!\n");
554 ecore_x_event_mask_set (_input_win, ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
560 static int pkgmgr_get_appinfo (const char *appid, pkgmgrinfo_appinfo_h *handle)
563 /* Try to get in global packages */
564 ret = pkgmgrinfo_appinfo_get_appinfo (appid, handle);
565 if (ret != PMINFO_R_OK) {
566 LOGW ("[pkgmgrinfo_appinfo_get_appinfo] appid : '%s', ret : %d\n", appid, ret);
567 /* Try to get in user packages */
568 ret = pkgmgrinfo_appinfo_get_usr_appinfo (appid, getuid (), handle);
569 if (ret != PMINFO_R_OK)
570 LOGW ("[pkgmgrinfo_appinfo_get_usr_appinfo] appid : '%s', ret : %d\n", appid, ret);
576 static void usb_keyboard_signal_cb (void *data, DBusMessage *msg)
582 LOGW ("No Message\n");
586 if (dbus_message_is_signal (msg, HOST_INTERFACE_NAME, HOST_KEYBOARD_SIGNAL) == 0) {
587 LOGW ("HOST_KEYBOARD_SIGNAL\n");
591 dbus_error_init (&err);
593 if (dbus_message_get_args (msg, &err, DBUS_TYPE_STRING, &str, DBUS_TYPE_INVALID) == 0) {
594 LOGW ("DBUS_TYPE_INVALID\n");
600 if (!strncmp (str, HOST_ADDED, strlen (HOST_ADDED))) {
601 LOGD ("HOST_ADDED\n");
605 if (!strncmp (str, HOST_REMOVED, strlen (HOST_REMOVED))) {
606 LOGD ("HOST_REMOVED\n");
607 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
608 change_keyboard_mode (TOOLBAR_HELPER_MODE);
613 LOGW ("ERROR: msg (%s) is improper\n", str);
616 static void unregister_edbus_signal_handler (void)
619 LOGD ("unregister signal handler for keyboard\n");
621 e_dbus_signal_handler_del (edbus_conn, edbus_handler);
622 edbus_handler = NULL;
624 e_dbus_connection_close (edbus_conn);
630 static int register_edbus_signal_handler (void)
633 LOGD ("start register_edbus_signal_handler\n");
636 while (e_dbus_init () == 0) {
639 LOGW ("retry fail\n");
644 edbus_conn = e_dbus_bus_get (DBUS_BUS_SYSTEM);
646 LOGW ("connection fail\n");
650 edbus_handler = e_dbus_signal_handler_add (edbus_conn, NULL, HOST_OBJECT_PATH, HOST_INTERFACE_NAME, HOST_KEYBOARD_SIGNAL, usb_keyboard_signal_cb, NULL);
651 if (!edbus_handler) {
652 LOGW ("cannot register signal\n");
656 LOGD ("Success register\n");
661 #ifdef HAVE_NOTIFICATION
662 static void delete_notification (NotificationData *noti_data)
664 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
666 if (!_MOBILE) return;
668 if (noti_data->noti_id != 0) {
669 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
670 LOGD ("deleted notification : %s\n", noti_data->launch_app.c_str ());
671 noti_data->noti_id = 0;
675 static void create_notification (NotificationData *noti_data)
677 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
679 notification_h notification = NULL;
682 if (!_MOBILE) return;
684 if (noti_data->noti_id != 0) {
685 notification_delete_by_priv_id ("isf-panel-efl", NOTIFICATION_TYPE_ONGOING, noti_data->noti_id);
686 noti_data->noti_id = 0;
689 notification = notification_create (NOTIFICATION_TYPE_ONGOING);
690 if (notification != NULL) {
691 notification_set_pkgname (notification, "isf-panel-efl");
692 notification_set_layout (notification, NOTIFICATION_LY_ONGOING_EVENT);
694 notification_set_image (notification, NOTIFICATION_IMAGE_TYPE_ICON, noti_data->icon);
696 if (noti_data->title)
697 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_TITLE, _(noti_data->title), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
699 if (noti_data->content)
700 notification_set_text (notification, NOTIFICATION_TEXT_TYPE_CONTENT, _(noti_data->content), NULL, NOTIFICATION_VARIABLE_TYPE_NONE);
702 notification_set_display_applist (notification, NOTIFICATION_DISPLAY_APP_NOTIFICATION_TRAY);
704 app_control_h service = NULL;
705 if (app_control_create (&service) == APP_CONTROL_ERROR_NONE) {
706 app_control_set_operation (service, APP_CONTROL_OPERATION_DEFAULT);
707 app_control_set_app_id (service, noti_data->launch_app.c_str ());
709 notification_set_launch_option (notification, NOTIFICATION_LAUNCH_OPTION_APP_CONTROL, (void *)service);
710 ret = notification_insert (notification, ¬i_data->noti_id);
711 if (ret != NOTIFICATION_ERROR_NONE) {
712 LOGW ("Failed to insert notification. error code : %d\n", ret);
714 app_control_destroy (service);
717 LOGW ("Failed to create appcontrol\n");
719 notification_free (notification);
722 LOGW ("Failed to create notification\n");
725 #endif /* HAVE_NOTIFICATION */
727 #if ISF_BUILD_CANDIDATE_UI
728 static bool tokenize_tag (const String& str, struct image *image_token)
730 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
731 if (str.length () <= 0) {
732 LOGW ("str is empty!!!\n");
736 char **tag_str = NULL;
738 tag_str = eina_str_split (str.c_str (), "\u3013", 0);
743 for (i = 0; tag_str [i]; i++) {
745 if (str.length () == strlen (tag_str[i])) {
755 image_token->path = String (tag_str[i]);
757 if (i - 1 < EMOJI_IMAGE_END)
758 image_token->emoji_option [i - 1] = atoi (tag_str[i]);
760 LOGW ("emoji option is more than EMOJI_IMAGE_END!!!\n");
772 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)
774 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << ", length=" << str.length () << "\n";
776 struct image image_data;
777 int object_width = 0, text_width = 0, image_width = 0, image_height = 0, max_width = 0, button_width = 0;
779 int image_get_width = 0, image_get_height = 0;
780 char image_key [10] = {0, };
781 char **splited_string = NULL;
782 char **sub_splited_string = NULL;
783 double image_rate = 0.0;
784 bool tokenize_result = false;
785 bool candidate_is_long = false;
787 Evas_Object *candidate_object_table = NULL;
788 Evas_Object *candidate_object_table_bg_rect = NULL;
789 Evas_Object *candidate_left_padding = NULL;
791 candidate_object_table = elm_table_add (parent);
793 candidate_left_padding = evas_object_rectangle_add (evas_object_evas_get (parent));
794 evas_object_size_hint_weight_set (candidate_left_padding, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
795 evas_object_size_hint_align_set (candidate_left_padding, EVAS_HINT_FILL, EVAS_HINT_FILL);
796 evas_object_size_hint_min_set (candidate_left_padding, _blank_width, 1);
797 evas_object_color_set (candidate_left_padding, 0, 0, 0, 0);
798 elm_table_pack (candidate_object_table, candidate_left_padding, 0, 0, _blank_width, 1);
799 evas_object_show (candidate_left_padding);
801 object_width += _blank_width;
802 if (item_num > 1 && item_index == 0)
803 button_width = 92 * _width_rate;
807 splited_string = eina_str_split (str.c_str (), "\uE000", 0);
808 if (splited_string) {
809 for (i = 0; splited_string [i]; i++) {
810 if (candidate_is_long)
812 sub_splited_string = eina_str_split (splited_string [i], "\uE001", 0);
813 if (sub_splited_string) {
814 for (j = 0; sub_splited_string [j]; j++) {
815 if (candidate_is_long)
817 tokenize_result = tokenize_tag (sub_splited_string [j], &image_data);
818 if (tokenize_result && _candidate_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
819 _candidate_image [_candidate_image_count] = elm_image_add (parent);
820 snprintf (image_key, sizeof (image_key), "%d", _candidate_image_count);
821 elm_image_file_set (_candidate_image [_candidate_image_count], image_data.path.c_str (), image_key);
822 elm_image_animated_set (_candidate_image [_candidate_image_count], EINA_TRUE);
823 elm_image_animated_play_set (_candidate_image [_candidate_image_count], EINA_TRUE);
824 elm_image_object_size_get (_candidate_image [_candidate_image_count], &image_get_width, &image_get_height);
825 LOGD ("image_path=%s, key=%s\n", image_data.path.c_str (), image_key);
827 if (image_get_height > image_get_width)
828 image_rate = ((double)candidate_image_height / (double)image_get_width);
830 image_rate = ((double)candidate_image_height / (double)image_get_height);
832 image_width = (int)((double)image_get_width * image_rate);
833 image_height = candidate_image_height;
835 if (_candidate_angle == 90 || _candidate_angle == 270)
836 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
838 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
840 if (image_width > max_width) {
841 Evas_Object *candidate_end = edje_object_add (evas_object_evas_get (parent));
842 edje_object_file_set (candidate_end, _candidate_edje_file.c_str (), _candidate_name.c_str ());
843 evas_object_show (candidate_end);
844 edje_object_part_text_set (candidate_end, "candidate", "...");
845 edje_object_scale_set (_candidate_text [_candidate_text_count], _height_rate);
847 text_width = max_width;
848 evas_object_size_hint_min_set (candidate_end, text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
849 if (HighLight || SetBack) {
850 set_highlight_color (candidate_end, ForeGround, BackGround, SetBack);
852 elm_table_pack (candidate_object_table, candidate_end, object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
853 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
855 if (_candidate_image [_candidate_image_count]) {
856 evas_object_del (_candidate_image [_candidate_image_count]);
857 _candidate_image [_candidate_image_count] = NULL;
859 candidate_is_long = true;
863 evas_object_resize (_candidate_image [_candidate_image_count], image_width, image_height);
864 evas_object_show (_candidate_image [_candidate_image_count]);
865 evas_object_size_hint_min_set (_candidate_image [_candidate_image_count], image_width, image_height);
867 elm_table_pack (candidate_object_table, _candidate_image [_candidate_image_count], object_width, 1, image_width, image_height);
868 object_width += image_width;
869 _candidate_image_count++;
871 if (image_data.emoji_option [EMOJI_IMAGE_POP_FLAG] == 1 && image_width > 0 && _candidate_pop_image_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
872 _candidate_pop_image [_candidate_pop_image_count] = elm_image_add (parent);
873 elm_image_file_set (_candidate_pop_image [_candidate_pop_image_count], ISF_POP_PLAY_ICON_FILE, image_key);
874 evas_object_resize (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
875 evas_object_show (_candidate_pop_image [_candidate_pop_image_count]);
876 evas_object_size_hint_min_set (_candidate_pop_image [_candidate_pop_image_count], candidate_play_image_width_height, candidate_play_image_width_height);
878 elm_table_pack (candidate_object_table, _candidate_pop_image [_candidate_pop_image_count],
879 object_width - candidate_play_image_width_height, image_height - candidate_play_image_width_height - 2,
880 candidate_play_image_width_height, candidate_play_image_width_height);
882 _candidate_pop_image_count++;
885 } else if (strlen (sub_splited_string [j]) > 0 && _candidate_text_count < SCIM_LOOKUP_TABLE_MAX_PAGESIZE) {
886 _candidate_text [_candidate_text_count] = edje_object_add (evas_object_evas_get (parent));
887 edje_object_file_set (_candidate_text [_candidate_text_count], _candidate_edje_file.c_str (), _candidate_name.c_str ());
888 evas_object_show (_candidate_text [_candidate_text_count]);
889 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", sub_splited_string [j]);
890 edje_object_text_class_set (_candidate_text [_candidate_text_count], "tizen",
891 _candidate_font_name.c_str (), _candidate_font_size);
892 evas_object_text_text_set (_tmp_candidate_text, sub_splited_string [j]);
893 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &text_width, NULL);
895 if (_candidate_angle == 90 || _candidate_angle == 270)
896 max_width = _candidate_land_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
898 max_width = _candidate_port_width - (_blank_width + object_width + button_width + (2 * CANDIDATE_TEXT_OFFSET));
900 if (text_width > max_width) {
901 candidate_is_long = true;
902 /* In order to avoid overlap issue, calculate show_string */
903 String show_string = String (sub_splited_string [j]);
904 int show_length = text_width;
905 while (show_length > max_width && show_string.length () > 1) {
906 show_string = show_string.substr (0, show_string.length () - 1);
907 evas_object_text_text_set (_tmp_candidate_text, (show_string + String ("...")).c_str ());
908 evas_object_geometry_get (_tmp_candidate_text, NULL, NULL, &show_length, NULL);
910 edje_object_part_text_set (_candidate_text [_candidate_text_count], "candidate", (show_string + String ("...")).c_str ());
911 text_width = max_width;
914 evas_object_size_hint_min_set (_candidate_text [_candidate_text_count], text_width + (2 * CANDIDATE_TEXT_OFFSET), _item_min_height);
915 if (HighLight || SetBack) {
916 set_highlight_color (_candidate_text [_candidate_text_count], ForeGround, BackGround, SetBack);
918 elm_table_pack (candidate_object_table, _candidate_text [_candidate_text_count], object_width, 0, text_width + (2 * CANDIDATE_TEXT_OFFSET), _candidate_font_size);
919 object_width += (text_width + (2 * CANDIDATE_TEXT_OFFSET));
920 _candidate_text_count++;
926 if (splited_string [0])
927 free (splited_string [0]);
929 free (splited_string);
932 if (sub_splited_string) {
933 if (sub_splited_string [0])
934 free (sub_splited_string [0]);
936 free (sub_splited_string);
939 *total_width = object_width + _blank_width;
941 candidate_object_table_bg_rect = edje_object_add (evas_object_evas_get (parent));
942 edje_object_file_set (candidate_object_table_bg_rect, _candidate_edje_file.c_str (), "candidate_object_table");
943 evas_object_size_hint_weight_set (candidate_object_table_bg_rect, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
944 evas_object_size_hint_align_set (candidate_object_table_bg_rect, EVAS_HINT_FILL, EVAS_HINT_FILL);
945 evas_object_size_hint_min_set (candidate_object_table_bg_rect, *total_width, _item_min_height);
946 elm_table_pack (candidate_object_table, candidate_object_table_bg_rect, 0, 0, *total_width, _item_min_height);
947 evas_object_show (candidate_object_table_bg_rect);
949 evas_object_size_hint_align_set (candidate_object_table, EVAS_HINT_FILL, EVAS_HINT_FILL);
950 evas_object_size_hint_weight_set (candidate_object_table, EVAS_HINT_EXPAND, 0.0);
952 return candidate_object_table;
954 #endif /* CANDIDATE */
956 /////////////////////////////////////////////////////////////////////////////
957 // Implementation of internal functions.
958 /////////////////////////////////////////////////////////////////////////////
960 * @brief Print system time point for panel performance.
962 * @param strInfo The output information.
964 static void check_time (const char *strInfo)
966 gettime (_clock_start, strInfo);
967 ISF_LOG ("%s ppid=%d pid=%d\n", strInfo, getppid (), getpid ());
971 * @brief Flush memory for elm.
975 static void flush_memory (void)
977 #if ISF_BUILD_CANDIDATE_UI
978 elm_cache_all_flush ();
983 #if ISF_BUILD_CANDIDATE_UI
985 * @brief Get ISE geometry information.
986 * Returns the "expected" ISE geometry when kbd_state is ON, otherwise w/h set to 0
988 * @param info The data is used to store ISE position and size.
989 * @param kbd_state The keyboard state.
991 static struct rectinfo get_ise_geometry ()
993 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
995 struct rectinfo info = {0, 0, 0, 0};
999 Ecore_X_Window gnb_win = efl_get_global_navigation_window ();
1001 ecore_x_window_size_get (gnb_win, &w, &h);
1004 int win_w = _screen_width, win_h = _screen_height;
1005 int angle = (_ise_angle == -1) ? efl_get_app_window_angle () : _ise_angle;
1008 /* The height of global navigation bar */
1011 if (angle == 90 || angle == 270) {
1012 win_w = _screen_height;
1013 win_h = _screen_width;
1018 /* If we have geometry reported by ISE, use the geometry information */
1019 if (_ise_reported_geometry.valid && _ise_reported_geometry.angle == angle) {
1020 info = _ise_reported_geometry.geometry;
1021 /* But still, if the current ISE is not in SHOW state, set w/h to 0 */
1022 if (_ise_state != WINDOW_STATE_SHOW) {
1023 info.pos_y = (win_h > win_w) ? win_h : win_w;
1028 /* READ ISE's SIZE HINT HERE */
1031 int pos_x, pos_y, width, height;
1032 if (ecore_x_e_window_rotation_geometry_get (_ise_window, angle,
1033 &pos_x, &pos_y, &width, &height)) {
1037 if (angle == 90 || angle == 270) {
1038 info.width = height;
1039 info.height = width;
1042 info.height = height;
1045 info.pos_x = (int)info.width > win_w ? 0 : (win_w - info.width) / 2;
1046 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
1048 info.pos_y = (win_h > win_w) ? win_h : win_w;
1052 if (_ise_state == WINDOW_STATE_SHOW) {
1053 info.pos_y = win_h - info.height - gnb_height;
1055 info.pos_y = (win_h > win_w) ? win_h : win_w;
1061 LOGD ("angle : %d, w_angle : %d, mode : %d, Geometry : %d %d %d %d\n",
1063 _info_manager->get_current_toolbar_mode (),
1064 info.pos_x, info.pos_y, info.width, info.height);
1073 // FIXME: Get the ISE's SIZE.
1081 _ise_width = info.width;
1082 _ise_height = info.height;
1086 #endif /* CANDIDATE */
1090 * @brief Set keyboard geometry for autoscroll.
1091 * This includes the ISE geometry together with candidate window
1093 * @param kbd_state The keyboard state.
1095 static void set_keyboard_geometry_atom_info (Ecore_X_Window window, struct rectinfo ise_rect)
1097 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1099 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
1102 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1103 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1104 ise_rect.width = _candidate_width;
1105 ise_rect.height = _candidate_height;
1107 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
1108 ise_rect.width = _soft_candidate_width;
1109 ise_rect.height = _soft_candidate_height;
1112 int angle = efl_get_app_window_angle ();
1113 if (angle == 90 || angle == 270)
1114 ise_rect.pos_y = _screen_width - ise_rect.height;
1116 ise_rect.pos_y = _screen_height - ise_rect.height;
1118 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
1119 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
1120 _candidate_valid_height = ui_candidate_get_valid_height ();
1121 if ((_candidate_height - _candidate_valid_height) > _ise_height) {
1122 _candidate_valid_height = _candidate_height;
1123 ise_rect.pos_y = ise_rect.pos_y + ise_rect.height - _candidate_height;
1124 ise_rect.height = _candidate_height;
1126 ise_rect.pos_y -= _candidate_valid_height;
1127 ise_rect.height += _candidate_valid_height;
1133 ecore_x_e_illume_keyboard_geometry_set (window, ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1134 LOGD ("KEYBOARD_GEOMETRY_SET : %d %d %d %d\n", ise_rect.pos_x, ise_rect.pos_y, ise_rect.width, ise_rect.height);
1135 SCIM_DEBUG_MAIN (3) << " KEYBOARD_GEOMETRY x=" << ise_rect.pos_x << " y=" << ise_rect.pos_y
1136 << " width=" << ise_rect.width << " height=" << ise_rect.height << "\n";
1138 /* even the kbd_state is OFF, consider the keyboard is still ON if we have candidate opened */
1139 if (ise_rect.width == 0 && ise_rect.height == 0) {
1140 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1142 ecore_x_e_virtual_keyboard_state_set (window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1144 if (_ise_angle == 0 || _ise_angle == 180) {
1145 _portrait_recent_ise_geometry.valid = true;
1146 _portrait_recent_ise_geometry.geometry = ise_rect;
1149 _landscape_recent_ise_geometry.valid = true;
1150 _landscape_recent_ise_geometry.geometry = ise_rect;
1157 * @brief Get ISE index according to uuid.
1159 * @param uuid The ISE uuid.
1161 * @return The ISE index
1163 static unsigned int get_ise_index (const String uuid)
1165 unsigned int index = 0;
1166 if (uuid.length () > 0) {
1167 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1168 if (uuid == _ime_info[i].appid) {
1178 static void set_keyboard_engine (String active_uuid)
1180 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
1181 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
1182 if (active_uuid != keyboard_uuid) {
1183 _info_manager->change_factory (active_uuid);
1184 _config->write (IMENGINE_KEY, active_uuid);
1189 static void _update_ime_info(void)
1191 std::vector<String> ise_langs;
1194 isf_pkg_select_all_ime_info_db(_ime_info);
1196 /* Update _groups */
1198 for (size_t i = 0; i < _ime_info.size (); ++i) {
1199 scim_split_string_list(ise_langs, _ime_info[i].languages);
1200 for (size_t j = 0; j < ise_langs.size (); j++) {
1201 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
1202 _groups[ise_langs[j]].push_back (i);
1208 static void _initialize_ime_info (void)
1210 std::vector<ImeInfoDB>::iterator iter;
1211 VectorPairStringUint32 ime_on_off;
1212 // Store is_enabled values of each keyboard
1213 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1214 if (iter->mode == TOOLBAR_HELPER_MODE) {
1215 ime_on_off.push_back (std::make_pair (iter->appid, iter->is_enabled));
1218 // Delete the whole ime_info DB and reload
1219 isf_db_delete_ime_info ();
1220 _update_ime_info ();
1221 // Restore is_enabled value to valid keyboards
1222 for (iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
1223 if (iter->mode == TOOLBAR_HELPER_MODE) {
1224 for (VectorPairStringUint32::iterator it = ime_on_off.begin (); it != ime_on_off.end (); it++) {
1225 if (it->first.compare (iter->appid) == 0) {
1226 if (it->second != iter->is_enabled) {
1227 iter->is_enabled = it->second;
1228 isf_db_update_is_enabled_by_appid (iter->appid.c_str (), static_cast<bool>(iter->is_enabled));
1230 ime_on_off.erase (it);
1238 #ifdef HAVE_PKGMGR_INFO
1240 * @brief Insert or update ime_info data with pkgid.
1242 * @param pkgid pkgid to insert/update ime_info table.
1244 * @return 1 on successful insert, 2 on successful update, -1 if pkgid is not IME package, otherwise return 0.
1246 static int _isf_insert_ime_info_by_pkgid(const char *pkgid)
1249 pkgmgrinfo_pkginfo_h handle = NULL;
1250 int result = 0; // 0: not IME, 1: Inserted, 2: Updated (because of the same appid)
1251 uid_t uid = getpid ();
1255 LOGW ("pkgid is null.\n");
1259 /* Try to get in global packages */
1260 ret = pkgmgrinfo_pkginfo_get_pkginfo (pkgid, &handle);
1261 if (ret != PMINFO_R_OK) {
1262 /* Try to get in user packages */
1263 ret = pkgmgrinfo_pkginfo_get_usr_pkginfo (pkgid, uid, &handle);
1264 if (ret != PMINFO_R_OK) {
1265 LOGW ("Failed to call pkgmgrinfo_pkginfo_get_pkginfo & get_usr_pkginfo(\"%s\",~) returned %d\n", pkgid, ret);
1274 /* Try to get in user packages */
1275 ret = pkgmgrinfo_appinfo_get_usr_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result, uid);
1278 /* Try to get in global packages */
1279 ret = pkgmgrinfo_appinfo_get_list (handle, PMINFO_UI_APP, isf_pkg_ime_app_list_cb, (void *)&result);
1282 if (ret != PMINFO_R_OK) {
1283 LOGW ("Failed to call %s failed(%d)\n", user ? "pkgmgrinfo_appinfo_get_usr_list" : "pkgmgrinfo_appinfo_get_list", ret);
1290 pkgmgrinfo_pkginfo_destroy_pkginfo (handle);
1296 * @brief Timer to start initial Helper ISE if the active (selected) 3rd party keyboard is uninstalled.
1298 * @param data User data
1300 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1301 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1303 static Eina_Bool _start_default_helper_timer(void *data)
1305 std::vector<String> total_appids;
1306 std::vector<ImeInfoDB>::iterator it;
1307 VectorPairStringUint32::iterator iter;
1309 /* Let panel know that ISE is deleted... */
1310 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1311 total_appids.push_back(it->appid);
1313 if (total_appids.size() > 0)
1314 _info_manager->update_ise_list (total_appids);
1316 LOGD ("Try to start the initial helper\n");
1317 set_active_ise(_initial_ise_uuid, true);
1319 for (iter = g_pkgids_to_be_uninstalled.begin (); iter != g_pkgids_to_be_uninstalled.end (); iter++) {
1320 if (iter->first.compare(g_stopped_helper_pkgid) == 0) {
1321 g_pkgids_to_be_uninstalled.erase (iter);
1325 g_stopped_helper_pkgid = "";
1327 g_start_default_helper_timer = NULL;
1328 return ECORE_CALLBACK_CANCEL;
1332 * @brief Timer to release uninstalled IME related info; g_pkgids_to_be_uninstalled has appid and is_enabled.
1334 * @param data User data
1336 * @return If it returns ECORE_CALLBACK_RENEW, it will be called again at the next tick, or if it returns
1337 * ECORE_CALLBACK_CANCEL it will be deleted automatically making any references/handles for it invalid.
1339 static Eina_Bool _release_uninstalled_pkginfo_timer(void *data)
1341 g_pkgids_to_be_uninstalled.clear ();
1342 g_release_uninstalled_ime_info_timer = NULL;
1343 return ECORE_CALLBACK_CANCEL;
1347 * @brief Called when the package is installed, uninstalled or updated, and the progress of the request to the package manager changes.
1349 * @param[in] type The type of the package to be installed, uninstalled or updated
1350 * @param[in] package The name of the package to be installed, uninstalled or updated
1351 * @param[in] event_type The type of the request to the package manager
1352 * @param[in] event_state The current state of the request to the package manager
1353 * @param[in] progress The progress for the request that is being processed by the package manager \n
1354 * The range of progress is from 0 to 100
1355 * @param[in] error The error code when the package manager failed to process the request
1356 * @param[in] user_data The user data passed from package_manager_set_event_cb()
1357 * @see package_manager_set_event_cb()
1358 * @see package_manager_unset_event_cb()
1360 INFO: Package install/update/uninstall scenario
1361 Install and Uninstall are obviously simple.
1362 Install: just INSTALL
1363 Uninstall: just UNINSTALL
1364 Update package (change the source codes in IME project and Run As again), there are four scenarios:
1367 2. UNINSTALL -> INSTALL
1368 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Check "Enable Project specific settings"
1369 and change Application ID in tizen-manifest.xml file and Run As.
1370 3. UPDATE -> INSTALL
1371 This happens when Tizen IDE Property > Tizen SDK > Rapid Development Support > Uncheck "Enable Project specific settings"
1372 and change Application ID in tizen-manifest.xml file and Run As.
1373 At UPDATE event, pkgid (package parameter) is invalid...
1375 Exceptionally, only UPDATE can be called when Application ID in tizen-manifest.xml file is changed.
1376 At UPDATE event, pkgid (package parameter) is valid, and only appid is changed; the previous appid is invalid.
1378 If multiple packages (including non-IME pkgs) are uninstalled and installed; Z300H UPS (ultra power saving) mode scenario.
1379 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
1381 Assuming IMEngine won't be changed through this. IMEngine might have multiple appids for one pkgid.
1382 Assuming preinstalled IME won't be changed through this.
1384 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)
1386 String current_ime_appid; // now appid is uuid.
1387 std::vector<String> appids;
1388 std::vector<String> total_appids;
1389 std::vector<ImeInfoDB>::iterator it;
1390 std::vector<String>::iterator it2;
1391 VectorPairStringUint32::iterator it3;
1394 if (!package || !type)
1397 if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UPDATE) {
1398 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1399 LOGD ("type=%s package=%s event_type=UPDATE event_state=COMPLETED progress=%d error=%d", type, package, progress, error);
1401 ret = _isf_insert_ime_info_by_pkgid (package); // If package is not IME, -1 would be returned.
1402 if (ret == 1) { // In case the package is updated with the changed appid. In this case, there will be two IMEs
1403 ret = isf_db_select_appids_by_pkgid (package, appids);
1405 if (_ime_info.size () > 0 && _ime_info [get_ise_index (appids.front ())].is_enabled)
1406 isf_db_update_is_enabled_by_appid (appids.back ().c_str (), true);
1407 isf_db_delete_ime_info_by_appid (appids.front ().c_str ());
1410 _update_ime_info ();
1412 /* Let panel know that ise list is changed... */
1413 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1414 total_appids.push_back(it->appid);
1416 if (total_appids.size() > 0)
1417 _info_manager->update_ise_list (total_appids);
1419 if (ret > 1 && _soft_keyboard_launched) { // If the previous appid of pkgid is the current IME, restart it with new appid.
1420 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1421 if (current_ime_appid.compare (appids.front ()) == 0) {
1422 LOGD ("Stop IME(%s)\n", current_ime_appid.c_str ());
1423 _info_manager->hide_helper (current_ime_appid);
1424 _info_manager->stop_helper (current_ime_appid);
1425 LOGD ("Start IME(%s)\n", appids.back ().c_str ());
1426 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids.back ());
1427 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1428 _info_manager->start_helper (appids.back ());
1432 else if (ret == 2) { // In case IME package is just updated...
1433 _update_ime_info ();
1435 if (_soft_keyboard_launched) { // If package is the current IME, restart it.
1436 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1437 if (isf_db_select_appids_by_pkgid(package, appids)) {
1438 if (std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the current ISE package is updated, restart it.
1439 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1440 if (it->mode == TOOLBAR_HELPER_MODE && it->appid.compare(current_ime_appid) == 0) { // Make sure it's Helper ISE...
1441 LOGD ("Restart IME(%s)\n", current_ime_appid.c_str ());
1442 _info_manager->hide_helper (current_ime_appid);
1443 _info_manager->stop_helper (current_ime_appid);
1444 _info_manager->start_helper (current_ime_appid);
1452 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...
1453 if (isf_db_select_appids_by_pkgid(package, appids) == 1) {
1454 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1455 if (it->pkgid.compare(package) == 0) {
1456 g_pkgids_to_be_updated_and_installed.push_back (std::make_pair (it->pkgid, it->is_enabled));
1460 if (it == _ime_info.end ()) // Probably not going to happen.
1461 g_pkgids_to_be_updated_and_installed.push_back(std::make_pair (String(package), 0));
1463 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1464 if (_soft_keyboard_launched && std::find(appids.begin(), appids.end(), current_ime_appid) != appids.end()) { // If the updated IME is the current ISE...
1465 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1466 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1467 LOGD ("Stop IME(%s)\n", current_ime_appid.c_str ());
1468 _info_manager->hide_helper (current_ime_appid);
1469 _info_manager->stop_helper (current_ime_appid);
1470 _soft_keyboard_launched = false;
1471 g_updated_helper_pkgid = package;
1477 if (appids.size () > 0) // Probably appids size is 1.
1478 LOGD ("Delete IME(%s)\n", appids[0].c_str ());
1479 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1482 /* Let panel know that ise is deleted... */
1483 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1484 total_appids.push_back(it->appid);
1486 if (total_appids.size() > 0)
1487 _info_manager->update_ise_list (total_appids);
1491 LOGW ("isf_db_select_appids_by_pkgid returned %d.\n", ret);
1496 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_INSTALL) {
1497 if (event_state == PACKAGE_MANAGER_EVENT_STATE_COMPLETED) {
1498 LOGD ("type=%s package=%s event_type=INSTALL event_state=COMPLETED progress=%d error=%d\n", type, package, progress, error);
1500 ///////////////// UNINSTALL -> INSTALL and if the uninstalled IME is reinstalled /////////////////
1501 if (g_stopped_helper_pkgid.compare(package) == 0 && g_start_default_helper_timer) {
1502 LOGD ("Cancel timer to start the default IME\n");
1503 ecore_timer_del(g_start_default_helper_timer);
1504 g_start_default_helper_timer = NULL;
1505 g_stopped_helper_pkgid = "";
1507 ret = _isf_insert_ime_info_by_pkgid(package);
1509 /* Find appid by pkgid. There might be multiple appid, but assume Helper always has one appid.
1510 And appid can be changed, but pkgid won't be changed. */
1511 ret = isf_db_select_appids_by_pkgid(package, appids);
1512 if (ret == 1 && appids.size () == 1) {
1513 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1514 if (it3->first.compare(package) == 0) {
1516 isf_db_update_is_enabled_by_appid(appids[0].c_str (), (bool)it3->second);
1520 /* Let panel know that ise is added... */
1521 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1522 total_appids.push_back(it->appid);
1524 if (total_appids.size() > 0)
1525 _info_manager->update_ise_list (total_appids);
1527 LOGD ("Restart IME(%s)\n", appids[0].c_str ());
1528 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), appids[0]);
1529 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1530 _info_manager->start_helper (appids[0]);
1531 _soft_keyboard_launched = true;
1533 g_pkgids_to_be_uninstalled.erase (it3);
1539 LOGW ("isf_db_select_appids_by_pkgid returned %d.\n", ret);
1543 /* Let panel know that ise is added... */
1544 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1545 total_appids.push_back(it->appid);
1547 if (total_appids.size() > 0)
1548 _info_manager->update_ise_list (total_appids);
1552 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.\n", ret);
1555 else { // If new package is installed...
1556 ret = _isf_insert_ime_info_by_pkgid(package); // If package is not IME, -1 would be returned.
1557 if (ret > 0) { // In case package is IME...
1558 ///////////////// INSTALL /////////////////
1561 /* Let panel know that ise is added... */
1562 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1563 total_appids.push_back(it->appid);
1565 if (total_appids.size() > 0)
1566 _info_manager->update_ise_list (total_appids);
1567 ///////////////// END /////////////////
1569 /* For example, the following happens if appid is changed in IME project and Run As again. The appid would be changed this time.
1570 Assuming only Helper (3rd party) might be installed after update or uninstall and there is one appid per each pkgid...*/
1572 ///////////////// UPDATE -> INSTALL /////////////////
1573 for (it3 = g_pkgids_to_be_updated_and_installed.begin (); it3 != g_pkgids_to_be_updated_and_installed.end (); it3++) {
1574 if (it3->first.compare(package) == 0) {
1576 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1577 if (it->pkgid.compare(package) == 0) {
1578 it->is_enabled = it3->second;
1579 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1584 g_pkgids_to_be_updated_and_installed.erase (it3);
1588 if (g_updated_helper_pkgid.compare(package) == 0) {
1589 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1590 if (it->mode == TOOLBAR_HELPER_MODE && it->pkgid.compare(package) == 0) {
1591 LOGD ("Start IME(%s)\n", it->appid.c_str ());
1592 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), it->appid);
1593 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1594 _info_manager->start_helper (it->appid);
1595 _soft_keyboard_launched = true;
1599 g_updated_helper_pkgid = "";
1602 ///////////////// END /////////////////
1604 ///////////////// UNINSTALL -> INSTALL /////////////////
1605 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1606 if (it3->first.compare(package) == 0) {
1608 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1609 if (it->pkgid.compare(package) == 0) {
1610 it->is_enabled = it3->second;
1611 isf_db_update_is_enabled_by_appid(it->appid.c_str (), (bool)it->is_enabled);
1616 g_pkgids_to_be_uninstalled.erase (it3);
1620 ///////////////// END /////////////////
1622 else if (ret == 0) {
1623 LOGW ("_isf_insert_ime_info_by_pkgid returned %d.\n", ret);
1628 else if (event_type == PACKAGE_MANAGER_EVENT_TYPE_UNINSTALL) {
1629 switch (event_state) {
1630 case PACKAGE_MANAGER_EVENT_STATE_STARTED:
1631 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=STARTED progress=%d error=%d\n", type, package, progress, error);
1633 // Need to check if there is "http://tizen.org/category/ime" category; it can be done by comparing pkgid with ime_info db.
1635 if (_ime_info.size() == 0)
1638 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1639 if (it->pkgid.compare(package) == 0 && it->is_preinstalled == 0) { // Ignore if it's preinstalled IME and IMEngine.
1646 // 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.
1647 LOGD ("%s for pkgid(\"%s\") is about to be deleted\n", it->appid.c_str (), package);
1648 g_pkgids_to_be_uninstalled.push_back(std::make_pair (String(package), it->is_enabled));
1650 if (_soft_keyboard_launched && isf_db_select_appids_by_pkgid(package, appids)) {
1651 current_ime_appid = scim_global_config_read(String(SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
1652 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.
1653 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1654 if (it->appid.compare(current_ime_appid) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1655 LOGD ("Stop IME(%s)\n", current_ime_appid.c_str ());
1656 _info_manager->hide_helper (current_ime_appid);
1657 _info_manager->stop_helper (current_ime_appid);
1658 _soft_keyboard_launched = false;
1659 g_stopped_helper_pkgid = package;
1669 case PACKAGE_MANAGER_EVENT_STATE_COMPLETED:
1670 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=COMPLETED progress=%d error=%d\n", type, package, progress, error);
1672 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1673 if (it3->first.compare(package) == 0) {
1674 if (isf_db_delete_ime_info_by_pkgid(package)) { // Delete package from ime_info db.
1678 if (g_stopped_helper_pkgid.compare(package) == 0) { // If the uninstalled ISE is the current ISE, start the initial helper ISE by timer.
1679 if (g_start_default_helper_timer)
1680 ecore_timer_del(g_start_default_helper_timer);
1681 LOGD ("Add timer to start the default IME\n");
1682 g_start_default_helper_timer = ecore_timer_add(3.0, _start_default_helper_timer, NULL);
1684 else { // Need to clean up g_pkgids_to_be_uninstalled info unless the same package is installed again; e.g., UNINSTALL -> INSTALL case.
1685 if (g_release_uninstalled_ime_info_timer)
1686 ecore_timer_del(g_release_uninstalled_ime_info_timer);
1687 LOGD ("Add timer to release uninstalled IME pkg info\n");
1688 g_release_uninstalled_ime_info_timer = ecore_timer_add(7.0, _release_uninstalled_pkginfo_timer, NULL);
1691 /* Let panel know that ise is deleted... */
1692 for (it = _ime_info.begin(); it != _ime_info.end(); it++) {
1693 total_appids.push_back(it->appid);
1695 if (total_appids.size() > 0)
1696 _info_manager->update_ise_list (total_appids);
1703 case PACKAGE_MANAGER_EVENT_STATE_FAILED:
1704 LOGD ("type=%s package=%s event_type=UNINSTALL event_state=FAILED progress=%d error=%d\n", type, package, progress, error);
1706 for (it3 = g_pkgids_to_be_uninstalled.begin (); it3 != g_pkgids_to_be_uninstalled.end (); it3++) {
1707 if (it3->first.compare(package) == 0) {
1708 // Update _ime_info for sure...
1711 if (g_stopped_helper_pkgid.compare(package) == 0) {
1712 ret = isf_db_select_appids_by_pkgid(package, appids);
1713 if (ret == 1 && appids.size () == 1) {
1714 for (it = _ime_info.begin (); it != _ime_info.end (); it++) {
1715 if (it->appid.compare(appids[0]) == 0 && it->mode == TOOLBAR_HELPER_MODE) { // Make sure it's Helper ISE...
1716 LOGD ("Restart IME(%s)\n", appids[0].c_str ());
1717 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1718 _info_manager->start_helper (appids[0]);
1719 _soft_keyboard_launched = true;
1725 LOGW ("isf_db_select_appids_by_pkgid returned %d.\n", ret);
1727 g_stopped_helper_pkgid = "";
1730 g_pkgids_to_be_uninstalled.erase (it3);
1744 * @brief Set keyboard ISE.
1746 * @param uuid The keyboard ISE's uuid.
1748 * @return false if keyboard ISE change is failed, otherwise return true.
1750 static bool set_keyboard_ise (const String &uuid)
1752 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1754 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1756 if (TOOLBAR_HELPER_MODE == mode) {
1757 String pre_uuid = _info_manager->get_current_helper_uuid ();
1758 _info_manager->hide_helper (pre_uuid);
1759 _info_manager->stop_helper (pre_uuid);
1760 _soft_keyboard_launched = false;
1761 } else if (TOOLBAR_KEYBOARD_MODE == mode) {
1762 uint32 kbd_option = 0;
1763 String kbd_uuid, kbd_name;
1764 isf_get_keyboard_ise (_config, kbd_uuid, kbd_name, kbd_option);
1765 if (kbd_uuid == uuid)
1769 _info_manager->change_factory (uuid);
1771 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
1772 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
1778 * @brief Set helper ISE.
1780 * @param uuid The helper ISE's uuid.
1781 * @param launch_ise The flag for launching helper ISE.
1783 * @return false if helper ISE change is failed, otherwise return true.
1785 static bool set_helper_ise (const String &uuid, bool launch_ise)
1787 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1789 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
1790 String pre_uuid = _info_manager->get_current_helper_uuid ();
1791 LOGD ("pre_appid=%s, appid=%s, launch_ise=%d, %d\n", pre_uuid.c_str(), uuid.c_str(), launch_ise, _soft_keyboard_launched);
1792 if (pre_uuid == uuid && _soft_keyboard_launched)
1795 if (TOOLBAR_HELPER_MODE == mode && pre_uuid.length () > 0 && _soft_keyboard_launched) {
1796 _info_manager->hide_helper (pre_uuid);
1797 _info_manager->stop_helper (pre_uuid);
1798 _soft_keyboard_launched = false;
1799 LOGD ("stop helper : %s\n", pre_uuid.c_str ());
1803 LOGD ("Start helper (%s)\n", uuid.c_str ());
1805 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
1806 if (_info_manager->start_helper (uuid))
1807 _soft_keyboard_launched = true;
1809 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), uuid);
1815 * @brief Set active ISE.
1817 * @param uuid The ISE's uuid.
1818 * @param launch_ise The flag for launching helper ISE.
1820 * @return false if ISE change is failed, otherwise return true.
1822 static bool set_active_ise (const String &uuid, bool launch_ise)
1824 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1825 LOGD ("set ISE (%s) %d\n", uuid.c_str(), launch_ise);
1827 if (uuid.length () <= 0)
1830 bool ise_changed = false, valid = false;
1832 for (unsigned int i = 0; i < _ime_info.size (); i++) {
1833 if (!uuid.compare (_ime_info[i].appid)) {
1834 if (TOOLBAR_KEYBOARD_MODE == _ime_info[i].mode)
1835 ise_changed = set_keyboard_ise (_ime_info[i].appid);
1836 else if (TOOLBAR_HELPER_MODE == _ime_info[i].mode) {
1837 if (_ime_info[i].is_enabled) {
1838 if (_ime_info[i].exec == String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
1839 /* If IME so is deleted somehow, main() in scim_helper_launcher.cpp will return -1.
1840 Checking HelperModule validity seems necessary here. */
1841 HelperModule helper_module (_ime_info[i].module_name);
1842 if (helper_module.valid ())
1844 helper_module.unload ();
1847 /* executable type */
1852 ise_changed = set_helper_ise (_ime_info[i].appid, launch_ise);
1854 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 ());
1857 LOGW ("Helper ISE(appid=\"%s\") is not enabled.\n", _ime_info[i].appid.c_str ());
1860 _info_manager->set_current_toolbar_mode (_ime_info[i].mode);
1862 /* From Tizen 4.0 all the ISEs need to handle H/W keyboard events */
1863 _ime_info[i].options |= ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT;
1864 _info_manager->set_current_helper_option (_ime_info[i].options);
1865 _info_manager->set_current_ise_name (_ime_info[i].label);
1868 _ise_state = WINDOW_STATE_HIDE;
1869 _candidate_mode = SOFT_CANDIDATE_WINDOW;
1870 _candidate_port_line = ONE_LINE_CANDIDATE;
1871 _soft_candidate_width = 0;
1872 _soft_candidate_height = 0;
1873 #if ISF_BUILD_CANDIDATE_UI
1874 if (_candidate_window)
1875 ui_create_candidate_window ();
1878 scim_global_config_write (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _ime_info[i].appid);
1879 scim_global_config_flush ();
1885 vconf_set_str (VCONFKEY_ISF_ACTIVE_KEYBOARD_UUID, uuid.c_str ());
1897 * @brief Load ISF configuration and ISEs information.
1899 static void load_config (void)
1901 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1903 /* Read configurations. */
1904 if (!_config.null ()) {
1905 bool shared_ise = _config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), false);
1906 _info_manager->set_should_shared_ise (shared_ise);
1908 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), _launch_ise_on_request);
1910 isf_load_ise_information (ALL_ISE, _config);
1914 * @brief Reload config callback function for ISF panel.
1916 * @param config The config pointer.
1918 static void config_reload_cb (const ConfigPointer &config)
1921 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
1922 /* load_config (); */
1923 _info_manager->reload_config ();
1926 #if ISF_BUILD_CANDIDATE_UI
1927 //////////////////////////////////////////////////////////////////////
1928 // Start of Candidate Functions
1929 //////////////////////////////////////////////////////////////////////
1931 * @brief Get candidate window valid height for autoscroll.
1933 * @return The valid height.
1935 static int ui_candidate_get_valid_height (void)
1937 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
1942 if (_candidate_window) {
1943 if (_candidate_state == WINDOW_STATE_SHOW)
1944 angle = _candidate_angle;
1946 angle = efl_get_app_window_angle ();
1948 if (_aux_area_visible && _candidate_area_1_visible) {
1949 if (angle == 90 || angle == 270)
1950 height = _candidate_land_height_min_2;
1952 height = _candidate_port_height_min_2;
1954 if (angle == 90 || angle == 270)
1955 height = _candidate_land_height_min;
1957 height = _candidate_port_height_min;
1964 * @brief Resize candidate window size.
1966 * @param new_width New width for candidate window.
1967 * @param new_height New height for candidate window.
1969 static void ui_candidate_window_resize (int new_width, int new_height)
1971 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " width:" << new_width << " height:" << new_height << "\n";
1973 if (!_candidate_window)
1978 LOGD ("%s (w: %d, h: %d)\n", __func__, new_width, new_height);
1979 evas_object_resize (_aux_line, new_width, 2);
1980 _candidate_width = new_width;
1981 _candidate_height = new_height;
1982 if (_candidate_state == WINDOW_STATE_SHOW)
1983 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
1985 if (_candidate_state == WINDOW_STATE_SHOW && _candidate_mode == FIXED_CANDIDATE_WINDOW) {
1986 height = ui_candidate_get_valid_height ();
1987 if ((_ise_width == 0 && _ise_height == 0) ||
1988 (_ise_height > 0 && _candidate_valid_height != height) ||
1989 (_ise_height > 0 && (_candidate_height - height) > _ise_height) ||
1990 ((_candidate_angle == 90 || _candidate_angle == 270) && (_ise_width < _screen_height)) ||
1991 ((_candidate_angle == 0 || _candidate_angle == 180) && (_ise_width > _screen_width ))) {
1993 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
1995 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
1999 /* Get height for portrait and landscape */
2000 int port_width = _candidate_port_width;
2001 int port_height = _candidate_port_height_min;
2002 int land_width = _candidate_land_width;
2003 int land_height = _candidate_land_height_min;
2004 if (_candidate_angle == 90 || _candidate_angle == 270) {
2005 land_height = new_height;
2006 if (land_height == _candidate_land_height_min_2) {
2007 port_height = _candidate_port_height_min_2;
2008 } else if (land_height == _candidate_land_height_max) {
2009 port_height = _candidate_port_height_max;
2010 } else if (land_height == _candidate_land_height_max_2) {
2011 port_height = _candidate_port_height_max_2;
2014 port_height = new_height;
2015 if (port_height == _candidate_port_height_min_2) {
2016 land_height = _candidate_land_height_min_2;
2017 } else if (port_height == _candidate_port_height_max) {
2018 land_height = _candidate_land_height_max;
2019 } else if (port_height == _candidate_port_height_max_2) {
2020 land_height = _candidate_land_height_max_2;
2024 LOGD ("window_rotation_geometry_set (_candidate_window), port (%d, %d), land (%d, %d)\n",
2025 port_width, port_height, land_width, land_height);
2029 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2030 0, 0, 0, port_width, port_height);
2031 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2032 90, 0, 0, land_height, land_width);
2033 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2034 180, 0, 0, port_width, port_height);
2035 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
2036 270, 0, 0, land_height, land_width);
2039 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
2040 0, 0, 0, port_width, port_height);
2041 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
2042 90, 0, 0, land_height, land_width);
2043 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
2044 180, 0, 0, port_width, port_height);
2045 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
2046 270, 0, 0, land_height, land_width);
2051 * @brief This function will show/hide widgets of candidate window,
2052 * and resize candidate window size according to aux_area/candidate_area.
2054 static void ui_candidate_window_adjust (void)
2056 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2057 if (!_candidate_window)
2060 int x = 0, y = 0, width = 0, height = 0;
2062 /* Get candidate window size */
2065 if (_candidate_angle == 90 || _candidate_angle == 270) {
2066 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2067 &x, &y, &height, &width);
2069 ecore_x_e_window_rotation_geometry_get (elm_win_xwindow_get (_candidate_window), _candidate_angle,
2070 &x, &y, &width, &height);
2074 if (_candidate_angle == 90 || _candidate_angle == 270)
2075 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &height, &width);
2077 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
2080 if (_aux_area_visible && _candidate_area_2_visible) {
2081 evas_object_show (_aux_line);
2082 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);
2083 if (_candidate_angle == 90 || _candidate_angle == 270) {
2084 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2085 _ise_height > _candidate_land_height_max_2 - _candidate_land_height_min_2)
2086 ui_candidate_window_resize (width, _candidate_land_height_min_2 + _ise_height);
2088 ui_candidate_window_resize (width, _candidate_land_height_max_2);
2089 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2090 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min_2);
2091 evas_object_move (_scroller_bg, 0, _candidate_land_height_min_2);
2092 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2094 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2095 _ise_height > _candidate_port_height_max_2 - _candidate_port_height_min_2)
2096 ui_candidate_window_resize (width, _candidate_port_height_min_2 + _ise_height);
2098 ui_candidate_window_resize (width, _candidate_port_height_max_2);
2099 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2100 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min_2);
2101 evas_object_move (_scroller_bg, 0, _candidate_port_height_min_2);
2102 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2104 } else if (_aux_area_visible && _candidate_area_1_visible) {
2105 evas_object_show (_aux_line);
2106 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);
2107 if (_candidate_angle == 90 || _candidate_angle == 270) {
2108 ui_candidate_window_resize (width, _candidate_land_height_min_2);
2109 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3] + _candidate_port_height_min_2 - _candidate_port_height_min);
2110 evas_object_resize (_candidate_bg, width, _candidate_land_height_min_2);
2112 ui_candidate_window_resize (width, _candidate_port_height_min_2);
2113 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1] + _candidate_port_height_min_2 - _candidate_port_height_min);
2114 evas_object_resize (_candidate_bg, width, _candidate_port_height_min_2);
2116 } else if (_aux_area_visible) {
2117 evas_object_hide (_aux_line);
2118 ui_candidate_window_resize (width, _aux_height + 2);
2119 evas_object_resize (_candidate_bg, width, _aux_height + 2);
2120 } else if (_candidate_area_2_visible) {
2121 evas_object_hide (_aux_line);
2122 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2123 if (_candidate_angle == 90 || _candidate_angle == 270) {
2124 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2125 _ise_height > _candidate_land_height_max - _candidate_land_height_min)
2126 ui_candidate_window_resize (width, _candidate_land_height_min + _ise_height);
2128 ui_candidate_window_resize (width, _candidate_land_height_max);
2129 evas_object_move (_close_btn, _close_btn_pos[2], _close_btn_pos[3]);
2130 evas_object_move (_candidate_area_2, 0, _candidate_land_height_min);
2131 evas_object_move (_scroller_bg, 0, _candidate_land_height_min);
2132 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2134 if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _ise_state == WINDOW_STATE_SHOW &&
2135 _ise_height > _candidate_port_height_max - _candidate_port_height_min)
2136 ui_candidate_window_resize (width, _candidate_port_height_min + _ise_height);
2138 ui_candidate_window_resize (width, _candidate_port_height_max);
2139 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
2140 evas_object_move (_candidate_area_2, 0, _candidate_port_height_min);
2141 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
2142 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2145 evas_object_hide (_aux_line);
2146 evas_object_move (_candidate_area_1, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
2147 if (_candidate_angle == 90 || _candidate_angle == 270) {
2148 ui_candidate_window_resize (width, _candidate_land_height_min);
2149 evas_object_move (_more_btn, _more_btn_pos[2], _more_btn_pos[3]);
2150 evas_object_resize (_candidate_bg, width, _candidate_land_height_min);
2152 ui_candidate_window_resize (width, _candidate_port_height_min);
2153 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
2154 evas_object_resize (_candidate_bg, width, _candidate_port_height_min);
2160 * @brief Rotate candidate window.
2162 * @param angle The angle of candidate window.
2164 static void ui_candidate_window_rotate (int angle)
2166 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2167 if (!_candidate_window)
2170 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
2172 if (angle == 90 || angle == 270) {
2173 _candidate_scroll_width = _candidate_scroll_width_max;
2174 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
2175 evas_object_resize (_aux_area, _aux_land_width, _aux_height);
2176 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_max, _item_min_height);
2177 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_min);
2178 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_min + 6);
2180 _candidate_scroll_width = _candidate_scroll_width_min;
2181 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
2182 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
2183 evas_object_resize (_candidate_area_1, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
2184 evas_object_resize (_candidate_area_2, _candidate_scroll_width, _candidate_scroll_height_max);
2185 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
2188 evas_object_hide (_candidate_area_2);
2189 _candidate_area_2_visible = false;
2190 ui_candidate_window_adjust ();
2191 if (_candidate_area_1_visible) {
2192 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2193 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
2194 ui_tts_focus_rect_hide ();
2200 * @brief This function is used to judge whether candidate window should be hidden.
2202 * @return true if candidate window should be hidden, otherwise return false.
2204 static bool ui_candidate_can_be_hide (void)
2206 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2208 if (_aux_area_visible || _candidate_area_1_visible || _candidate_area_2_visible)
2215 * @brief Delete check candidate window size timer.
2219 static void ui_candidate_delete_check_size_timer (void)
2221 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2223 if (_check_size_timer != NULL) {
2224 ecore_timer_del (_check_size_timer);
2225 _check_size_timer = NULL;
2230 * @brief Callback function for check candidate window size timer.
2232 * @param data Data to pass when it is called.
2234 * @return ECORE_CALLBACK_CANCEL
2236 static Eina_Bool ui_candidate_check_size_timeout (void *data)
2238 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2240 ui_candidate_delete_check_size_timer ();
2241 ui_candidate_window_resize (_candidate_width, _candidate_height);
2242 ui_settle_candidate_window ();
2243 return ECORE_CALLBACK_CANCEL;
2247 * @brief Delete longpress timer.
2251 static void ui_candidate_delete_longpress_timer (void)
2253 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2255 if (_longpress_timer != NULL) {
2256 ecore_timer_del (_longpress_timer);
2257 _longpress_timer = NULL;
2262 * @brief Callback function for candidate longpress timer.
2264 * @param data Data to pass when it is called.
2266 * @return ECORE_CALLBACK_CANCEL
2268 static Eina_Bool ui_candidate_longpress_timeout (void *data)
2270 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2272 int index = (int)GPOINTER_TO_INT (data);
2273 ui_candidate_delete_longpress_timer ();
2275 _info_manager->send_longpress_event (_click_object, index);
2276 return ECORE_CALLBACK_CANCEL;
2280 * @brief Delete destroy timer.
2284 static void ui_candidate_delete_destroy_timer (void)
2286 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2288 if (_destroy_timer != NULL) {
2289 ecore_timer_del (_destroy_timer);
2290 _destroy_timer = NULL;
2295 * @brief Callback function for destroy timer.
2297 * @param data Data to pass when it is called.
2299 * @return ECORE_CALLBACK_CANCEL
2301 static Eina_Bool ui_candidate_destroy_timeout (void *data)
2303 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2305 ui_candidate_delete_destroy_timer ();
2306 ui_destroy_candidate_window ();
2307 return ECORE_CALLBACK_CANCEL;
2309 #endif /* CANDIDATE */
2313 * @brief Callback function for off_prepare_done.
2315 * @param data Data to pass when it is called.
2317 * @return ECORE_CALLBACK_CANCEL
2319 static Eina_Bool off_prepare_done_timeout (void *data)
2321 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2323 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
2324 // WILL_HIDE_REQUEST_DONE Ack to WM
2325 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
2326 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
2327 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)\n",
2328 root_window, _control_window);
2329 _off_prepare_done_timer = NULL;
2331 return ECORE_CALLBACK_CANCEL;
2333 #endif /* HAVE_ECOREX */
2335 #if ISF_BUILD_CANDIDATE_UI
2337 * @brief Delete candidate hide timer.
2341 static void delete_candidate_hide_timer (void)
2343 LOGD ("deleting candidate_hide_timer\n");
2344 if (_candidate_hide_timer) {
2345 ecore_timer_del (_candidate_hide_timer);
2346 _candidate_hide_timer = NULL;
2350 static void candidate_window_hide (void)
2352 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "\n";
2354 delete_candidate_hide_timer ();
2355 _candidate_state = WINDOW_STATE_HIDE;
2357 LOGD ("evas_object_hide (_candidate_window, %p)\n", elm_win_xwindow_get (_candidate_window));
2359 if (_candidate_window) {
2360 /* There are cases that when there are rapid ISE_HIDE and ISE_SHOW requests,
2361 candidate window should be displayed but STATE_OFF for the first ISE_HIDE
2362 calls this function, so when the candidate window is shown by the following
2363 STATE_ON message, a blank area is displayed in candidate window -
2364 so we let the _candidate_area_1 as the default area that would be displayed */
2365 //evas_object_hide (_candidate_area_1);
2366 //evas_object_hide (_more_btn);
2367 _candidate_area_1_visible = false;
2369 evas_object_hide (_candidate_window);
2370 SCIM_DEBUG_MAIN (3) << " Hide candidate window\n";
2375 * @brief Callback function for candidate hide timer
2377 * @param data Data to pass when it is called.
2379 * @return ECORE_CALLBACK_CANCEL
2381 static Eina_Bool candidate_hide_timer (void *data)
2383 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2385 LOGD ("calling candidate_window_hide ()\n");
2386 candidate_window_hide ();
2388 return ECORE_CALLBACK_CANCEL;
2393 * @brief Delete candidate show handler.
2397 static void delete_candidate_show_handler (void)
2399 if (_candidate_show_handler) {
2400 ecore_event_handler_del (_candidate_show_handler);
2401 _candidate_show_handler = NULL;
2406 * @brief Callback function for window show completion event
2408 * @param data Data to pass when it is called.
2410 * @return ECORE_CALLBACK_CANCEL
2413 static Eina_Bool x_event_window_show_cb (void *data, int ev_type, void *event)
2415 delete_candidate_show_handler ();
2417 Ecore_X_Event_Window_Show *e = (Ecore_X_Event_Window_Show*)event;
2418 if (_candidate_state == WINDOW_STATE_WILL_SHOW) {
2419 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2420 LOGD ("Candidate window show callback\n");
2422 /* If our candidate window is in WILL_SHOW state and this show callback was called,
2423 now we are finally displayed on to the screen */
2424 _candidate_state = WINDOW_STATE_SHOW;
2426 /* Update the geometry information for auto scrolling */
2427 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2428 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2429 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2431 /* And the state event */
2432 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2434 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2435 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2436 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2437 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2442 if (e->win == elm_win_xwindow_get (_candidate_window)) {
2443 LOGD ("Candidate window show callback, but _candidate_state is %d\n", _candidate_state);
2447 return ECORE_CALLBACK_CANCEL;
2449 #endif /* HAVE_ECOREX */
2452 * @brief Show candidate window.
2454 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2456 static void ui_candidate_show (bool bSetVirtualKbd)
2458 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2460 delete_candidate_hide_timer ();
2462 if (!_candidate_window) return;
2463 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
2466 /* FIXME : SHOULD UNIFY THE METHOD FOR CHECKING THE HW KEYBOARD EXISTENCE */
2467 /* If the ISE is not visible currently, wait for the ISE to be opened and then show our candidate window */
2468 _candidate_show_requested = true;
2469 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) && (_ise_state != WINDOW_STATE_SHOW)) {
2470 LOGD ("setting _show_candidate_requested to TRUE\n");
2474 /* If the ISE angle is valid, respect the value to make sure
2475 the candidate window always have the same angle with ISE */
2476 if (_ise_angle != -1) {
2477 _candidate_angle = _ise_angle;
2479 ui_candidate_window_rotate (_candidate_angle);
2481 /* If the candidate window was about to hide, turn it back to SHOW state now */
2482 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
2483 _candidate_state = WINDOW_STATE_SHOW;
2486 /* Change to WILL_SHOW state only when we are not currently in SHOW state */
2487 if (_candidate_state != WINDOW_STATE_SHOW) {
2488 _candidate_state = WINDOW_STATE_WILL_SHOW;
2492 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2493 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
2494 // Unset conformant area
2495 Ecore_X_Window current_app_window = efl_get_app_window ();
2496 if (_app_window != current_app_window) {
2497 struct rectinfo info = {0, 0, 0, 0};
2498 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
2499 set_keyboard_geometry_atom_info (_app_window, info);
2500 LOGD ("Conformant reset for window %x\n", _app_window);
2501 _app_window = current_app_window;
2505 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2506 if (bSetVirtualKbd) {
2507 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2510 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
2513 ui_candidate_delete_check_size_timer ();
2514 _check_size_timer = ecore_timer_add (0.02, ui_candidate_check_size_timeout, NULL);
2516 SCIM_DEBUG_MAIN (3) << " Show candidate window\n";
2518 if (_ise_state == WINDOW_STATE_SHOW) {
2519 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
2520 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
2522 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
2523 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
2526 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2527 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2528 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2529 LOGD ("sending ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW\n");
2530 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
2534 if (_candidate_state != WINDOW_STATE_SHOW) {
2536 if (_candidate_show_handler) {
2537 LOGD ("Was still waiting for CANDIDATE_WINDOW_SHOW....\n");
2539 delete_candidate_show_handler ();
2540 LOGD ("Registering ECORE_X_EVENT_WINDOW_SHOW event, %d\n", _candidate_state);
2541 _candidate_show_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_SHOW, x_event_window_show_cb, NULL);
2545 LOGD ("The candidate window was already in SHOW state, update geometry information\n");
2546 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2547 _info_manager->update_input_panel_event (ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
2549 /* And the state event */
2550 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_SHOW);
2552 /* If we are in hardware keyboard mode, this candidate window is now considered to be a input panel */
2553 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2554 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2555 _info_manager->update_input_panel_event ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_SHOW);
2560 evas_object_show (_candidate_window);
2564 * @brief Hide candidate window.
2566 * @param bForce The flag to hide candidate window by force.
2567 * @param bSetVirtualKbd The flag for set_keyboard_geometry_atom_info () calling.
2569 static void ui_candidate_hide (bool bForce, bool bSetVirtualKbd, bool will_hide)
2571 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " bForce:" << bForce << " bSetVirtualKbd:" << bSetVirtualKbd << " will_hide:" << will_hide << "...\n";
2573 if (!_candidate_window)
2577 if (_candidate_area_2 && _candidate_area_2_visible) {
2578 evas_object_hide (_candidate_area_2);
2579 _candidate_area_2_visible = false;
2580 evas_object_hide (_scroller_bg);
2581 evas_object_hide (_close_btn);
2582 _info_manager->candidate_more_window_hide ();
2583 ui_candidate_window_adjust ();
2587 if (bForce || ui_candidate_can_be_hide ()) {
2589 LOGD ("candidate_state = WILL_HIDE\n");
2590 _candidate_state = WINDOW_STATE_WILL_HIDE;
2592 delete_candidate_hide_timer ();
2593 _candidate_hide_timer = ecore_timer_add (2.0, candidate_hide_timer, NULL);
2596 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
2597 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
2598 /* FIXME : should check if bSetVirtualKbd flag is really needed in this case */
2600 if (_ise_state == WINDOW_STATE_SHOW) {
2601 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2603 if (bSetVirtualKbd) {
2604 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
2608 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
2609 _info_manager->update_input_panel_event
2610 ((uint32)ECORE_IMF_INPUT_PANEL_STATE_EVENT, (uint32)ECORE_IMF_INPUT_PANEL_STATE_HIDE);
2614 /* Update the new keyboard geometry first, and then send the candidate hide event */
2615 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, (uint32)ECORE_IMF_CANDIDATE_PANEL_HIDE);
2618 /* If we are not in will_hide state, hide the candidate window immediately */
2619 candidate_window_hide ();
2621 if (_preedit_window)
2622 evas_object_hide (_preedit_window);
2628 * @brief Callback function for more button.
2630 * @param data Data to pass when it is called.
2631 * @param e The evas for current event.
2632 * @param button The evas object for current event.
2633 * @param event_info The information for current event.
2635 static void ui_candidate_window_more_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2637 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2639 _info_manager->candidate_more_window_show ();
2641 if (candidate_expanded == false) {
2642 candidate_expanded = true;
2643 int number = SCIM_LOOKUP_TABLE_MAX_PAGESIZE;
2644 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
2645 if (_candidate_0 [i] == NULL) {
2650 if (g_isf_candidate_table.get_current_page_size () != number)
2651 update_table (ISF_CANDIDATE_TABLE, g_isf_candidate_table);
2654 if (_candidate_angle == 180) {
2655 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2656 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2657 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)\n", ee, 0, 0, 0, 0);
2658 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2660 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2661 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2662 * for avoiding this situation.
2664 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2665 ecore_evas_move_resize (ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2666 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)\n",
2667 ee, 0, 0, _screen_height, ui_candidate_get_valid_height () + _ise_height);
2670 evas_object_show (_candidate_area_2);
2671 _candidate_area_2_visible = true;
2672 evas_object_show (_scroller_bg);
2673 evas_object_hide (_more_btn);
2674 evas_object_show (_close_btn);
2676 ui_candidate_window_adjust ();
2677 ui_settle_candidate_window ();
2682 * @brief Callback function for close button.
2684 * @param data Data to pass when it is called.
2685 * @param e The evas for current event.
2686 * @param button The evas object for current event.
2687 * @param event_info The information for current event.
2689 static void ui_candidate_window_close_button_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2691 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2693 if (_candidate_area_2 == NULL || !_candidate_area_2_visible)
2696 _info_manager->candidate_more_window_hide ();
2698 evas_object_hide (_candidate_area_2);
2699 _candidate_area_2_visible = false;
2700 evas_object_hide (_scroller_bg);
2701 evas_object_hide (_close_btn);
2703 candidate_expanded = false;
2704 evas_object_show (_candidate_area_1);
2705 _candidate_area_1_visible = true;
2706 evas_object_show (_more_btn);
2708 elm_scroller_region_show (_candidate_area_2, 0, 0, _candidate_scroll_width, 100);
2709 if (_candidate_angle == 180) {
2710 Ecore_Evas *ee= ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2711 ecore_evas_move_resize (ee, 0, 0, 0, 0);
2712 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)\n", ee, 0, 0, 0, 0);
2713 } else if (_candidate_mode == FIXED_CANDIDATE_WINDOW && _candidate_angle == 270) {
2715 * when screen rotate 270 degrees, candidate have to move then resize for expanding more
2716 * candidates, but it will flash or locate in a wrong position, this code just a workaround
2717 * for avoiding this situation.
2719 Ecore_Evas *ee = ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window));
2720 ecore_evas_move_resize (ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2721 LOGD ("ecore_evas_move_resize (%p, %d, %d, %d, %d)\n",
2722 ee, _ise_height, 0, _screen_height, ui_candidate_get_valid_height ());
2725 ui_candidate_window_adjust ();
2726 ui_settle_candidate_window ();
2731 * @brief Callback function for mouse button press.
2733 * @param data Data to pass when it is called.
2734 * @param e The evas for current event.
2735 * @param button The evas object for current event.
2736 * @param event_info The information for current event.
2738 static void ui_mouse_button_pressed_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2740 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2742 _click_object = GPOINTER_TO_INT (data) & 0xFF;
2745 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
2748 _click_down_pos [0] = ev->canvas.x;
2749 _click_down_pos [1] = ev->canvas.y;
2751 if (_click_object == ISF_EFL_CANDIDATE_0 || _click_object == ISF_EFL_CANDIDATE_ITEMS) {
2752 int index = (int)GPOINTER_TO_INT (data) >> 8;
2754 #ifdef HAVE_FEEDBACK
2755 if (feedback_initialized) {
2756 int feedback_result = 0;
2757 bool sound_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_SOUND_FEEDBACK, false);
2759 if (sound_feedback) {
2760 feedback_result = feedback_play_type (FEEDBACK_TYPE_SOUND, FEEDBACK_PATTERN_SIP);
2762 if (FEEDBACK_ERROR_NONE == feedback_result)
2763 LOGD ("Sound play successful\n");
2765 LOGW ("Cannot play feedback sound : %d\n", feedback_result);
2768 bool vibrate_feedback = _config->read (SCIM_GLOBAL_CONFIG_PANEL_VIBRATION_FEEDBACK, false);
2770 if (vibrate_feedback) {
2771 feedback_result = feedback_play_type (FEEDBACK_TYPE_VIBRATION, FEEDBACK_PATTERN_SIP);
2773 if (FEEDBACK_ERROR_NONE == feedback_result)
2774 LOGD ("Vibration play successful\n");
2776 LOGW ("Cannot play feedback vibration : %d\n", feedback_result);
2781 ui_candidate_delete_longpress_timer ();
2782 _longpress_timer = ecore_timer_add (1.0, ui_candidate_longpress_timeout, (void *)index);
2787 * @brief Callback function for mouse button release.
2789 * @param data Data to pass when it is called.
2790 * @param e The evas for current event.
2791 * @param button The evas object for current event.
2792 * @param event_info The information for current event.
2794 static void ui_mouse_button_released_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2796 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " index:" << GPOINTER_TO_INT (data) << "...\n";
2798 ui_candidate_delete_longpress_timer ();
2800 int index = GPOINTER_TO_INT (data);
2801 if (_click_object == ISF_EFL_AUX && _is_click) {
2803 const char *buf = edje_object_part_state_get (button, "aux", &ret);
2804 if (strcmp ("selected", buf)) {
2805 for (unsigned int i = 0; i < _aux_items.size (); i++) {
2806 buf = edje_object_part_state_get (_aux_items [i], "aux", &ret);
2807 if (!strcmp ("selected", buf))
2808 edje_object_signal_emit (_aux_items [i], "aux,state,unselected", "aux");
2810 edje_object_signal_emit (button, "aux,state,selected", "aux");
2811 _info_manager->select_aux (index);
2813 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
2814 edje_object_color_class_get (_aux_items [index], "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3);
2815 // Normal item is clicked
2816 if (!(r == 62 && g == 207 && b == 255)) {
2817 for (unsigned int i = 0; i < _aux_items.size (); i++) {
2818 edje_object_color_class_set (_aux_items [i], "text_color", 249, 249, 249, 255, r2, g2, b2, a2, r3, g3, b3, a3);
2820 edje_object_color_class_set (_aux_items [index], "text_color", 62, 207, 255, 255, r2, g2, b2, a2, r3, g3, b3, a3);
2821 _info_manager->select_aux (index);
2823 } else if (_click_object == ISF_EFL_CANDIDATE_0 && _is_click) {
2824 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
2825 _info_manager->select_candidate (index);
2826 } else if (_click_object == ISF_EFL_CANDIDATE_ITEMS && _is_click) {
2827 ui_candidate_window_close_button_cb (NULL, NULL, _close_btn, NULL);
2828 _info_manager->select_candidate (index);
2833 * @brief Callback function for mouse move.
2835 * @param data Data to pass when it is called.
2836 * @param e The evas for current event.
2837 * @param button The evas object for current event.
2838 * @param event_info The information for current event.
2840 static void ui_mouse_moved_cb (void *data, Evas *e, Evas_Object *button, void *event_info)
2842 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2844 Evas_Event_Mouse_Down *ev = (Evas_Event_Mouse_Down *)event_info;
2847 _click_up_pos [0] = ev->canvas.x;
2848 _click_up_pos [1] = ev->canvas.y;
2850 if (abs (_click_up_pos [0] - _click_down_pos [0]) >= (int)(15 * _height_rate) ||
2851 abs (_click_up_pos [1] - _click_down_pos [1]) >= (int)(15 * _height_rate)) {
2853 ui_candidate_delete_longpress_timer ();
2859 * @brief Open TTS device.
2861 * @return false if open is failed, otherwise return true.
2863 static bool ui_open_tts (void)
2865 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2867 int r = tts_create (&_tts);
2868 if (TTS_ERROR_NONE != r) {
2869 LOGW ("tts_create FAILED : result (%d)\n", r);
2874 r = tts_set_mode (_tts, TTS_MODE_SCREEN_READER);
2875 if (TTS_ERROR_NONE != r) {
2876 LOGW ("tts_set_mode FAILED : result (%d)\n", r);
2879 tts_state_e current_state;
2880 r = tts_get_state (_tts, ¤t_state);
2881 if (TTS_ERROR_NONE != r) {
2882 LOGW ("tts_get_state FAILED : result (%d)\n", r);
2885 if (TTS_STATE_CREATED == current_state) {
2886 r = tts_prepare (_tts);
2887 if (TTS_ERROR_NONE != r) {
2888 LOGW ("tts_prepare FAILED : ret (%d)\n", r);
2895 * @brief Close TTS device.
2897 static void ui_close_tts (void)
2899 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2902 int r = tts_unprepare (_tts);
2903 if (TTS_ERROR_NONE != r) {
2904 LOGW ("tts_unprepare FAILED : result (%d)\n", r);
2907 r = tts_destroy (_tts);
2908 if (TTS_ERROR_NONE != r) {
2909 LOGW ("tts_destroy FAILED : result (%d)\n", r);
2915 * @brief Play string by TTS.
2917 * @param str The string for playing.
2919 static void ui_play_tts (const char* str)
2921 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " str=" << str << "\n";
2926 if (!ui_open_tts ())
2932 tts_state_e current_state;
2934 r = tts_get_state (_tts, ¤t_state);
2935 if (TTS_ERROR_NONE != r) {
2936 LOGW ("Fail to get state from TTS : ret (%d)\n", r);
2939 if (TTS_STATE_PLAYING == current_state) {
2940 r = tts_stop (_tts);
2941 if (TTS_ERROR_NONE != r) {
2942 LOGW ("Fail to stop TTS : ret (%d)\n", r);
2946 /* Get ISE language */
2947 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
2948 String language = String ("en_US");
2949 if (default_uuid.length () > 0) {
2950 language = _ime_info[get_ise_index (default_uuid)].languages;
2951 if (language.length () > 0) {
2952 std::vector<String> ise_langs;
2953 scim_split_string_list (ise_langs, language);
2954 language = ise_langs[0];
2957 LOGD ("TTS language:%s, str:%s\n", language.c_str (), str);
2959 r = tts_add_text (_tts, str, language.c_str (), TTS_VOICE_TYPE_AUTO, TTS_SPEED_AUTO, &utt_id);
2960 if (TTS_ERROR_NONE == r) {
2961 r = tts_play (_tts);
2962 if (TTS_ERROR_NONE != r) {
2963 LOGW ("Fail to play TTS : ret (%d)\n", r);
2967 #endif /* HAVE_TTS */
2970 * @brief Show rect for candidate focus object when screen reader is enabled.
2972 * @param x Rect X position.
2973 * @param y Rect Y position.
2974 * @param w Rect width.
2975 * @param h Rect height.
2977 static void ui_tts_focus_rect_show (int x, int y, int w, int h)
2979 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
2980 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
2983 if (_tts_focus_rect == NULL) {
2984 _tts_focus_rect = evas_object_rectangle_add (evas_object_evas_get ((Evas_Object*)_candidate_window));
2985 evas_object_color_set (_tts_focus_rect, 0, 0, 0, 0);
2986 elm_access_highlight_set (elm_access_object_register (_tts_focus_rect, (Evas_Object*)_candidate_window));
2988 evas_object_move (_tts_focus_rect, x, y);
2989 evas_object_resize (_tts_focus_rect, w, h);
2990 evas_object_raise (_tts_focus_rect);
2991 evas_object_show (_tts_focus_rect);
2995 * @brief Hide rect for candidate focus object when screen reader is enabled.
2997 static void ui_tts_focus_rect_hide (void)
2999 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3001 if (_tts_focus_rect) {
3002 //evas_object_hide (_tts_focus_rect);
3003 evas_object_move (_tts_focus_rect, -1000, -1000);
3008 * @brief Callback function for candidate scroller stop event.
3010 * @param data Data to pass when it is called.
3011 * @param obj The evas object for current event.
3012 * @param event_info The information for current event.
3014 static void ui_candidate_scroller_stop_cb (void *data, Evas_Object *obj, void *event_info)
3016 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3017 if (!_wait_stop_event)
3020 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
3021 if (_candidate_0 [_candidate_tts_focus_index]) {
3023 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
3024 ui_tts_focus_rect_show (x, y, w, h);
3027 _wait_stop_event = false;
3032 * @brief Mouse over (find focus object and play text by TTS) when screen reader is enabled.
3034 * @param mouse_x Mouse X position.
3035 * @param mouse_y Mouse Y position.
3037 static void ui_mouse_over (int mouse_x, int mouse_y)
3039 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3040 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW)
3043 int x, y, width, height;
3044 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3045 if (_candidate_0 [i]) {
3046 evas_object_geometry_get (_candidate_0 [i], &x, &y, &width, &height);
3047 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3048 /* FIXME: Should consider emoji case */
3049 String mbs = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (i));
3050 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " play candidate string: " << mbs << "\n";
3052 ui_play_tts (mbs.c_str ());
3054 _candidate_tts_focus_index = i;
3055 ui_tts_focus_rect_show (x, y, width, height);
3061 String strTts = String ("");
3062 if (_candidate_area_2_visible) {
3063 evas_object_geometry_get (_close_btn, &x, &y, &width, &height);
3064 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3065 strTts = String (_("close button"));
3066 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
3067 ui_tts_focus_rect_show (x, y, width, height);
3070 evas_object_geometry_get (_more_btn, &x, &y, &width, &height);
3071 if (mouse_x >= x && mouse_x <= x + width && mouse_y >= y && mouse_y <= y + height) {
3072 strTts = String (_("more button"));
3073 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
3074 ui_tts_focus_rect_show (x, y, width, height);
3078 if (strTts.length () > 0)
3079 ui_play_tts (strTts.c_str ());
3084 * @brief Mouse click (find focus object and do click event) when screen reader is enabled.
3086 * @param focus_index focused candidate index.
3088 static void ui_mouse_click (int focus_index)
3090 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3091 if (_candidate_window == NULL || _candidate_state != WINDOW_STATE_SHOW || focus_index == INVALID_TTS_FOCUS_INDEX)
3094 if (focus_index >= 0 && focus_index < g_isf_candidate_table.get_current_page_size ()) {
3095 if (_candidate_0 [focus_index]) {
3096 int x, y, width, height;
3097 evas_object_geometry_get (_candidate_0 [focus_index], &x, &y, &width, &height);
3098 Evas_Event_Mouse_Down event_info;
3099 event_info.canvas.x = x + width / 2;
3100 event_info.canvas.y = y + height / 2;
3101 ui_mouse_button_pressed_cb (GINT_TO_POINTER ((focus_index << 8) + ISF_EFL_CANDIDATE_0), NULL, NULL, &event_info);
3102 ui_mouse_button_released_cb (GINT_TO_POINTER (focus_index), NULL, NULL, &event_info);
3104 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
3105 ui_tts_focus_rect_hide ();
3109 if (_candidate_area_2_visible) {
3110 if (focus_index == CLOSE_BUTTON_INDEX) {
3111 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
3112 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
3115 if (focus_index == MORE_BUTTON_INDEX) {
3116 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
3117 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
3121 #endif /* HAVE_ECOREX */
3124 * @brief Create preedit window.
3126 static void ui_create_preedit_window (void)
3128 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3130 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3133 _preedit_width = 100;
3134 _preedit_height = _preedit_height * _height_rate;
3135 if (_preedit_window == NULL) {
3136 _preedit_window = efl_create_window ("ISF Popup", "Preedit Window");
3137 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
3138 int rots [4] = {0, 90, 180, 270};
3139 elm_win_wm_rotation_available_rotations_set (_preedit_window, rots, 4);
3140 int preedit_font_size = (int)(32 * _width_rate);
3142 _preedit_text = edje_object_add (evas_object_evas_get (_preedit_window));
3143 edje_object_file_set (_preedit_text, _candidate_edje_file.c_str (), "preedit_text");
3144 evas_object_size_hint_fill_set (_preedit_text, EVAS_HINT_FILL, EVAS_HINT_FILL);
3145 evas_object_size_hint_weight_set (_preedit_text, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3146 elm_win_resize_object_add (_preedit_window, _preedit_text);
3147 evas_object_show (_preedit_text);
3149 _tmp_preedit_text = evas_object_text_add (evas_object_evas_get (_preedit_window));
3150 evas_object_text_font_set (_tmp_preedit_text, _candidate_font_name.c_str (), preedit_font_size);
3155 * @brief Create native style candidate window.
3157 static void ui_create_native_candidate_window (void)
3159 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3160 _more_btn_width = 80 * (_width_rate > 1 ? 1 : _width_rate);
3161 _more_btn_height = 64 * _height_rate;
3163 _candidate_port_width = _screen_width;
3164 _candidate_port_height_min = 84 * _height_rate * _candidate_port_line;
3165 _candidate_port_height_min_2 = 84 * _height_rate + _candidate_port_height_min;
3166 _candidate_port_height_max = 426 * _height_rate + _candidate_port_height_min;
3167 _candidate_port_height_max_2 = 84 * _height_rate + _candidate_port_height_max;
3168 _candidate_land_width = _screen_height;
3169 _candidate_land_height_min = 84 * _width_rate;
3170 _candidate_land_height_min_2 = 168 * _width_rate;
3171 _candidate_land_height_max = 342 * _width_rate;
3172 _candidate_land_height_max_2 = 426 * _width_rate;
3174 _candidate_scroll_0_width_min= _screen_width;
3175 _candidate_scroll_0_width_max= _screen_height;
3176 _candidate_scroll_width_min = _screen_width;
3177 _candidate_scroll_width_max = _screen_height;
3178 _candidate_scroll_height_min = 252 * _width_rate;
3179 _candidate_scroll_height_max = 420 * _height_rate;
3181 _candidate_area_1_pos [0] = 0 * _width_rate;
3182 _candidate_area_1_pos [1] = 2 * _height_rate;
3183 _more_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3184 _more_btn_pos [1] = 12 * _height_rate;
3185 _more_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3186 _more_btn_pos [3] = 12 * _width_rate;
3187 _close_btn_pos [0] = _candidate_port_width - _more_btn_width - _h_padding;
3188 _close_btn_pos [1] = 12 * _height_rate;
3189 _close_btn_pos [2] = _candidate_land_width - _more_btn_width - _h_padding;
3190 _close_btn_pos [3] = 12 * _width_rate;
3192 _aux_height = 84 * _height_rate - 2;
3193 _aux_port_width = _screen_width;
3194 _aux_land_width = _screen_height;
3196 _item_min_height = 84 * _height_rate - 2;
3198 /* Create candidate window */
3199 if (_candidate_window == NULL) {
3200 _candidate_window = efl_create_window ("ISF Popup", "Prediction Window");
3201 int rots [4] = {0, 90, 180, 270};
3202 elm_win_wm_rotation_available_rotations_set (_candidate_window, rots, 4);
3203 if (_candidate_angle == 90 || _candidate_angle == 270) {
3204 _candidate_width = _candidate_land_width;
3205 _candidate_height = _candidate_land_height_min;
3207 _candidate_width = _candidate_port_width;
3208 _candidate_height = _candidate_port_height_min;
3212 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3213 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3214 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3215 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3216 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3217 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3218 ecore_x_e_window_rotation_geometry_set (elm_win_xwindow_get (_candidate_window),
3219 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3222 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3223 0, 0, 0, _candidate_port_width, _candidate_port_height_min);
3224 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3225 90, 0, 0, _candidate_land_height_min, _candidate_land_width);
3226 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3227 180, 0, 0, _candidate_port_width, _candidate_port_height_min);
3228 ecore_wl_window_rotation_geometry_set (elm_win_wl_window_get (_candidate_window),
3229 270, 0, 0, _candidate_land_height_min, _candidate_land_width);
3231 /* Add dim background */
3232 Evas_Object *dim_bg = elm_bg_add (_candidate_window);
3233 evas_object_color_set (dim_bg, 0, 0, 0, 153);
3234 elm_win_resize_object_add (_candidate_window, dim_bg);
3235 evas_object_show (dim_bg);
3237 /* Add candidate background */
3238 _candidate_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3239 edje_object_file_set (_candidate_bg, _candidate_edje_file.c_str (), "candidate_bg");
3240 evas_object_size_hint_weight_set (_candidate_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3241 evas_object_resize (_candidate_bg, _candidate_port_width, _candidate_port_height_min);
3242 evas_object_move (_candidate_bg, 0, 0);
3243 evas_object_show (_candidate_bg);
3245 /* Create _candidate_0 scroller */
3246 _candidate_0_scroll = elm_scroller_add (_candidate_window);
3247 elm_scroller_bounce_set (_candidate_0_scroll, EINA_TRUE, EINA_FALSE);
3248 elm_scroller_policy_set (_candidate_0_scroll, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3249 evas_object_resize (_candidate_0_scroll, _candidate_scroll_0_width_min, (_item_min_height+2)*_candidate_port_line-2);
3250 evas_object_move (_candidate_0_scroll, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3252 /* Create candidate table */
3253 _candidate_0_table = elm_table_add (_candidate_window);
3254 evas_object_size_hint_weight_set (_candidate_0_table, 0.0, 0.0);
3255 evas_object_size_hint_align_set (_candidate_0_table, 0.0, 0.0);
3256 elm_table_padding_set (_candidate_0_table, 0, 0);
3257 elm_object_content_set (_candidate_0_scroll, _candidate_0_table);
3258 evas_object_show (_candidate_0_table);
3259 _candidate_area_1 = _candidate_0_scroll;
3261 /* Create more button */
3262 _more_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3263 if (_ise_width == 0 && _ise_height == 0)
3264 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "close_button");
3266 edje_object_file_set (_more_btn, _candidate_edje_file.c_str (), "more_button");
3267 evas_object_move (_more_btn, _more_btn_pos[0], _more_btn_pos[1]);
3268 evas_object_resize (_more_btn, _more_btn_width, _more_btn_height);
3269 evas_object_event_callback_add (_more_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_more_button_cb, NULL);
3271 /* Add scroller background */
3272 _candidate_scroll_width = _candidate_scroll_width_min;
3273 _scroller_bg = edje_object_add (evas_object_evas_get (_candidate_window));
3274 edje_object_file_set (_scroller_bg, _candidate_edje_file.c_str (), "scroller_bg");
3275 evas_object_size_hint_weight_set (_scroller_bg, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
3276 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3277 evas_object_move (_scroller_bg, 0, _candidate_port_height_min);
3279 /* Create vertical scroller */
3280 _candidate_scroll = elm_scroller_add (_candidate_window);
3281 elm_scroller_bounce_set (_candidate_scroll, 0, 1);
3282 elm_scroller_policy_set (_candidate_scroll, ELM_SCROLLER_POLICY_OFF, ELM_SCROLLER_POLICY_AUTO);
3283 evas_object_resize (_candidate_scroll, _candidate_scroll_width, _candidate_scroll_height_max);
3284 evas_object_resize (_scroller_bg, _candidate_scroll_width, _candidate_scroll_height_max + 6);
3285 elm_scroller_page_size_set (_candidate_scroll, 0, _item_min_height+_v_padding);
3286 evas_object_move (_candidate_scroll, 0, _candidate_port_height_min);
3288 /* Create candidate table */
3289 _candidate_table = elm_table_add (_candidate_window);
3290 evas_object_size_hint_weight_set (_candidate_table, 0.0, 0.0);
3291 evas_object_size_hint_align_set (_candidate_table, 0.0, 0.0);
3292 elm_table_padding_set (_candidate_table, 0, 0);
3293 elm_object_content_set (_candidate_scroll, _candidate_table);
3294 evas_object_show (_candidate_table);
3295 _candidate_area_2 = _candidate_scroll;
3296 evas_object_smart_callback_add (_candidate_scroll, "scroll,anim,stop", ui_candidate_scroller_stop_cb, NULL);
3298 /* Create close button */
3299 _close_btn = edje_object_add (evas_object_evas_get (_candidate_window));
3300 if (_ise_width == 0 && _ise_height == 0)
3301 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "more_button");
3303 edje_object_file_set (_close_btn, _candidate_edje_file.c_str (), "close_button");
3304 evas_object_move (_close_btn, _close_btn_pos[0], _close_btn_pos[1]);
3305 evas_object_resize (_close_btn, _more_btn_width, _more_btn_height);
3306 evas_object_event_callback_add (_close_btn, EVAS_CALLBACK_MOUSE_UP, ui_candidate_window_close_button_cb, NULL);
3308 _tmp_candidate_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3309 evas_object_text_font_set (_tmp_candidate_text, _candidate_font_name.c_str (), _candidate_font_size);
3312 _aux_area = elm_scroller_add (_candidate_window);
3313 elm_scroller_bounce_set (_aux_area, 1, 0);
3314 elm_scroller_policy_set (_aux_area, ELM_SCROLLER_POLICY_AUTO, ELM_SCROLLER_POLICY_OFF);
3315 evas_object_resize (_aux_area, _aux_port_width, _aux_height);
3316 evas_object_move (_aux_area, _candidate_area_1_pos[0], _candidate_area_1_pos[1]);
3318 _aux_table = elm_table_add (_candidate_window);
3319 elm_object_content_set (_aux_area, _aux_table);
3320 elm_table_padding_set (_aux_table, 0, 0);
3321 evas_object_size_hint_weight_set (_aux_table, 0.0, 0.0);
3322 evas_object_size_hint_align_set (_aux_table, 0.0, 0.0);
3323 evas_object_show (_aux_table);
3325 _aux_line = edje_object_add (evas_object_evas_get (_candidate_window));
3326 edje_object_file_set (_aux_line, _candidate_edje_file.c_str (), "popup_line");
3327 evas_object_resize (_aux_line, _candidate_port_width, 2);
3328 evas_object_move (_aux_line, 0, _aux_height + 2);
3330 _tmp_aux_text = evas_object_text_add (evas_object_evas_get (_candidate_window));
3331 evas_object_text_font_set (_tmp_aux_text, _candidate_font_name.c_str (), _aux_font_size);
3333 evas_object_hide (_candidate_window);
3340 * @brief Create candidate window.
3344 static void ui_create_candidate_window (void)
3346 check_time ("\nEnter ui_create_candidate_window");
3347 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3348 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
3353 _candidate_angle = 0;
3355 ui_create_native_candidate_window ();
3358 unsigned int set = 1;
3360 ecore_x_window_prop_card32_set (elm_win_xwindow_get (_candidate_window),
3361 ECORE_X_ATOM_E_WINDOW_ROTATION_SUPPORTED,
3364 int angle = efl_get_app_window_angle ();
3365 if (_candidate_angle != angle) {
3366 _candidate_angle = angle;
3367 ui_candidate_window_rotate (angle);
3369 ui_settle_candidate_window ();
3372 candidate_expanded = false;
3374 check_time ("Exit ui_create_candidate_window");
3378 * @brief Destroy candidate window.
3382 static void ui_destroy_candidate_window (void)
3384 check_time ("Enter ui_destroy_candidate_window");
3385 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3387 /* Delete candidate items, popup lines and seperator items */
3388 for (int i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
3389 if (_candidate_0 [i]) {
3390 evas_object_del (_candidate_0 [i]);
3391 _candidate_0 [i] = NULL;
3393 if (_seperate_0 [i]) {
3394 evas_object_del (_seperate_0 [i]);
3395 _seperate_0 [i] = NULL;
3397 if (_seperate_items [i]) {
3398 evas_object_del (_seperate_items [i]);
3399 _seperate_items [i] = NULL;
3402 evas_object_del (_line_0 [i]);
3405 if (_line_items [i]) {
3406 evas_object_del (_line_items [i]);
3407 _line_items [i] = NULL;
3411 _aux_items.clear ();
3412 _aux_seperates.clear ();
3413 /* Delete candidate window */
3414 if (_candidate_window) {
3415 LOGD ("calling ui_candidate_hide (true)\n");
3416 ui_candidate_hide (true);
3418 evas_object_del (_candidate_window);
3419 _candidate_window = NULL;
3421 _candidate_area_1 = NULL;
3422 _candidate_area_2 = NULL;
3425 if (_tts_focus_rect) {
3426 evas_object_del (_tts_focus_rect);
3427 _tts_focus_rect = NULL;
3430 if (_candidate_bg) {
3431 evas_object_del (_candidate_bg);
3432 _candidate_bg = NULL;
3436 evas_object_del (_more_btn);
3441 evas_object_del (_scroller_bg);
3442 _scroller_bg = NULL;
3446 evas_object_del (_close_btn);
3451 evas_object_del (_aux_line);
3455 if (_tmp_candidate_text) {
3456 evas_object_del (_tmp_candidate_text);
3457 _tmp_candidate_text = NULL;
3460 if (_tmp_preedit_text) {
3461 evas_object_del (_tmp_preedit_text);
3462 _tmp_preedit_text = NULL;
3465 if (_tmp_aux_text) {
3466 evas_object_del (_tmp_aux_text);
3467 _tmp_aux_text = NULL;
3470 if (_preedit_text) {
3471 evas_object_del (_preedit_text);
3472 _preedit_text = NULL;
3475 if (_preedit_window) {
3476 evas_object_hide (_preedit_window);
3477 evas_object_del (_preedit_window);
3478 _preedit_window = NULL;
3482 check_time ("Exit ui_destroy_candidate_window");
3486 * @brief Settle candidate window position.
3488 static void ui_settle_candidate_window (void)
3490 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3492 if (!_candidate_window)
3495 /* If both ISE and candidate window are going to be hidden,
3496 let's just not move our candidate window */
3497 if (_ise_state == WINDOW_STATE_WILL_HIDE && _candidate_state == WINDOW_STATE_WILL_HIDE)
3501 int x, y, width, height;
3502 int ise_width = 0, ise_height = 0;
3503 bool get_geometry_result = false;
3505 /* Get candidate window position */
3506 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
3510 int pos_x = 0, pos_y = 0;
3511 if (_candidate_angle == 90 || _candidate_angle == 270)
3512 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_height, &ise_width);
3514 get_geometry_result = ecore_x_e_window_rotation_geometry_get (_ise_window, _candidate_angle, &pos_x, &pos_y, &ise_width, &ise_height);
3519 ise_width = _ise_width;
3520 ise_height = _ise_height;
3521 get_geometry_result = true;
3523 if ((_ise_state != WINDOW_STATE_SHOW && _ise_state != WINDOW_STATE_WILL_HIDE) ||
3524 (get_geometry_result == false) || (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
3529 int height2 = ui_candidate_get_valid_height ();
3531 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
3532 if (_candidate_angle == 90) {
3533 spot_x = _screen_width - ise_height - height2;
3535 } else if (_candidate_angle == 270) {
3536 spot_x = ise_height - (_candidate_height - height2);
3538 } else if (_candidate_angle == 180) {
3540 spot_y = ise_height - (_candidate_height - height2);
3543 spot_y = _screen_height - ise_height - height2;
3546 spot_x = _spot_location_x;
3547 spot_y = _spot_location_y;
3549 rectinfo ise_rect = {0, 0, (uint32)ise_width, (uint32)ise_height};
3550 if (_candidate_angle == 90 || _candidate_angle == 270) {
3551 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32)_screen_width)
3552 ise_rect.height = ISE_DEFAULT_HEIGHT_LANDSCAPE * _width_rate;
3554 if (ise_rect.height <= (uint32)0 || ise_rect.height >= (uint32) _screen_height)
3555 ise_rect.height = ISE_DEFAULT_HEIGHT_PORTRAIT * _height_rate;
3558 int nOffset = _candidate_port_height_min / 3;
3559 if (_candidate_angle == 270) {
3560 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3561 spot_x = _screen_width - _spot_location_top_y - (_candidate_height - height2);
3563 spot_x = _screen_width - _spot_location_y - _candidate_height;
3565 } else if (_candidate_angle == 90) {
3566 if (ise_rect.height > 0 && spot_y + height2 > _screen_width - (int)ise_rect.height + nOffset) {
3567 spot_x = _spot_location_top_y - height2;
3571 } else if (_candidate_angle == 180) {
3572 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3573 spot_y = _screen_height - _spot_location_top_y - (_candidate_height - height2);
3575 spot_y = _screen_height - _spot_location_y - _candidate_height;
3578 if (ise_rect.height > 0 && spot_y + height2 > _screen_height - (int)ise_rect.height + nOffset) {
3579 spot_y = _spot_location_top_y - height2;
3584 if (_candidate_angle == 90) {
3585 spot_y = (_screen_height - _candidate_width) / 2;
3586 spot_x = spot_x < _indicator_height ? _indicator_height : spot_x;
3587 if (spot_x > _screen_width - _candidate_height)
3588 spot_x = _screen_width - _candidate_height;
3589 } else if (_candidate_angle == 270) {
3590 spot_y = (_screen_height - _candidate_width) / 2;
3591 spot_x = spot_x < 0 ? 0 : spot_x;
3592 if (spot_x > _screen_width - (_indicator_height+_candidate_height))
3593 spot_x = _screen_width - (_indicator_height+_candidate_height);
3594 } else if (_candidate_angle == 180) {
3595 spot_x = (_screen_width - _candidate_width) / 2;
3596 spot_y = spot_y < 0 ? 0 : spot_y;
3597 if (spot_y > _screen_height - (_indicator_height+_candidate_height))
3598 spot_y = _screen_height - (_indicator_height+_candidate_height);
3600 spot_x = (_screen_width - _candidate_width) / 2;
3601 spot_y = spot_y < _indicator_height ? _indicator_height : spot_y;
3602 if (spot_y > _screen_height - _candidate_height)
3603 spot_y = _screen_height - _candidate_height;
3606 if (spot_x != x || spot_y != y) {
3607 _candidate_x = spot_x;
3608 _candidate_y = spot_y;
3609 evas_object_move (_candidate_window, spot_x, spot_y);
3610 LOGD ("Moving candidate window to : %d %d\n", spot_x, spot_y);
3611 if (_preedit_window) {
3612 if (_candidate_angle == 90) {
3613 spot_x -= _preedit_height;
3614 spot_y = _screen_height - _preedit_width;
3615 } else if (_candidate_angle == 270) {
3617 } else if (_candidate_angle == 180) {
3618 spot_x = _screen_width - _preedit_width;
3621 spot_y -= _preedit_height;
3623 evas_object_move (_preedit_window, spot_x, spot_y);
3625 if (_candidate_state == WINDOW_STATE_SHOW) {
3626 _info_manager->update_candidate_panel_event ((uint32)ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT, 0);
3630 #endif /* CANDIDATE */
3633 * @brief Set soft candidate geometry.
3635 * @param x The x position in screen.
3636 * @param y The y position in screen.
3637 * @param width The candidate window width.
3638 * @param height The candidate window height.
3640 static void set_soft_candidate_geometry (int x, int y, int width, int height)
3642 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
3644 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);
3646 if ((_candidate_mode != SOFT_CANDIDATE_WINDOW) || (_info_manager->get_current_toolbar_mode () != TOOLBAR_KEYBOARD_MODE))
3649 _soft_candidate_width = width;
3650 _soft_candidate_height = height;
3652 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry());
3654 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
3657 #if ISF_BUILD_CANDIDATE_UI
3658 //////////////////////////////////////////////////////////////////////
3659 // End of Candidate Functions
3660 //////////////////////////////////////////////////////////////////////
3663 * @brief Set transient for app window.
3665 * @param window The Ecore_X_Window handler of app window.
3667 static void efl_set_transient_for_app_window (Ecore_X_Window window)
3669 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3671 /* Set a transient window for window stack */
3672 Ecore_X_Window xAppWindow = efl_get_app_window ();
3673 ecore_x_icccm_transient_for_set (window, xAppWindow);
3675 LOGD ("win : %x, forwin : %x\n", window, xAppWindow);
3678 static int efl_get_window_rotate_angle (Ecore_X_Window win)
3680 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3685 unsigned char *prop_data = NULL;
3687 ret = ecore_x_window_prop_property_get (win,
3688 ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE, ECORE_X_ATOM_CARDINAL, 32, &prop_data, &count);
3689 if (ret && prop_data) {
3690 memcpy (&angle, prop_data, sizeof (int));
3691 LOGD ("WINDOW angle of %p is %d\n", win, angle);
3693 std::cerr << "ecore_x_window_prop_property_get () is failed!!!\n";
3694 LOGW ("WINDOW angle of %p FAILED!\n", win);
3701 #endif /* HAVE_ECOREX */
3704 * @brief Get angle for app window.
3706 * @param win_obj The Evas_Object handler of application window.
3708 * @return The angle of app window.
3710 static int efl_get_app_window_angle ()
3712 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3714 return efl_get_window_rotate_angle (efl_get_app_window ());
3720 #endif /* CANDIDATE */
3723 * @brief Get angle for ise window.
3725 * @param win_obj The Evas_Object handler of ise window.
3727 * @return The angle of ise window.
3729 static int efl_get_ise_window_angle ()
3731 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3733 return efl_get_window_rotate_angle (_ise_window);
3740 #if ISF_BUILD_CANDIDATE_UI
3743 * @brief Get angle of quickpanel window.
3745 * @return The angle of quickpanel window.
3747 static int efl_get_quickpanel_window_angle ()
3749 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3750 return efl_get_window_rotate_angle (efl_get_quickpanel_window ());
3755 * @brief Set showing effect for application window.
3757 * @param win The Evas_Object handler of application window.
3758 * @param strEffect The pointer of effect string.
3760 static void efl_set_showing_effect_for_app_window (Evas_Object *win, const char* strEffect)
3762 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3764 ecore_x_icccm_name_class_set (elm_win_xwindow_get (static_cast<Evas_Object*>(win)), strEffect, "ISF");
3769 * @brief Create elementary window.
3771 * @param strWinName The window name.
3772 * @param strEffect The window effect string.
3774 * @return The window pointer
3776 static Evas_Object *efl_create_window (const char *strWinName, const char *strEffect)
3778 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3780 Evas_Object *win = elm_win_add (NULL, strWinName, ELM_WIN_UTILITY);
3781 elm_win_title_set (win, strWinName);
3783 /* set window properties */
3784 elm_win_autodel_set (win, EINA_TRUE);
3785 elm_object_focus_allow_set (win, EINA_FALSE);
3786 elm_win_borderless_set (win, EINA_TRUE);
3787 elm_win_alpha_set (win, EINA_TRUE);
3788 elm_win_prop_focus_skip_set (win, EINA_TRUE);
3789 efl_set_showing_effect_for_app_window (win, strEffect);
3793 #endif /* CANDIDATE */
3797 * @brief Create elementary control window.
3799 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3801 static Eina_Bool efl_create_control_window (void)
3803 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3805 /* WMSYNC, #1 Creating and registering control window */
3806 if (ecore_x_display_get () == NULL)
3809 Ecore_X_Window root = ecore_x_window_root_first_get ();
3810 _control_window = ecore_x_window_input_new (root, -100, -100, 1, 1);
3811 //ecore_x_e_virtual_keyboard_control_window_set (root, _control_window, 0, EINA_TRUE);
3813 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_CONTROL_WINDOW");
3814 ecore_x_window_prop_xid_set (root, atom, ECORE_X_ATOM_WINDOW, &_control_window, 1);
3820 * @brief Get an window's x window id.
3822 * @param name the property name.
3823 * @return X window id.
3825 static Ecore_X_Window efl_get_window (const char *name)
3827 /* Gets the XID of the window from the root window property */
3831 unsigned long nitems_return;
3832 unsigned long bytes_after_return;
3833 unsigned char *data = NULL;
3834 Ecore_X_Window window = 0;
3836 ret = XGetWindowProperty ((Display *)ecore_x_display_get (),
3837 ecore_x_window_root_get (_control_window),
3838 ecore_x_atom_get (name),
3839 0, G_MAXLONG, False, XA_WINDOW, &type_return,
3840 &format_return, &nitems_return, &bytes_after_return,
3843 if (ret == Success) {
3844 if ((type_return == XA_WINDOW) && (format_return == 32) && (data)) {
3845 window = *(Window *)data;
3848 std::cerr << "XGetWindowProperty () is failed!!!\n";
3858 * @brief Get app window's x window id.
3860 * @return the X window id of application to have focus or to request to show IME.
3862 static Ecore_X_Window efl_get_app_window (void)
3864 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3866 return efl_get_window ("_ISF_ACTIVE_WINDOW");
3870 * @brief Get clipboard window's x window id.
3872 * @return the X window id of clipboard.
3874 static Ecore_X_Window efl_get_clipboard_window (void)
3876 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3878 return efl_get_window ("CBHM_ELM_WIN");
3882 * @brief Get global natigation window's x window id.
3884 * @return the X window id of global navigation.
3886 static Ecore_X_Window efl_get_global_navigation_window (void)
3888 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3890 return efl_get_window ("GNB_WIN");
3894 * @brief Get app window's x window id.
3896 * @return the X window id of quick panel.
3898 static Ecore_X_Window efl_get_quickpanel_window (void)
3900 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3902 Ecore_X_Window rootWin = ecore_x_window_root_first_get ();
3903 Ecore_X_Window qpwin;
3904 ecore_x_window_prop_xid_get (rootWin, ecore_x_atom_get ("_E_ILLUME_QUICKPANEL_WINDOW_LIST"), ECORE_X_ATOM_WINDOW, &qpwin, 1);
3910 * @brief Get default zone geometry.
3912 * @param x The zone x position.
3913 * @param y The zone y position.
3914 * @param w The zone width.
3915 * @param h The zone height.
3917 * @return EINA_TRUE if successful, otherwise return EINA_FALSE
3919 static Eina_Bool efl_get_default_zone_geometry_info (Ecore_X_Window root, uint *x, uint *y, uint *w, uint *h)
3921 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3923 Ecore_X_Atom zone_geometry_atom;
3924 Ecore_X_Window *zone_lists;
3929 zone_geometry_atom = ecore_x_atom_get ("_E_ILLUME_ZONE_GEOMETRY");
3930 if (!zone_geometry_atom) {
3936 num_zone_lists = ecore_x_window_prop_window_list_get (root, ECORE_X_ATOM_E_ILLUME_ZONE_LIST, &zone_lists);
3937 if (num_zone_lists > 0) {
3938 num_ret = ecore_x_window_prop_card32_get (zone_lists[0], zone_geometry_atom, geom, 4);
3940 if (x) *x = geom[0];
3941 if (y) *y = geom[1];
3942 if (w) *w = geom[2];
3943 if (h) *h = geom[3];
3949 /* if there is no zone available */
3954 /* We must free zone_lists */
3960 #endif /* HAVE_ECOREX */
3962 #if ISF_BUILD_CANDIDATE_UI
3964 * @brief Get screen resolution.
3966 * @param width The screen width.
3967 * @param height The screen height.
3969 static void efl_get_screen_resolution (int &width, int &height)
3971 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
3973 static Evas_Coord scr_w = 0, scr_h = 0;
3974 if (scr_w == 0 || scr_h == 0) {
3977 if (efl_get_default_zone_geometry_info (ecore_x_window_root_first_get (), NULL, NULL, &w, &h)) {
3981 ecore_x_window_size_get (ecore_x_window_root_first_get (), &scr_w, &scr_h);
3984 ecore_wl_screen_size_get(&scr_w, &scr_h);
3991 #endif /* CANDIDATE */
3993 //////////////////////////////////////////////////////////////////////
3994 // Start of PanelAgent Functions
3995 //////////////////////////////////////////////////////////////////////
3998 * @brief Initialize panel agent.
4000 * @param config The config string for PanelAgent.
4001 * @param display The current display.
4002 * @param resident The variable indicates whether panel will be resident.
4004 * @return true if initialize is successful, otherwise return false.
4006 static bool initialize_panel_agent (const ConfigPointer& config, const String &display, bool resident)
4008 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4010 LOGD ("initializing panel agent\n");
4012 _info_manager = new InfoManager ();
4014 if (!_info_manager || !_info_manager->initialize (_info_manager, config, display, resident)) {
4015 ISF_SAVE_LOG ("panel_agent initialize fail!\n");
4019 _info_manager->signal_connect_focus_in (slot (slot_focus_in));
4020 _info_manager->signal_connect_focus_out (slot (slot_focus_out));
4021 _info_manager->signal_connect_expand_candidate (slot (slot_expand_candidate));
4022 _info_manager->signal_connect_contract_candidate (slot (slot_contract_candidate));
4023 _info_manager->signal_connect_set_candidate_ui (slot (slot_set_candidate_style));
4024 _info_manager->signal_connect_update_factory_info (slot (slot_update_factory_info));
4025 _info_manager->signal_connect_update_spot_location (slot (slot_update_spot_location));
4026 _info_manager->signal_connect_update_input_context (slot (slot_update_input_context));
4027 _info_manager->signal_connect_update_ise_geometry (slot (slot_update_ise_geometry));
4028 _info_manager->signal_connect_show_preedit_string (slot (slot_show_preedit_string));
4029 _info_manager->signal_connect_show_aux_string (slot (slot_show_aux_string));
4030 _info_manager->signal_connect_show_lookup_table (slot (slot_show_candidate_table));
4031 _info_manager->signal_connect_hide_preedit_string (slot (slot_hide_preedit_string));
4032 _info_manager->signal_connect_hide_aux_string (slot (slot_hide_aux_string));
4033 _info_manager->signal_connect_hide_lookup_table (slot (slot_hide_candidate_table));
4034 _info_manager->signal_connect_update_preedit_string (slot (slot_update_preedit_string));
4035 _info_manager->signal_connect_update_preedit_caret (slot (slot_update_preedit_caret));
4036 _info_manager->signal_connect_update_aux_string (slot (slot_update_aux_string));
4037 _info_manager->signal_connect_update_lookup_table (slot (slot_update_candidate_table));
4038 _info_manager->signal_connect_select_candidate (slot (slot_select_candidate));
4039 _info_manager->signal_connect_get_candidate_geometry (slot (slot_get_candidate_geometry));
4040 _info_manager->signal_connect_get_input_panel_geometry (slot (slot_get_input_panel_geometry));
4041 _info_manager->signal_connect_set_active_ise_by_uuid (slot (slot_set_active_ise));
4042 _info_manager->signal_connect_get_ise_list (slot (slot_get_ise_list));
4043 _info_manager->signal_connect_get_all_helper_ise_info (slot (slot_get_all_helper_ise_info));
4044 _info_manager->signal_connect_set_has_option_helper_ise_info(slot (slot_set_has_option_helper_ise_info));
4045 _info_manager->signal_connect_set_enable_helper_ise_info (slot (slot_set_enable_helper_ise_info));
4046 _info_manager->signal_connect_show_helper_ise_list (slot (slot_show_helper_ise_list));
4047 _info_manager->signal_connect_show_helper_ise_selector (slot (slot_show_helper_ise_selector));
4048 _info_manager->signal_connect_is_helper_ise_enabled (slot (slot_is_helper_ise_enabled));
4049 _info_manager->signal_connect_get_ise_information (slot (slot_get_ise_information));
4050 _info_manager->signal_connect_get_keyboard_ise_list (slot (slot_get_keyboard_ise_list));
4051 _info_manager->signal_connect_get_language_list (slot (slot_get_language_list));
4052 _info_manager->signal_connect_get_all_language (slot (slot_get_all_language));
4053 _info_manager->signal_connect_get_ise_language (slot (slot_get_ise_language));
4054 _info_manager->signal_connect_get_ise_info_by_uuid (slot (slot_get_ise_info));
4055 _info_manager->signal_connect_set_keyboard_ise (slot (slot_set_keyboard_ise));
4056 _info_manager->signal_connect_get_keyboard_ise (slot (slot_get_keyboard_ise));
4057 _info_manager->signal_connect_accept_connection (slot (slot_accept_connection));
4058 _info_manager->signal_connect_close_connection (slot (slot_close_connection));
4059 _info_manager->signal_connect_exit (slot (slot_exit));
4061 _info_manager->signal_connect_register_helper_properties (slot (slot_register_helper_properties));
4062 _info_manager->signal_connect_show_ise (slot (slot_show_ise));
4063 _info_manager->signal_connect_hide_ise (slot (slot_hide_ise));
4065 _info_manager->signal_connect_will_hide_ack (slot (slot_will_hide_ack));
4067 _info_manager->signal_connect_set_keyboard_mode (slot (slot_set_keyboard_mode));
4069 _info_manager->signal_connect_candidate_will_hide_ack (slot (slot_candidate_will_hide_ack));
4070 _info_manager->signal_connect_get_ise_state (slot (slot_get_ise_state));
4071 _info_manager->signal_connect_start_default_ise (slot (slot_start_default_ise));
4072 _info_manager->signal_connect_stop_default_ise (slot (slot_stop_default_ise));
4073 _info_manager->signal_connect_show_panel (slot (slot_show_helper_ise_selector));
4074 #if ENABLE_REMOTE_INPUT
4075 _info_manager->signal_connect_remoteinput_send_input_message(slot (slot_send_remote_input_message));
4076 _info_manager->signal_connect_remoteinput_send_surrounding_text(slot (slot_recv_remote_surrounding_text));
4078 _info_manager->signal_connect_get_recent_ise_geometry (slot (slot_get_recent_ise_geometry));
4079 _info_manager->signal_connect_check_privilege_by_sockfd (slot (slot_check_privilege_by_sockfd));
4081 _info_manager->signal_connect_run_helper (slot (slot_run_helper));
4082 _info_manager->signal_connect_launch_option_application (slot (slot_launch_option_application));
4084 LOGD ("initializing panel agent succeeded\n");
4089 static void delete_ise_hide_timer (void)
4091 LOGD ("deleting ise_hide_timer\n");
4092 if (_ise_hide_timer) {
4093 ecore_timer_del (_ise_hide_timer);
4094 _ise_hide_timer = NULL;
4098 static void hide_ise ()
4100 LOGD ("send request to hide helper\n");
4101 String uuid = _info_manager->get_current_helper_uuid ();
4102 _info_manager->hide_helper (uuid);
4104 /* Only if we are not already in HIDE state */
4105 if (_ise_state != WINDOW_STATE_HIDE) {
4106 /* From this point, slot_get_input_panel_geometry should return hidden state geometry */
4107 _ise_state = WINDOW_STATE_WILL_HIDE;
4109 _updated_hide_state_geometry = false;
4113 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
4115 #if ISF_BUILD_CANDIDATE_UI
4116 if (_candidate_window) {
4117 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)
4118 ui_candidate_hide (true, true, true);
4120 ui_candidate_hide (true, false, true);
4122 #endif /* CANDIDATE */
4125 #ifdef HAVE_NOTIFICATION
4126 delete_notification (&ise_selector_module_noti);
4131 #if ENABLE_MULTIWINDOW_SUPPORT
4132 static Eina_Bool ise_hide_timeout (void *data)
4134 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4136 delete_ise_hide_timer ();
4139 return ECORE_CALLBACK_CANCEL;
4144 * @brief Insert data to ime_info table.
4146 * @param list The list to store uuid
4148 * @return true if it is successful, otherwise return false.
4150 static bool update_ise_list (std::vector<String> &list)
4152 std::vector<String> uuids;
4153 std::vector<TOOLBAR_MODE_T> modes;
4154 std::vector<ImeInfoDB>::iterator iter;
4157 if (_ime_info.size() == 0) {
4158 if (isf_pkg_select_all_ime_info_db(_ime_info) == 0)
4162 /* Update _groups */
4164 std::vector<String> ise_langs;
4165 for (size_t i = 0; i < _ime_info.size (); ++i) {
4166 scim_split_string_list(ise_langs, _ime_info[i].languages);
4167 for (size_t j = 0; j < ise_langs.size (); j++) {
4168 if (std::find (_groups[ise_langs[j]].begin (), _groups[ise_langs[j]].end (), i) == _groups[ise_langs[j]].end ())
4169 _groups[ise_langs[j]].push_back (i);
4174 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
4175 uuids.push_back(iter->appid);
4176 modes.push_back(iter->mode);
4179 if (uuids.size() > 0) {
4183 _info_manager->update_ise_list (list);
4185 if (_initial_ise_uuid.length () > 0) {
4186 String active_uuid = _initial_ise_uuid;
4187 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
4188 if (std::find (uuids.begin (), uuids.end (), default_uuid) == uuids.end ()) {
4189 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (modes[get_ise_index (_initial_ise_uuid)] != TOOLBAR_KEYBOARD_MODE)) {
4190 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4192 if (set_active_ise (active_uuid, _soft_keyboard_launched) == false) {
4193 if (_initial_ise_uuid.compare (active_uuid))
4194 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
4196 } else if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) { // Check whether keyboard engine is installed
4197 String IMENGINE_KEY = String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + String ("~other");
4198 String keyboard_uuid = _config->read (IMENGINE_KEY, String (""));
4199 if (std::find (uuids.begin (), uuids.end (), keyboard_uuid) == uuids.end ()) {
4200 active_uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
4201 _info_manager->change_factory (active_uuid);
4202 _config->write (IMENGINE_KEY, active_uuid);
4209 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
4211 if (_ime_info.size () > 0 && _ime_info[0].display_lang.compare(lang_str) == 0)
4212 _locale_string = String (lang_str);
4219 #ifdef HAVE_PKGMGR_INFO
4221 int ret = package_manager_create (&pkgmgr);
4222 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4223 ret = package_manager_set_event_cb (pkgmgr, _package_manager_event_cb, NULL);
4224 if (ret == PACKAGE_MANAGER_ERROR_NONE) {
4225 LOGD ("package_manager_set_event_cb succeeded.\n");
4228 LOGE ("package_manager_set_event_cb failed(%d)\n", ret);
4232 LOGE ("package_manager_create failed(%d)\n", ret);
4241 * @brief Focus in slot function for PanelAgent.
4243 static void slot_focus_in (void)
4245 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4248 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE)) {
4249 if (_launch_ise_on_request && !_soft_keyboard_launched) {
4250 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
4251 if (uuid.length () > 0 && (_ime_info[get_ise_index(uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
4252 LOGD ("Start helper (%s)\n", uuid.c_str ());
4254 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
4255 if (_info_manager->start_helper (uuid))
4256 _soft_keyboard_launched = true;
4261 #if ISF_BUILD_CANDIDATE_UI
4262 ui_candidate_delete_destroy_timer ();
4263 #endif /* CANDIDATE */
4267 * @brief Focus out slot function for PanelAgent.
4269 static void slot_focus_out (void)
4271 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4275 #if ISF_BUILD_CANDIDATE_UI
4276 ui_candidate_delete_destroy_timer ();
4277 _destroy_timer = ecore_timer_add (ISF_CANDIDATE_DESTROY_DELAY, ui_candidate_destroy_timeout, NULL);
4278 #endif /* CANDIDATE */
4282 * @brief Expand candidate slot function for PanelAgent.
4284 static void slot_expand_candidate (void)
4286 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4287 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4290 #if ISF_BUILD_CANDIDATE_UI
4291 if (_candidate_area_2 && !_candidate_area_2_visible)
4292 ui_candidate_window_more_button_cb (NULL, NULL, NULL, NULL);
4293 #endif /* CANDIDATE */
4297 * @brief Contract candidate slot function for PanelAgent.
4299 static void slot_contract_candidate (void)
4301 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4303 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4306 #if ISF_BUILD_CANDIDATE_UI
4307 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
4308 #endif /* CANDIDATE */
4312 * @brief Set candidate style slot function for PanelAgent.
4314 * @param portrait_line The displayed line number for portrait.
4315 * @param mode The candidate mode.
4317 static void slot_set_candidate_style (int portrait_line, int mode)
4319 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " display_line:" << portrait_line << " mode:" << mode << "\n";
4320 #if ISF_BUILD_CANDIDATE_UI
4321 if ((portrait_line != _candidate_port_line) || (mode != _candidate_mode)) {
4322 _candidate_mode = (ISF_CANDIDATE_MODE_T)mode;
4323 _candidate_port_line = (ISF_CANDIDATE_PORTRAIT_LINE_T)portrait_line;
4324 _soft_candidate_width = 0;
4325 _soft_candidate_height = 0;
4327 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4328 if (_candidate_window)
4329 ui_destroy_candidate_window ();
4334 if (_candidate_window)
4335 ui_create_candidate_window ();
4337 #endif /* CANDIDATE */
4340 #if defined(HAVE_NOTIFICATION) || defined(HAVE_ECOREX)
4341 static unsigned int get_ise_count (TOOLBAR_MODE_T mode, bool valid_helper)
4343 unsigned int ise_count = 0;
4344 for (unsigned int i = 0; i < _ime_info.size (); i++) {
4345 if (mode == _ime_info[i].mode) {
4346 if (mode == TOOLBAR_KEYBOARD_MODE || !valid_helper)
4348 else if (_ime_info[i].is_enabled)
4358 * @brief Update keyboard ISE information slot function for PanelAgent.
4360 * @param info The information of current Keyboard ISE.
4362 static void slot_update_factory_info (const PanelFactoryInfo &info)
4364 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4366 String ise_name = info.name;
4367 String ise_icon = info.icon;
4369 String old_ise = _info_manager->get_current_ise_name ();
4370 #if ISF_BUILD_CANDIDATE_UI
4371 if (old_ise != ise_name) {
4372 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && _candidate_window) {
4373 ui_destroy_candidate_window ();
4376 #endif /* CANDIDATE */
4378 TOOLBAR_MODE_T mode = _info_manager->get_current_toolbar_mode ();
4380 if (TOOLBAR_HELPER_MODE == mode)
4381 ise_name = _ime_info[get_ise_index (_info_manager->get_current_helper_uuid())].label;
4383 if (ise_name.length () > 0)
4384 _info_manager->set_current_ise_name (ise_name);
4386 #ifdef HAVE_NOTIFICATION
4388 if (old_ise != ise_name) {
4389 if (TOOLBAR_KEYBOARD_MODE == mode) {
4390 char noti_msg[256] = {0};
4391 unsigned int keyboard_ise_count = get_ise_count (TOOLBAR_KEYBOARD_MODE, false);
4392 if (keyboard_ise_count == 0) {
4393 LOGD ("the number of keyboard ise is %d\n", keyboard_ise_count);
4396 else if (keyboard_ise_count >= 2) {
4397 snprintf (noti_msg, sizeof (noti_msg), _("%s selected"), ise_name.c_str ());
4399 else if (keyboard_ise_count == 1) {
4400 snprintf (noti_msg, sizeof (noti_msg), _("Only %s available"), ise_name.c_str ());
4403 notification_status_message_post (noti_msg);
4404 LOGD ("%s\n", noti_msg);
4412 * @brief Update cursor position slot function for PanelAgent.
4414 * @param x The x position of current cursor.
4415 * @param y The bottom y position of current cursor.
4416 * @param top_y The top y position of current cursor.
4418 static void slot_update_spot_location (int x, int y, int top_y)
4420 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4422 #if ISF_BUILD_CANDIDATE_UI
4423 if (x >= 0 && x < _screen_height && y >= 0 && y < _screen_height) {
4424 _spot_location_x = x;
4425 _spot_location_y = y;
4426 _spot_location_top_y = top_y;
4428 ui_settle_candidate_window ();
4430 #endif /* CANDIDATE */
4434 * @brief The input context of ISE is changed.
4436 * @param type The event type.
4437 * @param value The event value.
4439 static void slot_update_input_context (int type, int value)
4444 * @brief Update ise geometry.
4446 * @param x The x position in screen.
4447 * @param y The y position in screen.
4448 * @param width The ISE window width.
4449 * @param height The ISE window height.
4451 static void slot_update_ise_geometry (int x, int y, int width, int height)
4453 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << x << " y:" << y << " width:" << width << " height:" << height << "...\n";
4455 LOGD ("x : %d , y : %d , width : %d , height : %d, _ise_state : %d\n", x, y, width, height, _ise_state);
4457 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
4458 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4459 /*IF ISE sent the ise_geometry information when the current_keyboard_mode is H/W mode and candidate_mode is SOFT_CANDIDATE,
4460 It means that given geometry information is for the candidate window */
4461 set_soft_candidate_geometry (x, y, width, height);
4469 _ise_height = height;
4471 #if ISF_BUILD_CANDIDATE_UI
4472 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
4473 ui_settle_candidate_window ();
4475 #endif /* CANDIDATE */
4477 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
4478 _ise_reported_geometry.valid = true;
4479 _ise_reported_geometry.angle = efl_get_ise_window_angle ();
4480 _ise_reported_geometry.geometry.pos_x = x;
4481 _ise_reported_geometry.geometry.pos_y = y;
4482 _ise_reported_geometry.geometry.width = width;
4483 _ise_reported_geometry.geometry.height = height;
4484 if (_ise_state == WINDOW_STATE_SHOW) {
4486 set_keyboard_geometry_atom_info (_app_window, _ise_reported_geometry.geometry);
4488 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
4494 * @brief Show preedit slot function for PanelAgent.
4496 static void slot_show_preedit_string (void)
4498 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4500 if (_candidate_mode == SOFT_CANDIDATE_WINDOW)
4503 #if ISF_BUILD_CANDIDATE_UI
4504 if (_preedit_window == NULL) {
4505 ui_create_preedit_window ();
4507 /* Move preedit window according to candidate window position */
4508 if (_candidate_window) {
4509 /* Get candidate window position */
4510 int x, y, width, height;
4511 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);
4513 int height2 = ui_candidate_get_valid_height ();
4514 int angle = efl_get_app_window_angle ();
4517 x -= _preedit_height;
4518 y = _screen_height - _preedit_width;
4519 } else if (_candidate_angle == 270) {
4521 } else if (_candidate_angle == 180) {
4522 x = _screen_width - _preedit_width;
4525 y -= _preedit_height;
4528 if (_preedit_window)
4529 evas_object_move (_preedit_window, x, y);
4533 if (_preedit_window && evas_object_visible_get (_preedit_window))
4536 slot_show_candidate_table ();
4538 if (_preedit_window)
4539 evas_object_show (_preedit_window);
4540 #endif /* CANDIDATE */
4544 * @brief Show aux slot function for PanelAgent.
4546 static void slot_show_aux_string (void)
4548 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4550 #if ISF_BUILD_CANDIDATE_UI
4551 if (_candidate_window == NULL)
4552 ui_create_candidate_window ();
4554 if (_aux_area == NULL || _aux_area_visible)
4557 evas_object_show (_aux_area);
4558 _aux_area_visible = true;
4559 ui_candidate_window_adjust ();
4561 LOGD ("calling ui_candidate_show ()\n");
4562 ui_candidate_show ();
4563 ui_settle_candidate_window ();
4564 ui_candidate_delete_destroy_timer ();
4565 #endif /* CANDIDATE */
4569 * @brief Show candidate table slot function for PanelAgent.
4571 static void slot_show_candidate_table (void)
4573 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4574 _info_manager->helper_candidate_show ();
4578 #if ISF_BUILD_CANDIDATE_UI
4579 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4580 if (_candidate_window == NULL)
4581 ui_create_candidate_window ();
4584 if (_candidate_state == WINDOW_STATE_SHOW &&
4585 (_candidate_area_1_visible || _candidate_area_2_visible)) {
4586 efl_set_transient_for_app_window (elm_win_xwindow_get (_candidate_window));
4591 evas_object_show (_candidate_area_1);
4592 _candidate_area_1_visible = true;
4593 ui_candidate_window_adjust ();
4595 LOGD ("calling ui_candidate_show ()\n");
4596 ui_candidate_show ();
4597 ui_settle_candidate_window ();
4598 ui_candidate_delete_destroy_timer ();
4600 #ifdef HAVE_FEEDBACK
4601 int feedback_result = feedback_initialize ();
4603 if (FEEDBACK_ERROR_NONE == feedback_result) {
4604 LOGD ("Feedback initialize successful\n");
4605 feedback_initialized = true;
4607 LOGW ("Feedback initialize fail : %d\n", feedback_result);
4608 feedback_initialized = false;
4610 #endif /* HAVE_FEEDBACK */
4611 #endif /* CANDIDATE */
4615 * @brief Hide preedit slot function for PanelAgent.
4617 static void slot_hide_preedit_string (void)
4619 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4621 #if ISF_BUILD_CANDIDATE_UI
4622 if (!_preedit_window || !evas_object_visible_get (_preedit_window))
4625 evas_object_hide (_preedit_window);
4626 #endif /* CANDIDATE */
4630 * @brief Hide aux slot function for PanelAgent.
4632 static void slot_hide_aux_string (void)
4634 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4636 #if ISF_BUILD_CANDIDATE_UI
4637 if (!_aux_area || !_aux_area_visible)
4640 evas_object_hide (_aux_area);
4641 _aux_area_visible = false;
4642 elm_scroller_region_show (_aux_area, 0, 0, 10, 10);
4643 ui_candidate_window_adjust ();
4645 LOGD ("calling ui_candidate_hide (false, true, true)\n");
4646 ui_candidate_hide (false, true, true);
4647 ui_settle_candidate_window ();
4649 if (ui_candidate_can_be_hide ()) {
4650 _candidate_show_requested = false;
4651 LOGD ("setting _show_candidate_requested to FALSE\n");
4653 #endif /* CANDIDATE */
4657 * @brief Hide candidate table slot function for PanelAgent.
4659 static void slot_hide_candidate_table (void)
4661 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4663 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
4664 _info_manager->helper_candidate_hide ();
4668 #if ISF_BUILD_CANDIDATE_UI
4669 if (!_candidate_area_1 || _candidate_state == WINDOW_STATE_WILL_HIDE)
4672 if (_candidate_area_1_visible || _candidate_area_2_visible) {
4673 bool bForce = false;
4674 if (_candidate_area_1_visible) {
4675 if (_aux_area_visible) {
4676 evas_object_hide (_candidate_area_1);
4677 _candidate_area_1_visible = false;
4678 evas_object_hide (_more_btn);
4680 /* Let's not actually hide the _candidate_area_1 object, for the case that
4681 even if the application replies CANDIDATE_WILL_HIDE_ACK a little late,
4682 it is better to display the previous candidates instead of blank screen */
4683 _candidate_area_1_visible = false;
4687 if (_candidate_area_2_visible) {
4688 evas_object_hide (_candidate_area_2);
4689 _candidate_area_2_visible = false;
4690 evas_object_hide (_scroller_bg);
4691 evas_object_hide (_close_btn);
4692 _info_manager->candidate_more_window_hide ();
4694 ui_candidate_window_adjust ();
4696 LOGD ("calling ui_candidate_hide (%d, true, true)\n", bForce);
4697 ui_candidate_hide (bForce, true, true);
4698 ui_settle_candidate_window ();
4701 #ifdef HAVE_FEEDBACK
4702 int feedback_result = feedback_deinitialize ();
4704 if (FEEDBACK_ERROR_NONE == feedback_result)
4705 LOGD ("Feedback deinitialize successful\n");
4707 LOGW ("Feedback deinitialize fail : %d\n", feedback_result);
4709 feedback_initialized = false;
4712 if (ui_candidate_can_be_hide ()) {
4713 _candidate_show_requested = false;
4714 LOGD ("setting _show_candidate_requested to FALSE\n");
4716 #endif /* CANDIDATE */
4720 * @brief Update preedit slot function for PanelAgent.
4722 * @param str The new preedit string.
4723 * @param attrs The attribute list of new preedit string.
4725 static void slot_update_preedit_string (const String &str, const AttributeList &attrs, int caret)
4727 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " string=" << str << "\n";
4729 #if ISF_BUILD_CANDIDATE_UI
4730 if (str.length () <= 0)
4733 if (_preedit_window == NULL || !evas_object_visible_get (_preedit_window)) {
4734 slot_show_preedit_string ();
4737 int x, y, width, height, candidate_width;
4738 evas_object_text_text_set (_tmp_preedit_text, str.c_str ());
4739 evas_object_geometry_get (_tmp_preedit_text, &x, &y, &width, &height);
4740 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &candidate_width, &height);
4741 _preedit_width = (width + ISF_PREEDIT_BORDER * 2) < candidate_width ? (width + ISF_PREEDIT_BORDER * 2) : candidate_width;
4743 /* Resize preedit window and avoid text blink */
4744 int old_width, old_height;
4745 evas_object_geometry_get (_preedit_window, &x, &y, &old_width, &old_height);
4746 if (old_width < _preedit_width) {
4747 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4748 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4750 edje_object_part_text_set (_preedit_text, "preedit", str.c_str ());
4751 evas_object_resize (_preedit_window, _preedit_width, _preedit_height);
4754 /* Move preedit window */
4755 if (_candidate_angle == 90 || _candidate_angle == 180) {
4756 ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_preedit_window)), &x, &y, &width, &height);
4757 if (_candidate_angle == 90) {
4758 y = _screen_height - _preedit_width;
4759 } else if (_candidate_angle == 180) {
4760 x = _screen_width - _preedit_width;
4762 evas_object_move (_preedit_window, x, y);
4764 #endif /* CANDIDATE */
4768 * @brief Update caret slot function for PanelAgent.
4770 * @param caret The caret position.
4772 static void slot_update_preedit_caret (int caret)
4774 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " caret=" << caret << "\n";
4777 #if ISF_BUILD_CANDIDATE_UI
4779 * @brief Set highlight text color and background color for edje object.
4781 * @param item The edje object pointer.
4782 * @param nForeGround The text color.
4783 * @param nBackGround The background color.
4784 * @param bSetBack The flag for background color.
4786 static void set_highlight_color (Evas_Object *item, uint32 nForeGround, uint32 nBackGround, bool bSetBack)
4788 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4790 int r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3;
4791 if (edje_object_color_class_get (item, "text_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4792 r = SCIM_RGB_COLOR_RED (nForeGround);
4793 g = SCIM_RGB_COLOR_GREEN (nForeGround);
4794 b = SCIM_RGB_COLOR_BLUE (nForeGround);
4795 edje_object_color_class_set (item, "text_color", r, g, b, a, r2, g2, b2, a2, r3, g3, b3, a3);
4797 if (bSetBack && edje_object_color_class_get (item, "rect_color", &r, &g, &b, &a, &r2, &g2, &b2, &a2, &r3, &g3, &b3, &a3)) {
4798 r = SCIM_RGB_COLOR_RED (nBackGround);
4799 g = SCIM_RGB_COLOR_GREEN (nBackGround);
4800 b = SCIM_RGB_COLOR_BLUE (nBackGround);
4801 edje_object_color_class_set (item, "rect_color", r, g, b, 255, r2, g2, b2, a2, r3, g3, b3, a3);
4804 #endif /* CANDIDATE */
4807 * @brief Update aux slot function for PanelAgent.
4809 * @param str The new aux string.
4810 * @param attrs The attribute list of new aux string.
4812 static void slot_update_aux_string (const String &str, const AttributeList &attrs)
4814 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
4815 #if ISF_BUILD_CANDIDATE_UI
4816 if (_candidate_window == NULL)
4817 ui_create_candidate_window ();
4819 if (!_aux_area || (str.length () <= 0))
4822 if (!_aux_area_visible) {
4823 LOGD ("calling ui_candidate_show ()\n");
4824 ui_candidate_show ();
4825 slot_show_aux_string ();
4828 int x, y, width, height, item_width = 0;
4829 unsigned int window_width = 0, count = 0, i;
4831 Evas_Object *aux_edje = NULL;
4833 /* Get highlight item index */
4834 int aux_index = -1, aux_start = 0, aux_end = 0;
4835 String strAux = str;
4836 bool bSetBack = false;
4837 uint32 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
4838 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
4839 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4840 if (aux_index == -1 && ait->get_type () == SCIM_ATTR_DECORATE) {
4841 aux_index = ait->get_value ();
4842 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
4843 nForeGround = ait->get_value ();
4844 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
4845 nBackGround = ait->get_value ();
4850 std::vector<String> aux_list;
4851 scim_split_string_list (aux_list, strAux, '|');
4853 if (_aux_items.size () > 0) {
4854 for (i = 0; i < _aux_items.size (); i++)
4855 evas_object_del (_aux_items [i]);
4856 _aux_items.clear ();
4858 if (_aux_seperates.size () > 0) {
4859 for (i = 0; i < _aux_seperates.size (); i++)
4860 evas_object_del (_aux_seperates [i]);
4861 _aux_seperates.clear ();
4864 int seperate_width = 4;
4865 int seperate_height = 52 * _height_rate;
4866 Evas *evas = evas_object_evas_get (_candidate_window);
4867 for (i = 0; i < aux_list.size (); i++) {
4869 Evas_Object *seperate_item = edje_object_add (evas);
4870 edje_object_file_set (seperate_item, _candidate_edje_file.c_str (), "seperate_line");
4871 evas_object_size_hint_min_set (seperate_item, seperate_width, seperate_height);
4872 elm_table_pack (_aux_table, seperate_item, 2 * i - 1, 0, 1, 1);
4873 evas_object_show (seperate_item);
4874 _aux_seperates.push_back (seperate_item);
4878 aux_edje = edje_object_add (evas);
4879 edje_object_file_set (aux_edje, _candidate_edje_file.c_str (), "aux");
4880 edje_object_part_text_set (aux_edje, "aux", aux_list [i].c_str ());
4881 edje_object_text_class_set (aux_edje, "tizen", _candidate_font_name.c_str (), _aux_font_size);
4882 elm_table_pack (_aux_table, aux_edje, 2 * i, 0, 1, 1);
4883 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_DOWN, ui_mouse_button_pressed_cb, GINT_TO_POINTER ((i << 8) + ISF_EFL_AUX));
4884 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
4885 evas_object_event_callback_add (aux_edje, EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_AUX));
4886 evas_object_show (aux_edje);
4887 _aux_items.push_back (aux_edje);
4888 /* if (i == (unsigned int)aux_index)
4889 edje_object_signal_emit (aux_edje, "aux,state,selected", "aux");
4891 edje_object_signal_emit (aux_edje, "aux,state,unselected", "aux");
4893 evas_object_text_text_set (_tmp_aux_text, aux_list [i].c_str ());
4894 evas_object_geometry_get (_tmp_aux_text, &x, &y, &width, &height);
4895 item_width = width + 2*_blank_width;
4896 item_width = item_width > _item_min_width ? item_width : _item_min_width;
4897 evas_object_size_hint_min_set (aux_edje, item_width, _aux_height);
4898 if (aux_index == (int)i || (aux_index == -1 && i == 0)) {
4899 aux_start = window_width;
4900 aux_end = window_width + item_width;
4902 window_width = window_width + item_width + 4;
4905 // Set highlight item
4906 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
4907 if (ait->get_type () == SCIM_ATTR_DECORATE) {
4908 unsigned int index = ait->get_value ();
4909 if (index < _aux_items.size ())
4910 set_highlight_color (_aux_items [index], nForeGround, nBackGround, bSetBack);
4915 elm_scroller_region_get (_aux_area, &x, &y, &w, &h);
4916 item_width = aux_end - aux_start;
4917 if (item_width > 0) {
4918 if (item_width >= w)
4919 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4920 else if (aux_end > x + w)
4921 elm_scroller_region_show (_aux_area, aux_end - w, y, w, h);
4922 else if (aux_start < x)
4923 elm_scroller_region_show (_aux_area, aux_start, y, w, h);
4926 #endif /* CANDIDATE */
4929 #if ISF_BUILD_CANDIDATE_UI
4931 * @brief Update candidate/associate table.
4933 * @param table_type The table type.
4934 * @param table The lookup table for candidate or associate.
4936 static void update_table (int table_type, const LookupTable &table)
4938 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << table.get_current_page_size () << ")\n";
4940 int item_num = table.get_current_page_size ();
4947 AttributeList attrs;
4948 int i, x, y, item_0_width = 0;
4952 int seperate_width = 2;
4953 int seperate_height = 52 * _height_rate;
4954 int line_width = _candidate_scroll_width;
4955 int line_height = _v_padding;
4956 int total_width = 0;
4957 int current_width = 0;
4960 int more_item_count = 0;
4961 int scroll_0_width = _candidate_scroll_0_width_min;
4962 int cursor_pos = table.get_cursor_pos ();
4963 int cursor_line = 0;
4965 if (_candidate_angle == 90 || _candidate_angle == 270)
4966 scroll_0_width = _screen_height - _more_btn_width - _h_padding;
4968 scroll_0_width = _screen_width - _more_btn_width - _h_padding;
4970 _candidate_image_count = 0;
4971 _candidate_text_count = 0;
4972 _candidate_pop_image_count = 0;
4973 _candidate_display_number = 0;
4974 _candidate_row_items.clear ();
4976 Evas *evas = evas_object_evas_get (_candidate_window);
4977 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
4978 if (_candidate_0 [i]) {
4979 evas_object_del (_candidate_0 [i]);
4980 _candidate_0 [i] = NULL;
4982 if (_seperate_0 [i]) {
4983 evas_object_del (_seperate_0 [i]);
4984 _seperate_0 [i] = NULL;
4986 if (_seperate_items [i]) {
4987 evas_object_del (_seperate_items [i]);
4988 _seperate_items [i] = NULL;
4991 evas_object_del (_line_0 [i]);
4994 if (_line_items [i]) {
4995 evas_object_del (_line_items [i]);
4996 _line_items [i] = NULL;
5000 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; ++i) {
5002 bool bHighLight = false;
5003 bool bSetBack = false;
5004 uint32 nForeGround = SCIM_RGB_COLOR (249, 249, 249);
5005 uint32 nBackGround = SCIM_RGB_COLOR (0, 0, 0);
5006 attrs = table.get_attributes_in_current_page (i);
5007 for (AttributeList::const_iterator ait = attrs.begin (); ait != attrs.end (); ++ait) {
5008 if (ait->get_type () == SCIM_ATTR_DECORATE && ait->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
5010 nForeGround = SCIM_RGB_COLOR (62, 207, 255);
5011 } else if (ait->get_type () == SCIM_ATTR_FOREGROUND) {
5013 nForeGround = ait->get_value ();
5014 } else if (ait->get_type () == SCIM_ATTR_BACKGROUND) {
5016 nBackGround = ait->get_value ();
5020 wcs = table.get_candidate_in_current_page (i);
5021 mbs = utf8_wcstombs (wcs);
5023 if (!_candidate_0 [i] && total_width <= scroll_0_width) {
5024 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5025 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));
5026 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5027 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_0));
5029 /* Check whether this item is the last one */
5030 if (i == item_num - 1) {
5031 if (_candidate_angle == 90 || _candidate_angle == 270)
5032 scroll_0_width = _candidate_land_width;
5034 scroll_0_width = _candidate_port_width;
5037 /* Add first item */
5039 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5040 evas_object_show (_candidate_0 [i]);
5041 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5042 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, 0, item_0_width, _item_min_height);
5043 total_width += item_0_width;
5044 _candidate_display_number++;
5047 total_width += (item_0_width + seperate_width);
5048 if (total_width <= scroll_0_width) {
5049 _seperate_0 [i] = edje_object_add (evas);
5050 edje_object_file_set (_seperate_0 [i], _candidate_edje_file.c_str (), "seperate_line");
5051 evas_object_size_hint_min_set (_seperate_0 [i], seperate_width, seperate_height);
5052 elm_table_pack (_candidate_0_table, _seperate_0 [i],
5053 total_width - item_0_width - seperate_width,
5054 line_0*(_item_min_height+line_height) + (_item_min_height - seperate_height)/2,
5055 seperate_width, seperate_height);
5056 evas_object_show (_seperate_0 [i]);
5057 evas_object_show (_candidate_0 [i]);
5058 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5059 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);
5060 _candidate_display_number++;
5062 } else if ((_candidate_angle == 0 || _candidate_angle == 180) &&
5063 (_candidate_port_line > 1 && (line_0 + 1) < _candidate_port_line)) {
5065 scroll_0_width = _candidate_scroll_0_width_min;
5066 item_0_width = item_0_width > scroll_0_width ? scroll_0_width : item_0_width;
5067 evas_object_show (_candidate_0 [i]);
5068 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5069 elm_table_pack (_candidate_0_table, _candidate_0 [i], 0, line_0*(_item_min_height+line_height), item_0_width, _item_min_height);
5070 total_width = item_0_width;
5071 _candidate_display_number++;
5073 _candidate_row_items.push_back (i - nLast);
5077 _candidate_row_items.push_back (i - nLast);
5083 if (!_candidate_0 [i]) {
5084 _candidate_0 [i] = get_candidate (mbs, _candidate_window, &item_0_width, nForeGround, nBackGround, bHighLight, bSetBack, item_num, i);
5085 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));
5086 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_UP, ui_mouse_button_released_cb, GINT_TO_POINTER (i));
5087 evas_object_event_callback_add (_candidate_0 [i], EVAS_CALLBACK_MOUSE_MOVE, ui_mouse_moved_cb, GINT_TO_POINTER (ISF_EFL_CANDIDATE_ITEMS));
5089 if (current_width > 0 && current_width + item_0_width > _candidate_scroll_width) {
5093 _candidate_row_items.push_back (i - nLast);
5095 if (cursor_pos >= i)
5098 if (current_width == 0 && !_line_items [i]) {
5099 _line_items [i] = edje_object_add (evas);
5100 edje_object_file_set (_line_items [i], _candidate_edje_file.c_str (), "popup_line");
5101 evas_object_size_hint_min_set (_line_items [i], line_width, line_height);
5103 y = line_count*(_item_min_height+line_height);
5104 elm_table_pack (_candidate_table, _line_items [i], x, y, line_width, line_height);
5105 evas_object_show (_line_items [i]);
5107 if (current_width != 0 && !_seperate_items [i]) {
5108 _seperate_items [i] = edje_object_add (evas);
5109 edje_object_file_set (_seperate_items [i], _candidate_edje_file.c_str (), "seperate_line");
5110 evas_object_size_hint_min_set (_seperate_items [i], seperate_width, seperate_height);
5112 y = line_count*(_item_min_height+line_height) + line_height + (_item_min_height - seperate_height)/2;
5113 elm_table_pack (_candidate_table, _seperate_items [i], x, y, seperate_width, seperate_height);
5114 evas_object_show (_seperate_items [i]);
5115 current_width += seperate_width;
5118 y = line_count*(_item_min_height+line_height) + line_height;
5119 evas_object_size_hint_min_set (_candidate_0 [i], item_0_width, _item_min_height);
5120 evas_object_show (_candidate_0 [i]);
5121 elm_table_pack (_candidate_table, _candidate_0 [i], x, y, item_0_width, _item_min_height);
5122 current_width += item_0_width;
5124 if (candidate_expanded == false && !bHighLight)
5127 candidate_expanded = true;
5131 for (i = 1; i < _candidate_port_line; i++) {
5132 if ((_candidate_angle == 0 || _candidate_angle == 180)) {
5133 if (_line_0 [i] == NULL) {
5134 _line_0 [i] = edje_object_add (evas);
5135 edje_object_file_set (_line_0 [i], _candidate_edje_file.c_str (), "popup_line");
5136 evas_object_size_hint_min_set (_line_0 [i], line_width, line_height);
5138 y = i * (_item_min_height + line_height) - line_height;
5139 elm_table_pack (_candidate_0_table, _line_0 [i], x, y, line_width, line_height);
5140 evas_object_show (_line_0 [i]);
5143 // Create blank line
5144 if (line_0 + 1 < _candidate_port_line && i > line_0) {
5145 int nIndex = item_num + i;
5146 nIndex = nIndex < SCIM_LOOKUP_TABLE_MAX_PAGESIZE ? nIndex : SCIM_LOOKUP_TABLE_MAX_PAGESIZE - 1;
5147 _seperate_0 [nIndex] = edje_object_add (evas);
5148 edje_object_file_set (_seperate_0 [nIndex], _candidate_edje_file.c_str (), "seperate_line");
5149 evas_object_size_hint_min_set (_seperate_0 [nIndex], seperate_width, _item_min_height);
5150 elm_table_pack (_candidate_0_table, _seperate_0 [nIndex],
5151 0, i*(_item_min_height+line_height), seperate_width, _item_min_height);
5153 } else if (_line_0 [i]) {
5154 evas_object_del (_line_0 [i]);
5159 _candidate_row_items.push_back (item_num - nLast); /* Add the number of last row */
5160 _info_manager->update_displayed_candidate_number (_candidate_display_number);
5161 _info_manager->update_candidate_item_layout (_candidate_row_items);
5162 if (more_item_count == 0) {
5163 ui_candidate_window_close_button_cb (NULL, NULL, NULL, NULL);
5164 evas_object_hide (_more_btn);
5165 evas_object_hide (_close_btn);
5166 } else if (!_candidate_area_2_visible) {
5167 evas_object_show (_more_btn);
5168 evas_object_hide (_close_btn);
5170 evas_object_hide (_more_btn);
5171 evas_object_show (_close_btn);
5175 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
5177 int line_h = _item_min_height + _v_padding;
5178 int cursor_y = cursor_line * line_h;
5180 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
5181 } else if (cursor_y >= y + h) {
5182 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
5187 #endif /* CANDIDATE */
5190 * @brief Update candidate table slot function for PanelAgent.
5192 * @param table The lookup table for candidate.
5194 static void slot_update_candidate_table (const LookupTable &table)
5196 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5198 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5199 _info_manager->update_helper_lookup_table (table);
5203 #if ISF_BUILD_CANDIDATE_UI
5204 if (_candidate_window == NULL)
5205 ui_create_candidate_window ();
5207 if (!_candidate_window || table.get_current_page_size () < 0)
5210 if (evas_object_visible_get (_candidate_area_2)) {
5211 candidate_expanded = true;
5213 candidate_expanded = false;
5216 update_table (ISF_CANDIDATE_TABLE, table);
5217 _candidate_tts_focus_index = INVALID_TTS_FOCUS_INDEX;
5218 ui_tts_focus_rect_hide ();
5219 #endif /* CANDIDATE */
5223 * @brief Send selected candidate index.
5225 * @param selected candidate string index number.
5227 static void slot_select_candidate (int index)
5229 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5230 _info_manager->select_candidate (index);
5234 * @brief Get candidate geometry slot function for PanelAgent.
5236 * @param info The data is used to store candidate position and size.
5238 static void slot_get_candidate_geometry (struct rectinfo &info)
5245 if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5249 info.height = height;
5253 #if ISF_BUILD_CANDIDATE_UI
5254 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5255 /* Get candidate window position */
5256 /*ecore_evas_geometry_get (ecore_evas_ecore_evas_get (evas_object_evas_get (_candidate_window)), &x, &y, &width, &height);*/
5257 /* Get exact candidate window size */
5259 evas_object_geometry_get (_candidate_window, &x2, &y2, &width, &height);*/
5263 width = _candidate_width;
5264 height = _candidate_height;
5266 #endif /* CANDIDATE */
5271 info.height = height;
5273 LOGD ("%d %d %d %d\n", info.pos_x, info.pos_y, info.width, info.height);
5274 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5275 << " width:" << info.width << " height:" << info.height << "\n";
5279 * @brief Get input panel geometry slot function for PanelAgent.
5281 * @param info The data is used to store input panel position and size.
5283 static void slot_get_input_panel_geometry (struct rectinfo &info)
5285 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
5290 #if ISF_BUILD_CANDIDATE_UI
5291 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5292 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5293 info.width = _candidate_width;
5294 info.height = _candidate_height;
5296 } else if (_candidate_mode == SOFT_CANDIDATE_WINDOW) {
5297 info.width = _soft_candidate_width;
5298 info.height = _soft_candidate_height;
5300 int angle = efl_get_app_window_angle ();
5301 if (angle == 90 || angle == 270)
5302 info.pos_y = _screen_width - info.height;
5304 info.pos_y = _screen_height - info.height;
5306 info = get_ise_geometry ();
5307 if (_ise_state != WINDOW_STATE_SHOW) {
5311 if (_candidate_mode == FIXED_CANDIDATE_WINDOW) {
5312 if (_candidate_window && _candidate_state == WINDOW_STATE_SHOW) {
5313 int height = ui_candidate_get_valid_height ();
5315 if ((_candidate_height - height) > _ise_height) {
5316 info.pos_y = info.pos_y + info.height - _candidate_height;
5317 info.height = _candidate_height;
5319 info.pos_y -= height;
5320 info.height += height;
5325 #endif /* CANDIDATE */
5328 LOGD ("%d %d %d %d\n", info.pos_x, info.pos_y, info.width, info.height);
5329 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " x:" << info.pos_x << " y:" << info.pos_y
5330 << " width:" << info.width << " height:" << info.height << "\n";
5334 * @brief Get the recent input panel geometry slot function for PanelAgent.
5336 * @param angle the rotation angle of application window.
5337 * @param info The data is used to store input panel position and size.
5339 static void slot_get_recent_ise_geometry (int angle, struct rectinfo &info)
5341 LOGD ("slot_get_recent_ise_geometry\n");
5343 /* If we have geometry reported by ISE, use the geometry information */
5348 if (angle == 0 || angle == 180) {
5349 if (_portrait_recent_ise_geometry.valid) {
5350 info = _portrait_recent_ise_geometry.geometry;
5355 if (_landscape_recent_ise_geometry.valid) {
5356 info = _landscape_recent_ise_geometry.geometry;
5367 static bool slot_check_privilege_by_sockfd (int client_id, String privilege)
5369 PrivilegeChecker privilegeChecker (client_id);
5371 bool priv_ret = privilegeChecker.checkPrivilege (privilege.c_str ());
5373 if (priv_ret == false)
5374 LOGW ("Failed to check privilege (%s)\n", privilege.c_str ());
5376 LOGD ("Succeeded to check privilege (%s)\n", privilege.c_str ());
5382 * @brief Set active ISE slot function for PanelAgent.
5384 * @param uuid The active ISE's uuid.
5385 * @param changeDefault The flag for changing default ISE.
5387 static void slot_set_active_ise (const String &uuid, bool changeDefault)
5389 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " (" << uuid << ")\n";
5391 bool invalid = false;
5393 #ifdef HAVE_PKGMGR_INFO
5394 /* When changing the active (default) keyboard, initialize ime_info DB if appid is invalid.
5395 This may be necessary if IME packages are changed while panel process is terminated. */
5396 pkgmgrinfo_appinfo_h handle = NULL;
5397 /* Try to get in global packages */
5398 int ret = pkgmgr_get_appinfo (uuid.c_str (), &handle);
5399 if (ret != PMINFO_R_OK) {
5400 LOGW ("appid \"%s\" is invalid.\n", uuid.c_str ());
5401 /* This might happen if IME is uninstalled while the panel process is inactive.
5402 The variable uuid would be invalid, so set_active_ise() would return false. */
5407 pkgmgrinfo_appinfo_destroy_appinfo (handle);
5411 _initialize_ime_info ();
5412 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5414 else if (set_active_ise (uuid, _soft_keyboard_launched) == false) {
5415 if (_initial_ise_uuid.compare (uuid))
5416 set_active_ise (_initial_ise_uuid, _soft_keyboard_launched);
5421 * @brief Get all ISEs list slot function for PanelAgent.
5423 * @param list The list is used to store all ISEs.
5425 * @return true if this operation is successful, otherwise return false.
5427 static bool slot_get_ise_list (std::vector<String> &list)
5429 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5431 bool result = false;
5433 std::vector<String> uuids;
5434 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5435 uuids.push_back(iter->appid);
5437 if (_ime_info.size () > 0) {
5442 result = update_ise_list (list);
5449 * @brief Get all Helper ISE information from ime_info DB.
5451 * @param info This is used to store all Helper ISE information.
5453 * @return true if this operation is successful, otherwise return false.
5455 static bool slot_get_all_helper_ise_info (HELPER_ISE_INFO &info)
5457 bool result = false;
5458 String active_ime_appid;
5460 info.appid.clear ();
5461 info.label.clear ();
5462 info.is_enabled.clear ();
5463 info.is_preinstalled.clear ();
5464 info.has_option.clear ();
5466 if (_ime_info.size() == 0)
5467 isf_pkg_select_all_ime_info_db (_ime_info);
5469 //active_ime_appid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5470 if (_info_manager) {
5471 active_ime_appid = _info_manager->get_current_helper_uuid ();
5474 if (_ime_info.size () > 0) {
5475 for (std::vector<ImeInfoDB>::iterator iter = _ime_info.begin (); iter != _ime_info.end (); iter++) {
5476 if (iter->mode == TOOLBAR_HELPER_MODE) {
5477 info.appid.push_back (iter->appid);
5478 info.label.push_back (iter->label);
5479 info.is_enabled.push_back (iter->is_enabled);
5480 info.is_preinstalled.push_back (iter->is_preinstalled);
5481 info.has_option.push_back (static_cast<uint32>(iter->has_option));
5491 * @brief Update "has_option" column of ime_info DB by Application ID
5493 * @param[in] appid Application ID of IME to enable or disable
5494 * @param[in] has_option @c true to have IME option(setting), otherwise @c false
5496 static void slot_set_has_option_helper_ise_info (const String &appid, bool has_option)
5498 if (appid.length() == 0) {
5499 LOGW ("Invalid appid\n");
5503 if (_ime_info.size() == 0)
5504 isf_pkg_select_all_ime_info_db(_ime_info);
5506 if (isf_db_update_has_option_by_appid(appid.c_str(), has_option)) { // Update ime_info DB
5507 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5508 if (appid == _ime_info[i].appid) {
5509 _ime_info[i].has_option = static_cast<uint32>(has_option); // Update global variable
5516 * @brief Update "is_enable" column of ime_info DB by Application ID
5518 * @param[in] appid Application ID of IME to enable or disable
5519 * @param[in] is_enabled @c true to enable the IME, otherwise @c false
5521 static void slot_set_enable_helper_ise_info (const String &appid, bool is_enabled)
5523 if (appid.length() == 0) {
5524 LOGW ("Invalid appid\n");
5528 if (_ime_info.size() == 0)
5529 isf_pkg_select_all_ime_info_db(_ime_info);
5531 if (isf_db_update_is_enabled_by_appid(appid.c_str(), is_enabled)) { // Update ime_info DB
5532 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5533 if (appid == _ime_info[i].appid) {
5534 _ime_info[i].is_enabled = static_cast<uint32>(is_enabled); // Update global variable
5540 #ifdef HAVE_PKGMGR_INFO
5542 * @brief Finds appid with specific category
5544 * @return 0 if success, negative value(<0) if fail. Callback is not called if return value is negative
5546 static int _find_appid_from_category (const pkgmgrinfo_appinfo_h handle, void *user_data)
5549 char **result = static_cast<char **>(user_data);
5554 ret = pkgmgrinfo_appinfo_get_appid (handle, &appid);
5555 if (ret == PMINFO_R_OK) {
5556 *result = strdup (appid);
5559 LOGW ("pkgmgrinfo_appinfo_get_appid failed!\n");
5563 LOGW ("user_data is null!\n");
5566 return -1; // This callback is no longer called.
5571 * @brief Requests to open the installed IME list application.
5573 static void slot_show_helper_ise_list (void)
5575 // Launch IME List application; e.g., org.tizen.inputmethod-setting-list
5577 char *app_id = NULL;
5578 #ifdef HAVE_PKGMGR_INFO
5579 pkgmgrinfo_appinfo_filter_h handle;
5581 if (ime_list_app.length() < 1) {
5582 ret = pkgmgrinfo_appinfo_filter_create (&handle);
5583 if (ret == PMINFO_R_OK) {
5584 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-list");
5585 if (ret == PMINFO_R_OK) {
5586 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
5588 pkgmgrinfo_appinfo_filter_destroy (handle);
5591 ime_list_app = String (app_id);
5595 app_id = strdup (ime_list_app.c_str());
5599 app_control_launch (app_id);
5603 SECURE_LOGW ("AppID with http://tizen.org/category/ime-list category is not available.\n");
5608 * @brief Requests to open the installed IME selector application.
5610 static void slot_show_helper_ise_selector (void)
5612 // Launch IME Selector application; e.g., org.tizen.inputmethod-setting-selector
5614 char *app_id = NULL;
5615 #ifdef HAVE_PKGMGR_INFO
5616 pkgmgrinfo_appinfo_filter_h handle;
5618 if (ime_selector_app.length() < 1) {
5619 ret = pkgmgrinfo_appinfo_filter_create(&handle);
5620 if (ret == PMINFO_R_OK) {
5621 ret = pkgmgrinfo_appinfo_filter_add_string(handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
5622 if (ret == PMINFO_R_OK) {
5623 pkgmgrinfo_appinfo_filter_foreach_appinfo(handle, _find_appid_from_category, &app_id);
5625 pkgmgrinfo_appinfo_filter_destroy(handle);
5628 ime_selector_app = String(app_id);
5632 app_id = strdup(ime_selector_app.c_str());
5636 app_control_launch (app_id);
5640 SECURE_LOGW ("AppID with http://tizen.org/category/ime-selector category is not available.\n");
5644 static bool slot_is_helper_ise_enabled (String appid, int &enabled)
5646 bool is_enabled = false;
5648 if (appid.length() == 0) {
5649 LOGW ("Invalid appid.\n");
5653 if (_ime_info.size() == 0)
5654 isf_pkg_select_all_ime_info_db(_ime_info);
5656 if (isf_db_select_is_enabled_by_appid(appid.c_str(), &is_enabled)) {
5657 enabled = static_cast<int>(is_enabled);
5666 * @brief Get the ISE's information.
5668 * @param uuid The ISE's uuid.
5669 * @param name The ISE's name.
5670 * @param language The ISE's language.
5671 * @param type The ISE's type.
5672 * @param option The ISE's option.
5674 * @return true if this operation is successful, otherwise return false.
5676 static bool slot_get_ise_information (String uuid, String &name, String &language, int &type, int &option, String &module_name)
5678 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5680 if (uuid.length () > 0) {
5681 // update all ISE names according to the display languages
5682 // sometimes get_ise_information is called before vconf display language changed callback is called.
5683 update_ise_locale ();
5685 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5686 if (uuid == _ime_info[i].appid) {
5687 name = _ime_info[i].label;
5688 language = _ime_info[i].languages;
5689 type = _ime_info[i].mode;
5690 option = _ime_info[i].options;
5691 module_name = _ime_info[i].module_name;
5697 std::cerr << __func__ << " is failed!!!\n";
5702 * @brief Get keyboard ISEs list slot function for PanelAgent.
5704 * @param name_list The list is used to store keyboard ISEs.
5706 * @return true if this operation is successful, otherwise return false.
5708 static bool slot_get_keyboard_ise_list (std::vector<String> &name_list)
5710 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5712 isf_load_ise_information (ALL_ISE, _config);
5714 std::vector<String> lang_list, uuid_list;
5715 isf_get_all_languages (lang_list);
5716 isf_get_keyboard_ises_in_languages (lang_list, uuid_list, name_list, false);
5718 _info_manager->update_ise_list (uuid_list);
5723 * @brief Get enable languages list slot function for PanelAgent.
5725 * @param list The list is used to store languages.
5727 static void slot_get_language_list (std::vector<String> &list)
5729 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5732 MapStringVectorSizeT::iterator iter = _groups.begin ();
5734 for (; iter != _groups.end (); iter++) {
5735 lang_name = scim_get_language_name (iter->first);
5736 list.push_back (lang_name);
5741 * @brief Get all languages list slot function for PanelAgent.
5743 * @param lang The list is used to store languages.
5745 static void slot_get_all_language (std::vector<String> &lang)
5747 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5749 isf_get_all_languages (lang);
5753 * @brief Get specific ISE language list slot function for PanelAgent.
5755 * @param name The ISE name.
5756 * @param list The list is used to store ISE languages.
5758 static void slot_get_ise_language (char *name, std::vector<String> &list)
5760 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5765 std::vector<String> list_tmp;
5767 for (unsigned int i = 0; i < _ime_info.size(); i++) {
5768 if (!strcmp (_ime_info[i].label.c_str (), name)) {
5769 scim_split_string_list (list_tmp, _ime_info[i].languages, ',');
5770 for (i = 0; i < list_tmp.size (); i++)
5771 list.push_back (scim_get_language_name (list_tmp[i]));
5778 * @brief Get ISE information slot function for PanelAgent.
5780 * @param uuid The ISE uuid.
5781 * @param info The variable is used to store ISE information.
5783 * @return true if this operation is successful, otherwise return false.
5785 static bool slot_get_ise_info (const String &uuid, ISE_INFO &info)
5787 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5789 for (unsigned int i = 0; i < _ime_info.size (); i++) {
5790 if (!uuid.compare (_ime_info[i].appid)) {
5791 info.uuid = _ime_info[i].appid;
5792 info.name = _ime_info[i].label;
5793 info.icon = _ime_info[i].iconpath;
5794 info.lang = _ime_info[i].languages;
5795 info.option = _ime_info[i].options;
5796 info.type = _ime_info[i].mode;
5805 * @brief Set keyboard ISE slot function for PanelAgent.
5807 * @param uuid The variable is ISE uuid.
5809 static void slot_set_keyboard_ise (const String &uuid)
5811 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << uuid << "\n";
5813 std::vector<String> uuids;
5814 std::vector<ImeInfoDB>::iterator iter;
5815 for (iter = _ime_info.begin(); iter != _ime_info.end(); iter++) {
5816 uuids.push_back(iter->appid);
5819 if (uuid.length () <= 0 || std::find (uuids.begin (), uuids.end (), uuid) == uuids.end ())
5822 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
5823 if (_ime_info[get_ise_index (default_uuid)].mode == TOOLBAR_KEYBOARD_MODE)
5826 uint32 ise_option = 0;
5827 String ise_uuid, ise_name;
5828 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5829 if (ise_uuid == uuid)
5832 String language = String ("~other");/*scim_get_locale_language (scim_get_current_locale ());*/
5833 _config->write (String (SCIM_CONFIG_DEFAULT_IMENGINE_FACTORY) + String ("/") + language, uuid);
5837 _info_manager->change_factory (uuid);
5841 * @brief Get current keyboard ISE name and uuid slot function for PanelAgent.
5843 * @param ise_name The variable is used to store ISE name.
5844 * @param ise_uuid The variable is used to store ISE uuid.
5846 static void slot_get_keyboard_ise (String &ise_name, String &ise_uuid)
5848 uint32 ise_option = 0;
5849 isf_get_keyboard_ise (_config, ise_uuid, ise_name, ise_option);
5851 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " uuid = " << ise_uuid << "\n";
5855 * @brief Accept connection slot function for PanelAgent.
5857 * @param fd The file descriptor to connect.
5859 static void slot_accept_connection (int fd)
5861 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5864 get_input_window ();
5869 * @brief Close connection slot function for PanelAgent.
5871 * @param fd The file descriptor to connect.
5873 static void slot_close_connection (int fd)
5875 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5879 * @brief Exit panel process slot function for PanelAgent.
5881 static void slot_exit (void)
5883 std::cerr << __FUNCTION__ << "...\n";
5884 ISF_SAVE_LOG ("exit\n");
5886 #if ISF_BUILD_CANDIDATE_UI
5889 ecore_main_loop_quit ();
5890 #endif /* CANDIDATE */
5893 static void slot_register_helper_properties (int id, const PropertyList &props)
5895 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5897 /* WMSYNC, #2 Receiving X window ID from ISE */
5898 /* FIXME : We should add an API to set window id of ISE */
5899 Property prop = props[0];
5900 if (prop.get_label ().compare ("XID") == 0) {
5901 Ecore_X_Window xwindow = atoi (prop.get_key ().c_str ());
5902 _ise_window = xwindow;
5903 LOGD ("ISE XID : %x\n", _ise_window);
5905 /* Just in case for the helper sent this message later than show_ise request */
5906 if (_ise_state == WINDOW_STATE_SHOW || _ise_state == WINDOW_STATE_WILL_SHOW) {
5907 efl_set_transient_for_app_window (_ise_window);
5910 Ecore_X_Atom atom = ecore_x_atom_get ("_ISF_ISE_WINDOW");
5911 if (atom && _control_window && _ise_window) {
5912 ecore_x_window_prop_xid_set (_control_window, atom, ECORE_X_ATOM_WINDOW, &_ise_window, 1);
5914 #ifdef HAVE_NOTIFICATION
5915 delete_notification (&ise_selector_module_noti);
5921 #if ENABLE_REMOTE_INPUT
5922 static void slot_send_remote_input_message (const String &msg, bool len)
5924 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5926 String con = msg.c_str ();
5927 ISE_MESSAGE message = CISEMessageSerializer::deserialize(con);
5929 if (remote_input_impl == NULL) {
5930 remote_input_impl = Remote_Input::get_instance();
5933 if (remote_input_impl)
5934 remote_input_impl->handle_websocket_message(message);
5937 static void slot_recv_remote_surrounding_text (int cursor, const String &text)
5939 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5941 if (remote_input_impl == NULL) {
5942 remote_input_impl = Remote_Input::get_instance();
5945 if (remote_input_impl)
5946 remote_input_impl->handle_recv_panel_message(3, text.c_str (), cursor);
5950 static void slot_show_ise (void)
5952 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
5954 /* If the current toolbar mode is not HELPER_MODE, do not proceed */
5955 if (_info_manager->get_current_toolbar_mode () != TOOLBAR_HELPER_MODE) {
5956 LOGD ("Current toolbar mode should be TOOLBAR_HELPER_MODE but is %d, returning\n",
5957 _info_manager->get_current_toolbar_mode ());
5961 LOGD ("slot_show_ise ()\n");
5963 delete_ise_hide_timer ();
5965 /* WMSYNC, #3 Clear the existing application's conformant area and set transient_for */
5966 // Unset conformant area
5967 Ecore_X_Window current_app_window = efl_get_app_window ();
5968 if (_app_window != current_app_window) {
5969 struct rectinfo info = {0, 0, 0, 0};
5970 info.pos_y = _screen_width > _screen_height ? _screen_width : _screen_height;
5971 set_keyboard_geometry_atom_info (_app_window, info);
5972 ecore_x_event_mask_unset (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
5973 LOGD ("Conformant reset for window %x\n", _app_window);
5974 _app_window = current_app_window;
5976 /* If the target window has changed but our ISE is still in visible state,
5977 update the keyboard geometry information */
5978 if (_ise_state == WINDOW_STATE_SHOW) {
5979 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
5983 /* If the candidate was already in SHOW state, respect the current angle */
5984 if (_candidate_state != WINDOW_STATE_SHOW) {
5985 /* FIXME : Need to check if candidate_angle and window_angle should be left as separated */
5986 _candidate_angle = efl_get_app_window_angle ();
5988 /* If the ise was already in SHOW state, respect the current angle */
5989 if (_ise_state != WINDOW_STATE_SHOW) {
5990 _ise_angle = efl_get_app_window_angle ();
5993 ecore_x_event_mask_set (_app_window, ECORE_X_EVENT_MASK_WINDOW_FOCUS_CHANGE);
5994 efl_set_transient_for_app_window (_ise_window);
5996 /* Make clipboard window to have transient_for information on ISE window,
5997 so that the clipboard window will always be above ISE window */
5998 Ecore_X_Window clipboard_window = efl_get_clipboard_window ();
5999 if (_ise_window && clipboard_window) {
6000 ecore_x_icccm_transient_for_set (clipboard_window, _ise_window);
6003 /* If our ISE was already in SHOW state, skip state transition to WILL_SHOW */
6004 if (_ise_state != WINDOW_STATE_SHOW) {
6005 _ise_state = WINDOW_STATE_WILL_SHOW;
6009 #if ISF_BUILD_CANDIDATE_UI
6010 _candidate_angle = 0;
6011 #endif /* CANDIDATE */
6012 _ise_state = WINDOW_STATE_SHOW;
6014 #ifdef HAVE_NOTIFICATION
6015 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6016 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6017 show_ime_selector_notification ();
6024 static void slot_hide_ise (void)
6026 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6028 LOGD ("slot_hide_ise ()\n");
6030 if (!_ise_hide_timer)
6034 static void slot_will_hide_ack (void)
6036 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6038 /* WMSYNC, #8 Let the Window Manager to actually hide keyboard window */
6039 // WILL_HIDE_REQUEST_DONE Ack to WM
6040 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6041 //ecore_x_e_virtual_keyboard_off_prepare_done_send (root_window, _control_window);
6042 LOGD ("_ecore_x_e_virtual_keyboard_off_prepare_done_send (%x, %x)\n",
6043 root_window, _control_window);
6044 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6045 LOGD ("calling ui_candidate_hide (true, false)\n");
6046 ui_candidate_hide (true, false);
6049 /* WILL_HIDE_ACK means that the application finished redrawing the autoscroll area,
6050 now hide the candidate window right away if it is also in WILL_HIDE state */
6051 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6052 candidate_window_hide ();
6055 if (_off_prepare_done_timer) {
6056 ecore_timer_del (_off_prepare_done_timer);
6057 _off_prepare_done_timer = NULL;
6062 static void slot_candidate_will_hide_ack (void)
6064 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6066 LOGD ("candidate_will_hide_ack\n");
6067 if (_candidate_state == WINDOW_STATE_WILL_HIDE) {
6068 candidate_window_hide ();
6073 static void slot_set_keyboard_mode (int mode)
6075 LOGD ("slot_set_keyboard_mode called (TOOLBAR_MODE : %d)\n", mode);
6077 change_keyboard_mode ((TOOLBAR_MODE_T)mode);
6080 static void slot_get_ise_state (int &state)
6082 if (_ise_state == WINDOW_STATE_SHOW ||
6083 ((_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) && (_candidate_state == WINDOW_STATE_SHOW))) {
6084 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6086 /* Currently we don't have WILL_HIDE / HIDE state distinction in Ecore_IMF */
6087 switch (_ise_state) {
6088 case WINDOW_STATE_SHOW :
6089 state = ECORE_IMF_INPUT_PANEL_STATE_SHOW;
6091 case WINDOW_STATE_WILL_SHOW :
6092 state = ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW;
6094 case WINDOW_STATE_WILL_HIDE :
6095 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6097 case WINDOW_STATE_HIDE :
6098 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6101 state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
6104 LOGD ("state = %d\n", state);
6105 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " state = " << state << "\n";
6108 static void slot_start_default_ise (void)
6110 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6111 if ((_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE)) {
6112 if (_launch_ise_on_request && !_soft_keyboard_launched) {
6113 String uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6115 LOGD ("Start helper (%s)\n", uuid.c_str ());
6117 set_keyboard_engine (String (SCIM_COMPOSE_KEY_FACTORY_UUID));
6118 if (_info_manager->start_helper (uuid))
6119 _soft_keyboard_launched = true;
6124 static void slot_stop_default_ise (void)
6126 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6128 if (_launch_ise_on_request && _soft_keyboard_launched) {
6129 String uuid = _info_manager->get_current_helper_uuid ();
6131 if (uuid.length () > 0) {
6132 _info_manager->hide_helper (uuid);
6133 _info_manager->stop_helper (uuid);
6134 _soft_keyboard_launched = false;
6135 LOGD ("stop helper (%s)\n", uuid.c_str ());
6140 static void launch_helper (const char* exec, const char *name, const char *appid, const char *config, const char *display)
6146 if (pid < 0) return;
6149 const char *argv [] = { exec,
6152 "--display", display,
6153 const_cast<char*> (name),
6154 const_cast<char*> (appid),
6157 SCIM_DEBUG_MAIN (2) << " Call scim-helper-launcher.\n";
6158 ISF_SAVE_LOG ("Exec scim_helper_launcher(%s %s)\n", name, appid);
6160 unsetenv ("ELM_THEME");
6161 unsetenv ("ELM_SCALE");
6164 LOGD ("launch execpath : %s\n", exec);
6165 execv (exec, const_cast<char **>(argv));
6166 #if ISF_BUILD_CANDIDATE_UI
6169 ecore_main_loop_quit ();
6170 #endif /* CANDIDATE */
6174 static void app_control_launch (const char *app_id)
6176 app_control_h app_control;
6179 ret = app_control_create (&app_control);
6180 if (ret != APP_CONTROL_ERROR_NONE) {
6181 LOGW ("app_control_create returned %08x\n", ret);
6185 ret = app_control_set_operation (app_control, APP_CONTROL_OPERATION_DEFAULT);
6186 if (ret != APP_CONTROL_ERROR_NONE) {
6187 LOGW ("app_control_set_operation returned %08x\n", ret);
6188 app_control_destroy (app_control);
6192 ret = app_control_set_app_id (app_control, app_id);
6193 if (ret != APP_CONTROL_ERROR_NONE) {
6194 LOGW ("app_control_set_app_id returned %08x\n", ret);
6195 app_control_destroy (app_control);
6199 ret = app_control_send_launch_request (app_control, NULL, NULL);
6200 if (ret != APP_CONTROL_ERROR_NONE) {
6201 LOGW ("app_control_send_launch_request returned %08x, app_id=%s\n", ret, app_id);
6202 app_control_destroy (app_control);
6206 app_control_destroy (app_control);
6207 LOGD ("Launch %s\n", app_id);
6210 static void slot_run_helper (const String &uuid, const String &config, const String &display)
6212 ISF_SAVE_LOG ("time:%ld pid:%d %s %s uuid(%s)\n",
6213 time (0), getpid (), __FILE__, __func__, uuid.c_str ());
6215 String strConfig = config;
6216 String strDisplay = display;
6217 String scim_helper_path;
6219 #ifdef HAVE_PKGMGR_INFO
6220 char *execpath = NULL;
6222 pkgmgrinfo_appinfo_h appinfo_handle;
6224 /* get app info handle */
6225 /* Try to get in global packages */
6226 ret = pkgmgr_get_appinfo (uuid.c_str (), &appinfo_handle);
6227 if (ret != PMINFO_R_OK) {
6228 LOGW ("pkgmgrinfo_appinfo_get_appinfo () & get_usr_appinfo () failed. appid : %s, ret : %d \n", uuid.c_str (), ret);
6233 ret = pkgmgrinfo_appinfo_get_exec (appinfo_handle, &execpath);
6234 if (ret != PMINFO_R_OK) {
6235 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6239 LOGD ("exec path : %s\n", execpath);
6240 scim_helper_path = String (execpath);
6242 if (appinfo_handle) {
6243 pkgmgrinfo_appinfo_destroy_appinfo (appinfo_handle);
6244 appinfo_handle = NULL;
6247 scim_helper_path = String (SCIM_HELPER_LAUNCHER_PROGRAM);
6250 for (size_t i = 0; i < _ime_info.size (); ++i) {
6251 if (_ime_info[i].appid == uuid && _ime_info[i].module_name.length ()) {
6252 if (scim_helper_path != String (SCIM_HELPER_LAUNCHER_PROGRAM)) {
6253 /* Check if IME with the same AppID is alive */
6254 int status_ret = aul_app_get_status (uuid.c_str ());
6255 if (status_ret >= STATUS_LAUNCHING) {
6256 /* Request to terminate IME */
6257 int ime_pid = aul_app_get_pid (uuid.c_str ());
6258 status_ret = aul_terminate_pid (ime_pid);
6259 if (status_ret < AUL_R_OK) {
6260 LOGE ("aul_terminate_pid(%d) failed: %d", ime_pid, status_ret);
6263 LOGD ("Requested to terminate IME(%s)", uuid.c_str ());
6267 /* execute type IME */
6268 app_control_launch (uuid.c_str ());
6271 /* shared object (so) type IME */
6272 launch_helper (scim_helper_path.c_str(), _ime_info[i].module_name.c_str (), uuid.c_str (), config.c_str (), display.c_str ());
6279 SCIM_DEBUG_MAIN (2) << " exit run_helper ().\n";
6282 static bool slot_launch_option_application (String ime_appid)
6284 String ime_setting_app = isf_pkg_get_setting_app (ime_appid);
6286 LOGD ("IME appid : %s, IME setting app id : %s\n", ime_appid.c_str (), ime_setting_app.c_str ());
6288 if (ime_setting_app.length () > 0) {
6289 app_control_launch (ime_setting_app.c_str ());
6296 //////////////////////////////////////////////////////////////////////
6297 // End of PanelAgent-Functions
6298 //////////////////////////////////////////////////////////////////////
6302 * @brief Callback function for abnormal signal.
6304 * @param sig The signal.
6306 static void signalhandler (int sig)
6308 std::cerr << __FUNCTION__ << " Signal=" << sig << "\n";
6309 ISF_SAVE_LOG ("Signal=%d\n", sig);
6311 #if ISF_BUILD_CANDIDATE_UI
6314 ecore_main_loop_quit ();
6315 #endif /* CANDIDATE */
6319 static void update_ise_locale (const char *language)
6324 strLang = String (language);
6327 char *lang_str = vconf_get_str (VCONFKEY_LANGSET);
6328 if (lang_str && _locale_string.compare(lang_str) == 0) {
6333 strLang = String (lang_str);
6340 LOGD ("update all ISE names according to display language : %s\n", strLang.c_str ());
6341 set_language_and_locale (strLang.c_str ());
6343 bool need_to_init_db = false;
6344 #ifdef HAVE_PKGMGR_INFO
6348 pkgmgrinfo_appinfo_h handle = NULL;
6350 /* Read DB from ime_info table */
6351 isf_load_ise_information(ALL_ISE, _config);
6353 for (unsigned int i = 0; i < _ime_info.size (); i++) {
6354 ret = pkgmgr_get_appinfo (_ime_info[i].appid.c_str(), &handle);
6356 if (ret == PMINFO_R_OK) {
6357 ret = pkgmgrinfo_appinfo_is_category_exist(handle, "http://tizen.org/category/ime", &exist);
6358 if (ret == PMINFO_R_OK && exist) {
6359 ret = pkgmgrinfo_appinfo_get_label(handle, &label);
6360 if (ret == PMINFO_R_OK && label) {
6361 _ime_info[i].label = String(label);
6362 /* Update label column in ime_info db table */
6363 if (isf_db_update_label_by_appid(_ime_info[i].appid.c_str(), label)) {
6364 _ime_info[i].label = label;
6369 // The appid is invalid.. Need to initialize ime_info DB.
6370 need_to_init_db = true;
6372 pkgmgrinfo_appinfo_destroy_appinfo(handle);
6375 // The appid is invalid.. Need to initialize ime_info DB.
6376 need_to_init_db = true;
6381 if (need_to_init_db) {
6382 _initialize_ime_info ();
6385 if (strLang.length () > 0) {
6386 isf_db_update_disp_lang (strLang.c_str ());
6387 _locale_string = strLang;
6392 * @brief Set language and locale.
6396 static void set_language_and_locale (const char *lang_str)
6398 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6403 LOGD ("language : %s\n", lang_str);
6404 #if ISF_BUILD_CANDIDATE_UI
6405 elm_language_set (lang_str);
6406 #endif /* CANDIDATE */
6408 snprintf (language, sizeof (language), "%s:en_US:en_GB:en", lang_str);
6409 setenv ("LANGUAGE", language, 1);
6410 setenv ("LANG", lang_str, 1);
6411 setlocale (LC_MESSAGES, lang_str);
6413 setenv ("LANG", "en_US.utf8", 1);
6414 setlocale (LC_MESSAGES, "en_US.utf8");
6419 * @brief Callback function for display language change.
6421 * @param key The key node.
6422 * @param data The data to pass to this callback.
6426 static void display_language_changed_cb (keynode_t *key, void* data)
6428 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6430 char *lang_str = vconf_keynode_get_str (key);
6431 LOGD ("lang : %s\n", lang_str);
6432 set_language_and_locale (lang_str);
6434 /* Update all ISE names according to display language */
6435 update_ise_locale ();
6437 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), _initial_ise_uuid);
6438 unsigned int ise_idx = get_ise_index (default_uuid);
6440 if (ise_idx < _ime_info.size ()) {
6441 String default_name = _ime_info[ise_idx].label;
6442 _info_manager->set_current_ise_name (default_name);
6448 * @brief Callback function for keyboard mode change.
6450 * @param key The key node.
6451 * @param data The data to pass to this callback.
6455 static void keyboard_mode_changed_cb (keynode_t *key, void* data)
6457 bool val = vconf_keynode_get_bool (key);
6460 _info_manager->reset_keyboard_ise ();
6461 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6462 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6468 * @brief Change keyboard mode.
6470 * @param mode The keyboard mode.
6474 static void change_keyboard_mode (TOOLBAR_MODE_T mode)
6476 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6480 bool _support_hw_keyboard_mode = false;
6482 unsigned int val = 0;
6486 int input_detect = false;
6489 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
6490 String default_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_ISE_UUID), String (""));
6491 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
6493 if (mode == TOOLBAR_KEYBOARD_MODE && _support_hw_keyboard_mode) {
6494 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6495 LOGD ("HARDWARE_KEYBOARD_MODE return\n");
6499 LOGD ("HARDWARE KEYBOARD MODE\n");
6500 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 1);
6503 if (_ime_info[get_ise_index(default_uuid)].mode == TOOLBAR_HELPER_MODE) {
6504 /* Get the keyboard ISE */
6505 isf_get_keyboard_ise (_config, uuid, name, option);
6506 if (option & SCIM_IME_NOT_SUPPORT_HARDWARE_KEYBOARD) {
6507 uuid = String (SCIM_COMPOSE_KEY_FACTORY_UUID);
6508 std::cerr << __FUNCTION__ << ": Keyboard ISE (" << name << ") can not support hardware keyboard!!!\n";
6510 /* Try to find reasonable keyboard ISE according to helper ISE language */
6511 if (uuid == String (SCIM_COMPOSE_KEY_FACTORY_UUID)) {
6512 String helper_language = _ime_info[get_ise_index(default_uuid)].languages;
6513 if (helper_language.length () > 0) {
6514 std::vector<String> ise_langs;
6515 scim_split_string_list (ise_langs, helper_language);
6516 for (size_t i = 0; i < _groups[ise_langs[0]].size (); ++i) {
6517 int j = _groups[ise_langs[0]][i];
6518 if (_ime_info[j].appid != uuid && _ime_info[j].mode == TOOLBAR_KEYBOARD_MODE) {
6519 uuid = _ime_info[j].appid;
6527 uuid = default_uuid;
6529 #if ISF_BUILD_CANDIDATE_UI
6530 _soft_candidate_width = 0;
6531 _soft_candidate_height = 0;
6532 #endif /* CANDIDATE */
6533 _ise_state = WINDOW_STATE_HIDE;
6534 _info_manager->set_current_toolbar_mode (TOOLBAR_KEYBOARD_MODE);
6535 _info_manager->hide_helper (helper_uuid);
6537 /* Check whether stop soft keyboard */
6538 if (_focus_in && (_ime_info[get_ise_index (helper_uuid)].options & ISM_HELPER_PROCESS_KEYBOARD_KEYEVENT)) {
6539 /* If focus in and soft keyboard can support hardware key event, then don't stop it */
6541 } else if (_launch_ise_on_request && _soft_keyboard_launched) {
6542 _info_manager->stop_helper (helper_uuid);
6543 _soft_keyboard_launched = false;
6546 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6549 #ifdef HAVE_NOTIFICATION
6551 notification_status_message_post (_("Input detected from hardware keyboard"));
6553 /* Read configuations for notification app (isf-kbd-mode-changer) */
6554 String kbd_mode_changer = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_DEFAULT_KBD_MODE_CHANGER_PROGRAM), String (""));
6555 hwkbd_module_noti.launch_app = kbd_mode_changer;
6556 LOGD ("Create kbd_mode_changer notification with : %s\n", kbd_mode_changer.c_str ());
6557 create_notification (&hwkbd_module_noti);
6562 vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect);
6564 if (!input_detect) {
6565 if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 1) != 0)
6566 LOGW ("Failed to set vconf key\n");
6568 LOGD ("Succeeded to set vconf key\n");
6571 } else if (mode == TOOLBAR_HELPER_MODE) {
6572 LOGD ("SOFTWARE KEYBOARD MODE\n");
6573 /* When switching back to S/W keyboard mode, let's hide candidate window first */
6574 #if ISF_BUILD_CANDIDATE_UI
6575 LOGD ("calling ui_candidate_hide (true, true, true)\n");
6576 ui_candidate_hide (true, true, true);
6577 #endif /* CANDIDATE */
6578 _config->write (ISF_CONFIG_HARDWARE_KEYBOARD_DETECT, 0);
6580 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6581 uuid = helper_uuid.length () > 0 ? helper_uuid : _initial_ise_uuid;
6582 if (_launch_ise_on_request) {
6583 if (set_active_ise (uuid, false) == false) {
6584 if (_initial_ise_uuid.compare(uuid))
6585 set_active_ise (_initial_ise_uuid, false);
6589 if (set_active_ise (uuid, true) == false) {
6590 if (_initial_ise_uuid.compare(uuid))
6591 set_active_ise (_initial_ise_uuid, true);
6596 #ifdef HAVE_NOTIFICATION
6597 delete_notification (&hwkbd_module_noti);
6601 vconf_get_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, &input_detect);
6604 if (vconf_set_bool (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, 0) != 0)
6605 LOGW ("Failed to set vconf key\n");
6607 LOGD ("Succeeded to set vconf key\n");
6614 #ifdef HAVE_BLUETOOTH
6616 * @brief Callback function for the connection state of Bluetooth Keyboard
6618 * @param result The result of changing the connection state
6619 * @param connected The state to be changed. true means connected state, Otherwise, false.
6620 * @param remote_address The remote address
6621 * @param user_data The user data passed from the callback registration function
6625 static void _bt_cb_hid_state_changed (int result, bool connected, const char *remote_address, void *user_data)
6627 if (connected == false) {
6628 LOGD ("Bluetooth keyboard disconnected\n");
6629 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6630 change_keyboard_mode (TOOLBAR_HELPER_MODE);
6636 #ifdef HAVE_NOTIFICATION
6637 static void show_ime_selector_notification ()
6641 if (!_MOBILE) return;
6643 unsigned int idx = get_ise_index (_info_manager->get_current_helper_uuid ());
6644 if (idx < _ime_info.size ())
6645 ise_name = _ime_info[idx].label;
6647 String noti_icon_path = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_QUICK_PANEL_ICON_PATH), String (SCIM_ICONDIR));
6648 noti_icon_path += ISF_ISE_SELECTOR_ICON_FILE;
6650 LOGD("IME selector icon path : %s\n", noti_icon_path.c_str ());
6652 ise_selector_module_noti.icon = noti_icon_path.c_str ();
6653 ise_selector_module_noti.content = ise_name.c_str ();
6655 /* Find IME Selector appid for notification */
6656 if (ime_selector_app.length () < 1) {
6657 char *app_id = NULL;
6658 pkgmgrinfo_appinfo_filter_h handle;
6659 int ret = pkgmgrinfo_appinfo_filter_create (&handle);
6660 if (ret == PMINFO_R_OK) {
6661 ret = pkgmgrinfo_appinfo_filter_add_string (handle, PMINFO_APPINFO_PROP_APP_CATEGORY, "http://tizen.org/category/ime-selector");
6662 if (ret == PMINFO_R_OK) {
6663 pkgmgrinfo_appinfo_filter_foreach_appinfo (handle, _find_appid_from_category, &app_id);
6665 pkgmgrinfo_appinfo_filter_destroy (handle);
6668 ime_selector_app = String (app_id);
6675 if (ime_selector_app.length () > 0) {
6676 ise_selector_module_noti.launch_app = ime_selector_app;
6677 LOGD ("Create ise_selector notification with : %s\n", ime_selector_app.c_str ());
6678 create_notification (&ise_selector_module_noti);
6681 LOGW ("AppID with http://tizen.org/category/ime-selector category is not available\n");
6687 * @brief Callback function for ECORE_X_EVENT_WINDOW_PROPERTY.
6689 * @param data Data to pass when it is called.
6690 * @param ev_type The event type.
6691 * @param ev The information for current message.
6693 * @return ECORE_CALLBACK_PASS_ON
6695 static Eina_Bool x_event_window_property_cb (void *data, int ev_type, void *event)
6697 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6699 Ecore_X_Event_Window_Property *ev = (Ecore_X_Event_Window_Property *)event;
6702 return ECORE_CALLBACK_PASS_ON;
6704 if (ev->atom == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE) {
6705 if (ev->win == _control_window) {
6706 /* WMSYNC, #6 The keyboard window is displayed fully so set the conformant geometry */
6707 LOGD ("ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_STATE : win : %p, atom : %d\n", ev->win, ev->atom);
6708 Ecore_X_Virtual_Keyboard_State state;
6709 state = ecore_x_e_virtual_keyboard_state_get (ev->win);
6710 if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_ON) {
6711 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_ON\n");
6712 _ise_state = WINDOW_STATE_SHOW;
6714 /* Make sure that we have the same rotation angle with the keyboard window */
6716 _candidate_angle = efl_get_ise_window_angle ();
6717 _ise_angle = efl_get_ise_window_angle ();
6720 if (_candidate_show_requested) {
6721 LOGD ("calling ui_candidate_show (true)\n");
6722 ui_candidate_show (true);
6724 if (_candidate_area_1_visible) {
6725 LOGD ("calling ui_candidate_show (false)\n");
6726 ui_candidate_show (false);
6730 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6731 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6732 _info_manager->update_input_panel_event (
6733 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_SHOW);
6736 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_SHOW);
6739 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6740 if (get_ise_count (TOOLBAR_HELPER_MODE, true) >= 2) {
6741 ecore_x_event_mask_set (efl_get_quickpanel_window (), ECORE_X_EVENT_MASK_WINDOW_PROPERTY);
6743 #ifdef HAVE_NOTIFICATION
6744 show_ime_selector_notification ();
6749 _updated_hide_state_geometry = false;
6751 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
6752 } else if (state == ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF) {
6753 /* WMSYNC, #9 The keyboard window is hidden fully so send HIDE state */
6754 LOGD ("ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF\n");
6755 // For now don't send HIDE signal here
6756 //_info_manager->update_input_panel_event (
6757 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6758 _ise_state = WINDOW_STATE_HIDE;
6760 if (!_updated_hide_state_geometry) {
6761 /* When the ISE gets hidden by the window manager forcefully without OFF_PREPARE,
6762 the application might not have updated its autoscroll area */
6763 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6764 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6765 _info_manager->update_input_panel_event (
6766 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6768 _updated_hide_state_geometry = true;
6770 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
6771 LOGD ("calling ui_candidate_hide (true, false)\n");
6772 ui_candidate_hide (true, false);
6774 ui_settle_candidate_window ();
6778 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_HIDE);
6781 #ifdef HAVE_NOTIFICATION
6782 delete_notification (&ise_selector_module_noti);
6785 _ise_reported_geometry.valid = false;
6787 ecore_x_e_virtual_keyboard_state_set (_ise_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
6789 ui_settle_candidate_window ();
6791 } else if (ev->atom == ECORE_X_ATOM_E_ILLUME_ROTATE_WINDOW_ANGLE) {
6792 if (ev->win == efl_get_quickpanel_window ()) {
6793 int angle = efl_get_quickpanel_window_angle ();
6794 LOGD ("ev->win : %p, change window angle : %d\n", ev->win, angle);
6798 return ECORE_CALLBACK_PASS_ON;
6802 * @brief Callback function for X event client message.
6804 * @param data Data to pass when it is called.
6805 * @param type The event type.
6806 * @param event The information for current message.
6808 * @return ECORE_CALLBACK_RENEW
6810 static Eina_Bool x_event_client_message_cb (void *data, int type, void *event)
6812 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
6814 Ecore_X_Event_Client_Message *ev = (Ecore_X_Event_Client_Message *)event;
6817 return ECORE_CALLBACK_RENEW;
6820 if ((ev->win == _control_window)) {
6821 if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST) {
6822 /* WMSYNC, #4 Send WILL_SHOW event when the keyboard window is about to displayed */
6823 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_ON_PREPARE_REQUEST\n");
6825 /* WMSYNC, #5 Let the Window Manager to actually show keyboard window */
6826 // WILL_SHOW_REQUEST_DONE Ack to WM
6827 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6828 ecore_x_e_virtual_keyboard_on_prepare_done_send (root_window, _control_window);
6829 LOGD ("_ecore_x_e_virtual_keyboard_on_prepare_done_send (%x, %x)\n",
6830 root_window, _control_window);
6832 _info_manager->update_input_panel_event (
6833 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW);
6834 ui_create_candidate_window ();
6836 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_SHOW);
6837 } else if (ev->message_type == ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST) {
6838 _ise_state = WINDOW_STATE_WILL_HIDE;
6839 /* WMSYNC, #7 Send WILL_HIDE event when the keyboard window is about to hidden */
6840 LOGD ("_ECORE_X_ATOM_E_VIRTUAL_KEYBOARD_OFF_PREPARE_REQUEST\n");
6841 // Clear conformant geometry information first
6843 if (_off_prepare_done_timer) {
6844 ecore_timer_del (_off_prepare_done_timer);
6845 _off_prepare_done_timer = NULL;
6847 _off_prepare_done_timer = ecore_timer_add (1.0, off_prepare_done_timeout, NULL);
6849 _ise_reported_geometry.valid = false;
6850 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6851 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6852 _updated_hide_state_geometry = true;
6854 /* If the input panel is getting hidden because of hw keyboard mode while
6855 the candidate window is still opened, it is considered to be an
6856 "input panel being resized" event instead of "input panel being hidden",
6857 since the candidate window will work as an "input panel" afterwards */
6858 bool send_input_panel_hide_event = true;
6859 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_KEYBOARD_MODE) {
6860 LOGD ("_candidate_state : %d", _candidate_state);
6861 if (_candidate_state == WINDOW_STATE_SHOW) {
6862 send_input_panel_hide_event = false;
6865 if (send_input_panel_hide_event) {
6866 _info_manager->update_input_panel_event (
6867 ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
6869 // For now don't send WILL_HIDE signal here
6870 //_info_manager->update_input_panel_event (
6871 // ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_WILL_HIDE);
6872 // Instead send HIDE signal
6873 vconf_set_int (VCONFKEY_ISF_INPUT_PANEL_STATE, VCONFKEY_ISF_INPUT_PANEL_STATE_WILL_HIDE);
6874 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE) {
6875 /* WMSYNC, #10 Register size hints for candidate window and set conformant geometry */
6876 // PRE_ROTATE_DONE Ack to WM
6877 _candidate_angle = ev->data.l[1];
6878 _ise_angle = ev->data.l[1];
6879 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_PREPARE : %d\n", _candidate_angle);
6881 if (_candidate_angle == 90 || _candidate_angle == 270) {
6882 ui_candidate_window_resize (_candidate_land_width, _candidate_land_height_min);
6884 ui_candidate_window_resize (_candidate_port_width, _candidate_port_height_min);
6886 if (_ise_state == WINDOW_STATE_SHOW) {
6887 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6888 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6890 ui_settle_candidate_window ();
6891 ui_candidate_window_rotate (_candidate_angle);
6892 Ecore_X_Window root_window = ecore_x_window_root_get (_control_window);
6893 LOGD ("ecore_x_e_window_rotation_change_prepare_done_send (%d)\n", _candidate_angle);
6894 ecore_x_e_window_rotation_change_prepare_done_send (root_window,
6895 _control_window, _candidate_angle);
6896 } else if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
6897 int ise_angle = (int)ev->data.l[1];
6898 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST for ISE WINDOW : ISE angle : %d, Candidate angle : %d\n", ise_angle, _candidate_angle);
6899 _candidate_angle = ise_angle;
6900 _ise_angle = ise_angle;
6901 if (_ise_state == WINDOW_STATE_SHOW) {
6902 set_keyboard_geometry_atom_info (_app_window, get_ise_geometry ());
6903 _info_manager->update_input_panel_event (ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, 0);
6904 ui_settle_candidate_window ();
6907 } else if (ev->win == elm_win_xwindow_get (_candidate_window)) {
6908 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST || ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE) {
6909 /* WMSYNC, #11 Actual rotate the candidate window */
6910 if (ev->message_type == ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST) {
6911 _candidate_angle = (int)ev->data.l[1];
6912 ui_candidate_window_rotate (_candidate_angle);
6913 LOGD ("ECORE_X_ATOM_E_WINDOW_ROTATION_CHANGE_REQUEST : %d\n", _candidate_angle);
6914 } else if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE &&
6915 _ise_state != WINDOW_STATE_SHOW) {
6916 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_TRUE);
6917 _candidate_angle = (int)ev->data.l[0];
6918 if (_candidate_angle == 90 || _candidate_angle == 270) {
6919 evas_object_resize (_candidate_window, _candidate_land_width, _candidate_land_height_min);
6921 evas_object_resize (_candidate_window, _candidate_port_width, _candidate_port_height_min);
6923 ui_candidate_window_rotate (_candidate_angle);
6924 ui_settle_candidate_window ();
6925 ecore_x_e_window_rotation_app_set (elm_win_xwindow_get (_candidate_window), EINA_FALSE);
6926 LOGD ("ECORE_X_ATOM_E_ILLUME_ROTATE_ROOT_ANGLE : %d\n", _candidate_angle);
6928 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " : ANGLE (" << _candidate_angle << ")\n";
6933 /* Screen reader feature */
6934 if (ev->message_type == ECORE_X_ATOM_E_ILLUME_ACCESS_CONTROL) {
6935 static int last_pos_x = -10000;
6936 static int last_pos_y = -10000;
6938 if (_candidate_window) {
6939 if ((unsigned int)ev->data.l[0] == elm_win_xwindow_get (_candidate_window)) {
6940 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_ACTIVATE) {
6941 // 1 finger double tap
6942 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger double tap focus index = " << _candidate_tts_focus_index << "\n";
6943 ui_mouse_click (_candidate_tts_focus_index);
6944 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ) {
6946 // 1 finger touch & move
6947 last_pos_x = ev->data.l[2];
6948 last_pos_y = ev->data.l[3];
6949 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger touch & move (" << last_pos_x << ", " << last_pos_y << ")\n";
6950 ui_mouse_over (last_pos_x, last_pos_y);
6951 } else if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT ||
6952 (unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_PREV) {
6953 if ((unsigned int)ev->data.l[1] == ECORE_X_ATOM_E_ILLUME_ACCESS_ACTION_READ_NEXT) {
6955 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick right\n";
6956 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_display_number - 1))
6957 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : 0;
6958 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
6959 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
6960 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)(_candidate_row_items[0] - 1))
6961 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
6962 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
6963 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? 0 : _candidate_row_items[0];
6964 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
6965 _candidate_tts_focus_index = _candidate_row_items[0];
6966 else if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < (g_isf_candidate_table.get_current_page_size () - 1))
6967 _candidate_tts_focus_index++;
6968 else if (_candidate_tts_focus_index == (g_isf_candidate_table.get_current_page_size () - 1))
6969 _candidate_tts_focus_index = 0;
6972 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << " 1 finger flick left\n";
6973 if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == 0)
6974 _candidate_tts_focus_index = _candidate_display_number == _candidate_row_items[0] ? MORE_BUTTON_INDEX : _candidate_display_number - 1;
6975 else if (evas_object_visible_get (_more_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
6976 _candidate_tts_focus_index = MORE_BUTTON_INDEX;
6977 else if (evas_object_visible_get (_close_btn) && _candidate_tts_focus_index == (int)_candidate_row_items[0])
6978 _candidate_tts_focus_index = CLOSE_BUTTON_INDEX;
6979 else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX)
6980 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
6981 else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX)
6982 _candidate_tts_focus_index = _candidate_row_items[0] - 1;
6983 else if (_candidate_tts_focus_index > 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ())
6984 _candidate_tts_focus_index--;
6985 else if (_candidate_tts_focus_index == 0)
6986 _candidate_tts_focus_index = g_isf_candidate_table.get_current_page_size () - 1;
6989 int x = 0, y = 0, w = 0, h = 0;
6990 _wait_stop_event = false;
6991 if (candidate_expanded) {
6993 int cursor_line = 0;
6994 for (unsigned int i = 0; i < _candidate_row_items.size (); i++) {
6995 total += _candidate_row_items [i];
6996 if (total > (int)_candidate_display_number && _candidate_tts_focus_index >= total)
7000 elm_scroller_region_get (_candidate_area_2, &x, &y, &w, &h);
7002 int line_h = _item_min_height + _v_padding;
7003 int cursor_y = cursor_line * line_h;
7005 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y, w, h);
7006 _wait_stop_event = true;
7007 } else if (cursor_y >= y + h) {
7008 elm_scroller_region_bring_in (_candidate_area_2, 0, cursor_y + line_h - h, w, h);
7009 _wait_stop_event = true;
7014 String strTts = String ("");
7015 if (_candidate_tts_focus_index >= 0 && _candidate_tts_focus_index < g_isf_candidate_table.get_current_page_size ()) {
7016 strTts = utf8_wcstombs (g_isf_candidate_table.get_candidate_in_current_page (_candidate_tts_focus_index));
7017 if (_candidate_0 [_candidate_tts_focus_index])
7018 evas_object_geometry_get (_candidate_0 [_candidate_tts_focus_index], &x, &y, &w, &h);
7019 } else if (_candidate_tts_focus_index == MORE_BUTTON_INDEX) {
7020 strTts = String (_("more button"));
7021 evas_object_geometry_get (_more_btn, &x, &y, &w, &h);
7022 } else if (_candidate_tts_focus_index == CLOSE_BUTTON_INDEX) {
7023 strTts = String (_("close button"));
7024 evas_object_geometry_get (_close_btn, &x, &y, &w, &h);
7026 LOGW ("TTS focus index = %d\n", _candidate_tts_focus_index);
7027 ui_tts_focus_rect_hide ();
7031 if (strTts.length () > 0)
7032 ui_play_tts (strTts.c_str ());
7034 if (w > 0 && h > 0) {
7035 if (!_wait_stop_event)
7036 ui_tts_focus_rect_show (x, y, w, h);
7038 ui_tts_focus_rect_hide ();
7045 return ECORE_CALLBACK_RENEW;
7049 Eina_Bool check_focus_out_by_popup_win ()
7051 Eina_Bool ret = EINA_FALSE;
7053 Ecore_X_Window focus_win = ecore_x_window_focus_get ();
7054 Ecore_X_Window_Type win_type = ECORE_X_WINDOW_TYPE_UNKNOWN;
7056 if (!ecore_x_netwm_window_type_get (focus_win, &win_type))
7059 LOGD ("win type : %d\n", win_type);
7061 if (win_type == ECORE_X_WINDOW_TYPE_POPUP_MENU ||
7062 win_type == ECORE_X_WINDOW_TYPE_NOTIFICATION) {
7071 * @brief Callback function for focus out event of application window
7073 * @param data Data to pass when it is called.
7075 * @return ECORE_CALLBACK_RENEW
7077 static Eina_Bool x_event_window_focus_out_cb (void *data, int ev_type, void *event)
7079 Ecore_X_Event_Window_Focus_Out *e = (Ecore_X_Event_Window_Focus_Out*)event;
7081 if (e && e->win == _app_window) {
7082 if (_info_manager->get_current_toolbar_mode () == TOOLBAR_HELPER_MODE) {
7083 if (check_focus_out_by_popup_win ())
7084 return ECORE_CALLBACK_RENEW;
7086 #if ENABLE_MULTIWINDOW_SUPPORT
7087 unsigned int layout = 0;
7088 LOGD ("Application window focus OUT!\n");
7089 delete_ise_hide_timer ();
7091 // Check multi window mode
7092 if (ecore_x_window_prop_card32_get (efl_get_app_window (), ECORE_X_ATOM_E_WINDOW_DESKTOP_LAYOUT, &layout, 1) != -1) {
7093 if (layout == 0 || layout == 1) {
7095 LOGD ("Multi window mode. start timer to hide IME\n");
7097 // Use timer not to hide and show IME again in focus-out and focus-in event between applications
7098 _ise_hide_timer = ecore_timer_add (ISF_ISE_HIDE_DELAY, ise_hide_timeout, NULL);
7102 if (!_ise_hide_timer) {
7103 LOGD ("Panel hides ISE\n");
7104 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7106 ui_candidate_hide (true, false, false);
7109 LOGD ("Application window focus OUT! Panel hides ISE\n");
7110 _info_manager->hide_helper (_info_manager->get_current_helper_uuid ());
7112 ui_candidate_hide (true, false, false);
7117 return ECORE_CALLBACK_RENEW;
7122 * @brief : Launches default soft keyboard for performance enhancement (It's not mandatory)
7124 static void launch_default_soft_keyboard (keynode_t *key, void* data)
7126 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
7128 /* Start default ISE */
7129 change_keyboard_mode (TOOLBAR_HELPER_MODE);
7132 static String sanitize_string (const char *str, int maxlen = 32)
7135 static char acceptables[] =
7136 "abcdefghijklmnopqrstuvwxyz"
7137 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
7140 char *newstr = NULL;
7142 newstr = new char[maxlen + 1];
7146 memset (newstr, 0x00, sizeof (char) * (maxlen + 1));
7149 while (len < maxlen && str[len] != '\0' && strchr (acceptables, str[len]) != NULL) {
7150 newstr[len] = str[len];
7160 int main (int argc, char *argv [])
7162 struct tms tiks_buf;
7163 _clock_start = times (&tiks_buf);
7168 bool daemon = false;
7169 bool should_resident = true;
7172 char **new_argv = new char * [40];
7173 int display_name_c = 0;
7174 ConfigModule *config_module = NULL;
7175 String config_name = String ("simple");
7176 String display_name = String ();
7177 char buf[256] = {0};
7178 char *lang_str = NULL;
7181 Ecore_Event_Handler *xclient_message_handler = NULL;
7182 Ecore_Event_Handler *xwindow_property_handler = NULL;
7183 Ecore_Event_Handler *xwindow_focus_out_handler = NULL;
7186 check_time ("\nStarting ISF Panel EFL...... ");
7187 ISF_SAVE_LOG ("Starting ISF Panel EFL......\n");
7189 DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
7190 DebugOutput::enable_debug (SCIM_DEBUG_MainMask);
7192 /* Parse command options */
7198 if (String ("-c") == argv [i] || String ("--config") == argv [i]) {
7200 std::cerr << "no argument for option " << argv [i-1] << "\n";
7204 config_name = argv [i];
7208 if (String ("-h") == argv [i] || String ("--help") == argv [i]) {
7209 std::cout << "Usage: " << argv [0] << " [option]...\n\n"
7210 << "The options are: \n"
7211 << " --display DISPLAY Run on display DISPLAY.\n"
7212 << " -c, --config NAME Uses specified Config module.\n"
7213 << " -d, --daemon Run " << argv [0] << " as a daemon.\n"
7214 << " -ns, --no-stay Quit if no connected client.\n"
7216 << " -v, --verbose LEVEL Enable debug info, to specific LEVEL.\n"
7217 << " -o, --output FILE Output debug information into FILE.\n"
7219 << " -h, --help Show this help message.\n";
7224 if (String ("-d") == argv [i] || String ("--daemon") == argv [i]) {
7229 if (String ("-ns") == argv [i] || String ("--no-stay") == argv [i]) {
7230 should_resident = false;
7234 if (String ("-v") == argv [i] || String ("--verbose") == argv [i]) {
7236 std::cerr << "no argument for option " << argv [i-1] << "\n";
7240 DebugOutput::set_verbose_level (atoi (argv [i]));
7244 if (String ("-o") == argv [i] || String ("--output") == argv [i]) {
7246 std::cerr << "No argument for option " << argv [i-1] << "\n";
7250 DebugOutput::set_output (argv [i]);
7254 if (String ("--display") == argv [i]) {
7256 std::cerr << "No argument for option " << argv [i-1] << "\n";
7260 display_name = sanitize_string (argv [i]);
7264 if (String ("--") == argv [i])
7267 std::cerr << "Invalid command line option: " << argv [i] << "\n";
7270 } /* End of command line parsing. */
7273 new_argv [new_argc ++] = argv [0];
7275 /* Store the rest argvs into new_argv. */
7276 for (++i; i < argc && new_argc < 37; ++i) {
7277 new_argv [new_argc ++] = argv [i];
7280 /* Make up DISPLAY env. */
7281 if (display_name.length ()) {
7282 new_argv [new_argc ++] = const_cast <char*> ("--display");
7283 display_name_c = new_argc;
7284 new_argv [new_argc ++] = strdup (display_name.c_str ());
7286 setenv ("DISPLAY", display_name.c_str (), 1);
7289 new_argv [new_argc] = 0;
7292 if (!config_name.length ()) {
7293 std::cerr << "No Config module is available!\n";
7298 /* Get current display. */
7300 const char *p = getenv ("DISPLAY");
7302 display_name = String (p);
7305 snprintf (buf, sizeof (buf), "config_name=%s display_name=%s", config_name.c_str (), display_name.c_str ());
7309 check_time ("ISF Panel EFL run as daemon");
7313 /* No loading default theme to reduce heap memory */
7314 setenv ("ELM_THEME", "", 1);
7316 #if ISF_BUILD_CANDIDATE_UI
7317 elm_init (argc, argv);
7320 ecore_app_args_set(argc, (const char **)argv);
7321 #endif /* CANDIDATE */
7323 check_time ("elm_init");
7327 #if ISF_BUILD_CANDIDATE_UI
7328 elm_policy_set (ELM_POLICY_THROTTLE, ELM_POLICY_THROTTLE_NEVER);
7329 #endif /* CANDIDATE */
7331 if (config_name != "dummy") {
7332 /* Load config module */
7333 config_module = new ConfigModule (config_name);
7335 if (!config_module || !config_module->valid ()) {
7336 std::cerr << "Can not load " << config_name << " Config module.\n";
7341 _config = new DummyConfig ();
7344 /* Create config instance */
7345 if (_config.null () && config_module && config_module->valid ())
7346 _config = config_module->create_config ();
7347 if (_config.null ()) {
7348 std::cerr << "Failed to create Config instance from " << config_name << " Config module.\n";
7352 ConfigBase::set (_config);
7353 check_time ("create config instance");
7356 if (!initialize_panel_agent (_config, display_name, should_resident)) {
7357 check_time ("Failed to initialize Panel Agent!");
7358 std::cerr << "Failed to initialize Panel Agent!\n";
7359 LOGE ("Failed to initialize Panel Agent!\n");
7363 } catch (scim::Exception & e) {
7364 std::cerr << e.what () << "\n";
7369 check_time ("initialize_panel_agent");
7371 #if ISF_BUILD_CANDIDATE_UI
7372 /* Initialize global variables and pointers for candidate items and etc. */
7373 for (i = 0; i < SCIM_LOOKUP_TABLE_MAX_PAGESIZE; i++) {
7374 _candidate_0 [i] = NULL;
7375 _seperate_0 [i] = NULL;
7376 _seperate_items [i] = NULL;
7378 _line_items [i] = NULL;
7379 _candidate_text [i] = NULL;
7380 _candidate_image [i] = NULL;
7381 _candidate_pop_image [i] = NULL;
7383 #endif /* CANDIDATE */
7385 /* Connect the configuration reload signal. */
7386 _config_connection = _config->signal_connect_reload (slot (config_reload_cb));
7389 if (!efl_create_control_window ()) {
7390 LOGW ("Failed to create control window\n");
7395 #if ISF_BUILD_CANDIDATE_UI
7396 efl_get_screen_resolution (_screen_width, _screen_height);
7398 _width_rate = (float)(_screen_width / 720.0);
7399 _height_rate = (float)(_screen_height / 1280.0);
7400 _blank_width = (int)(_blank_width * _width_rate);
7401 _item_min_width = (int)(_item_min_width * _width_rate);
7402 _item_min_height = (int)(_item_min_height * _height_rate);
7403 _candidate_width = (int)(_candidate_port_width * _width_rate);
7404 _candidate_height = (int)(_candidate_port_height_min * _height_rate);
7405 _indicator_height = (int)(_indicator_height * _height_rate);
7407 _aux_font_size = (int)(_aux_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7408 _candidate_font_size = (int)(_candidate_font_size * (_width_rate < _height_rate ? _width_rate : _height_rate));
7409 #endif /* CANDIDATE */
7411 /* Load ISF configuration */
7413 check_time ("load_config");
7416 lang_str = vconf_get_str (VCONFKEY_LANGSET);
7417 set_language_and_locale (lang_str);
7421 /* Add callback function for input language and display language */
7422 vconf_notify_key_changed (VCONFKEY_LANGSET, display_language_changed_cb, NULL);
7423 vconf_notify_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb, NULL);
7426 if (0 != register_edbus_signal_handler ())
7427 LOGW ("register edbus signal fail\n");
7430 /* Update ISE list */
7431 std::vector<String> list;
7432 update_ise_list (list);
7434 /* Load initial ISE information */
7435 _initial_ise_uuid = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_INITIAL_ISE_UUID), String (SCIM_COMPOSE_KEY_FACTORY_UUID));
7437 /* Check if SCIM_CONFIG_DEFAULT_HELPER_ISE is available. If it's not, set it as _initial_ise_uuid.
7438 e.g., This might be necessary when the platform is upgraded from 2.3 to 2.4. */
7439 String helper_uuid = _config->read (SCIM_CONFIG_DEFAULT_HELPER_ISE, String (""));
7440 if (helper_uuid.length() > 0 && _initial_ise_uuid.length() > 0 && helper_uuid != _initial_ise_uuid) {
7442 for (unsigned int u = 0; u < _ime_info.size (); u++) {
7443 if (_ime_info[u].mode == TOOLBAR_HELPER_MODE && helper_uuid == _ime_info[u].appid) {
7449 _config->write (String (SCIM_CONFIG_DEFAULT_HELPER_ISE), _initial_ise_uuid);
7453 /* Launches default soft keyboard when all conditions are satisfied */
7454 launch_default_soft_keyboard ();
7456 /* Update the name of each ISE according to display language */
7457 update_ise_locale ();
7458 } catch (scim::Exception & e) {
7459 std::cerr << e.what () << "\n";
7460 } catch (std::logic_error & e) {
7461 std::cerr << e.what () << "\n";
7464 xclient_message_handler = ecore_event_handler_add (ECORE_X_EVENT_CLIENT_MESSAGE, x_event_client_message_cb, NULL);
7465 xwindow_property_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, x_event_window_property_cb, NULL);
7466 xwindow_focus_out_handler = ecore_event_handler_add (ECORE_X_EVENT_WINDOW_FOCUS_OUT, x_event_window_focus_out_cb, NULL);
7469 #ifdef HAVE_BLUETOOTH
7470 /* Register the callback function of Bluetooth connection */
7471 ret = bt_initialize ();
7472 if (ret != BT_ERROR_NONE)
7473 LOGW ("Fail to init Bluetooth\n");
7475 ret = bt_hid_host_initialize (_bt_cb_hid_state_changed, NULL);
7476 if (ret != BT_ERROR_NONE)
7477 LOGW ("bt_hid_host_initialize failed\n");
7480 #if ENABLE_REMOTE_INPUT
7481 launch_remote_input = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_REMOTE_INPUT), launch_remote_input);
7483 /* Create remote input */
7484 if (launch_remote_input) {
7485 LOGD("remote input start");
7486 remote_input_impl = new Remote_Input();
7487 if (remote_input_impl) {
7488 remote_input_impl->init(_info_manager);
7493 #if ISF_BUILD_CANDIDATE_UI
7494 _system_scale = elm_config_scale_get ();
7496 /* Set elementary scale */
7497 if (_screen_width) {
7498 _app_scale = _screen_width / 720.0;
7499 elm_config_scale_set (_app_scale);
7501 snprintf (buf, sizeof (buf), "%4.3f", _app_scale);
7502 setenv ("ELM_SCALE", buf, 1);
7504 #endif /* CANDIDATE */
7506 signal (SIGQUIT, signalhandler);
7507 signal (SIGTERM, signalhandler);
7508 signal (SIGINT, signalhandler);
7509 signal (SIGHUP, signalhandler);
7511 check_time ("EFL Panel launch time");
7513 if (!isf_cynara_initialize())
7514 LOGW ("Failed to initialize cynara\n");
7516 #if ISF_BUILD_CANDIDATE_UI
7519 ecore_main_loop_begin ();
7520 #endif /* CANDIDATE */
7522 LOGW("out of loop");
7524 isf_cynara_finish();
7529 #ifdef HAVE_BLUETOOTH
7530 /* deinitialize the callback function of Bluetooth connection */
7531 ret = bt_hid_host_deinitialize ();
7532 if (ret != BT_ERROR_NONE)
7533 LOGW ("bt_hid_host_deinitialize failed: %d\n", ret);
7535 ret = bt_deinitialize ();
7536 if (ret != BT_ERROR_NONE)
7537 LOGW ("bt_deinitialize failed: %d\n", ret);
7541 if (xclient_message_handler) {
7542 ecore_event_handler_del (xclient_message_handler);
7543 xclient_message_handler = NULL;
7546 if (xwindow_property_handler) {
7547 ecore_event_handler_del (xwindow_property_handler);
7548 xwindow_property_handler = NULL;
7551 if (xwindow_focus_out_handler) {
7552 ecore_event_handler_del (xwindow_focus_out_handler);
7553 xwindow_focus_out_handler = NULL;
7558 /* Remove callback function for input language and display language */
7559 vconf_ignore_key_changed (VCONFKEY_LANGSET, display_language_changed_cb);
7560 vconf_ignore_key_changed (VCONFKEY_ISF_HW_KEYBOARD_INPUT_DETECTED, keyboard_mode_changed_cb);
7564 #if ISF_BUILD_CANDIDATE_UI
7565 ui_destroy_candidate_window ();
7566 ui_candidate_delete_check_size_timer ();
7567 ui_candidate_delete_longpress_timer ();
7568 ui_candidate_delete_destroy_timer ();
7569 #endif /* CANDIDATE */
7570 #ifdef HAVE_PKGMGR_INFO
7572 package_manager_destroy (pkgmgr);
7581 unregister_edbus_signal_handler ();
7583 if (_info_manager) {
7585 _info_manager->stop ();
7586 } catch (scim::Exception & e) {
7587 std::cerr << "Exception is thrown from _info_manager->stop (), error is " << e.what () << "\n";
7589 delete _info_manager;
7591 _config_connection.disconnect ();
7592 if (!_config.null ())
7594 ConfigBase::set (0);
7597 delete config_module;
7599 #if ISF_BUILD_CANDIDATE_UI
7603 #endif /* CANDIDATE */
7606 if ((display_name_c > 0) && new_argv [display_name_c]) {
7607 free (new_argv [display_name_c]);
7612 ISF_SAVE_LOG ("ret=%d\n", ret);
7614 std::cerr << "Successfully exited.\n";
7617 std::cerr << "Abnormally exited.\n";
7623 vi:ts=4:nowrap:expandtab