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-2013 Samsung Electronics Co., Ltd.
7 * Contact: Jihoon Kim <jihoon48.kim@samsung.com>, Haifeng Deng <haifeng.deng@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_BACKEND
26 #define Uses_SCIM_IMENGINE_MODULE
27 #define Uses_SCIM_HELPER_MODULE
28 #define Uses_SCIM_HOTKEY
29 #define Uses_SCIM_PANEL_CLIENT
31 #include <sys/types.h>
34 #include <sys/times.h>
39 #include <Ecore_Evas.h>
41 #include <X11/XKBlib.h>
42 #include <X11/keysym.h>
43 #include <X11/Xutil.h>
47 #include <vconf-keys.h>
48 #include <notification.h>
50 #include "scim_private.h"
52 #include "isf_imf_context.h"
53 #include "isf_imf_control_ui.h"
56 # define CODESET "INVALID"
59 #define ENABLE_BACKKEY 1
63 struct _EcoreIMFContextISFImpl {
64 EcoreIMFContextISF *parent;
65 IMEngineInstancePointer si;
66 Ecore_X_Window client_window;
68 Ecore_IMF_Input_Mode input_mode;
69 WideString preedit_string;
70 AttributeList preedit_attrlist;
71 Ecore_IMF_Autocapital_Type autocapital_type;
83 bool preedit_updating;
84 bool need_commit_preedit;
86 bool prediction_allow;
88 EcoreIMFContextISFImpl *next;
91 /* Input Context handling functions. */
92 static EcoreIMFContextISFImpl *new_ic_impl (EcoreIMFContextISF *parent);
93 static void delete_ic_impl (EcoreIMFContextISFImpl *impl);
94 static void delete_all_ic_impl (void);
96 static EcoreIMFContextISF *find_ic (int id);
99 /* private functions */
100 static void panel_slot_reload_config (int context);
101 static void panel_slot_exit (int context);
102 static void panel_slot_update_candidate_item_layout (int context,
103 const std::vector<uint32> &row_items);
104 static void panel_slot_update_lookup_table_page_size(int context,
106 static void panel_slot_lookup_table_page_up (int context);
107 static void panel_slot_lookup_table_page_down (int context);
108 static void panel_slot_trigger_property (int context,
109 const String &property);
110 static void panel_slot_process_helper_event (int context,
111 const String &target_uuid,
112 const String &helper_uuid,
113 const Transaction &trans);
114 static void panel_slot_move_preedit_caret (int context,
116 static void panel_slot_update_preedit_caret (int context,
118 static void panel_slot_select_aux (int context,
120 static void panel_slot_select_candidate (int context,
122 static void panel_slot_process_key_event (int context,
123 const KeyEvent &key);
124 static void panel_slot_commit_string (int context,
125 const WideString &wstr);
126 static void panel_slot_forward_key_event (int context,
127 const KeyEvent &key);
128 static void panel_slot_request_help (int context);
129 static void panel_slot_request_factory_menu (int context);
130 static void panel_slot_change_factory (int context,
132 static void panel_slot_reset_keyboard_ise (int context);
133 static void panel_slot_update_keyboard_ise (int context);
134 static void panel_slot_show_preedit_string (int context);
135 static void panel_slot_hide_preedit_string (int context);
136 static void panel_slot_update_preedit_string (int context,
137 const WideString &str,
138 const AttributeList &attrs);
139 static void panel_slot_get_surrounding_text (int context,
142 static void panel_slot_delete_surrounding_text (int context,
146 static void panel_req_focus_in (EcoreIMFContextISF *ic);
147 static void panel_req_update_factory_info (EcoreIMFContextISF *ic);
148 static void panel_req_update_spot_location (EcoreIMFContextISF *ic);
149 static void panel_req_update_cursor_position (EcoreIMFContextISF *ic, int cursor_pos);
150 static void panel_req_show_help (EcoreIMFContextISF *ic);
151 static void panel_req_show_factory_menu (EcoreIMFContextISF *ic);
153 /* Panel iochannel handler*/
154 static bool panel_initialize (void);
155 static void panel_finalize (void);
156 static Eina_Bool panel_iochannel_handler (void *data,
157 Ecore_Fd_Handler *fd_handler);
159 /* utility functions */
160 static bool filter_hotkeys (EcoreIMFContextISF *ic,
161 const KeyEvent &key);
162 static void turn_on_ic (EcoreIMFContextISF *ic);
163 static void turn_off_ic (EcoreIMFContextISF *ic);
164 static void set_ic_capabilities (EcoreIMFContextISF *ic);
166 static void initialize (void);
167 static void finalize (void);
169 static void open_next_factory (EcoreIMFContextISF *ic);
170 static void open_previous_factory (EcoreIMFContextISF *ic);
171 static void open_specific_factory (EcoreIMFContextISF *ic,
173 static void initialize_modifier_bits (Display *display);
174 static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask);
175 static XKeyEvent createKeyEvent (bool press, int keycode, int modifiers, bool fake);
176 static void send_x_key_event (const KeyEvent &key, bool fake);
178 static void attach_instance (const IMEngineInstancePointer &si);
181 static void slot_show_preedit_string (IMEngineInstanceBase *si);
182 static void slot_show_aux_string (IMEngineInstanceBase *si);
183 static void slot_show_lookup_table (IMEngineInstanceBase *si);
185 static void slot_hide_preedit_string (IMEngineInstanceBase *si);
186 static void slot_hide_aux_string (IMEngineInstanceBase *si);
187 static void slot_hide_lookup_table (IMEngineInstanceBase *si);
189 static void slot_update_preedit_caret (IMEngineInstanceBase *si,
191 static void slot_update_preedit_string (IMEngineInstanceBase *si,
192 const WideString &str,
193 const AttributeList &attrs);
194 static void slot_update_aux_string (IMEngineInstanceBase *si,
195 const WideString &str,
196 const AttributeList &attrs);
197 static void slot_commit_string (IMEngineInstanceBase *si,
198 const WideString &str);
199 static void slot_forward_key_event (IMEngineInstanceBase *si,
200 const KeyEvent &key);
201 static void slot_update_lookup_table (IMEngineInstanceBase *si,
202 const LookupTable &table);
204 static void slot_register_properties (IMEngineInstanceBase *si,
205 const PropertyList &properties);
206 static void slot_update_property (IMEngineInstanceBase *si,
207 const Property &property);
208 static void slot_beep (IMEngineInstanceBase *si);
209 static void slot_start_helper (IMEngineInstanceBase *si,
210 const String &helper_uuid);
211 static void slot_stop_helper (IMEngineInstanceBase *si,
212 const String &helper_uuid);
213 static void slot_send_helper_event (IMEngineInstanceBase *si,
214 const String &helper_uuid,
215 const Transaction &trans);
216 static bool slot_get_surrounding_text (IMEngineInstanceBase *si,
221 static bool slot_delete_surrounding_text (IMEngineInstanceBase *si,
225 static void slot_expand_candidate (IMEngineInstanceBase *si);
226 static void slot_contract_candidate (IMEngineInstanceBase *si);
228 static void slot_set_candidate_style (IMEngineInstanceBase *si,
229 ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line,
230 ISF_CANDIDATE_MODE_T mode);
232 static void reload_config_callback (const ConfigPointer &config);
234 static void fallback_commit_string_cb (IMEngineInstanceBase *si,
235 const WideString &str);
236 static void _display_input_language (EcoreIMFContextISF *ic);
238 /* Local variables declaration */
239 static String _language;
240 static EcoreIMFContextISFImpl *_used_ic_impl_list = 0;
241 static EcoreIMFContextISFImpl *_free_ic_impl_list = 0;
242 static EcoreIMFContextISF *_ic_list = 0;
244 static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
245 static int _valid_key_mask = SCIM_KEY_AllMasks;
247 static FrontEndHotkeyMatcher _frontend_hotkey_matcher;
248 static IMEngineHotkeyMatcher _imengine_hotkey_matcher;
250 static IMEngineInstancePointer _default_instance;
252 static ConfigModule *_config_module = 0;
253 static ConfigPointer _config;
254 static BackEndPointer _backend;
256 static EcoreIMFContextISF *_focused_ic = 0;
258 static bool _scim_initialized = false;
260 static int _instance_count = 0;
261 static int _context_count = 0;
263 static IMEngineFactoryPointer _fallback_factory;
264 static IMEngineInstancePointer _fallback_instance;
265 static PanelClient _panel_client;
266 static int _panel_client_id = 0;
268 static Ecore_Fd_Handler *_panel_iochannel_read_handler = 0;
269 static Ecore_Fd_Handler *_panel_iochannel_err_handler = 0;
271 static Ecore_X_Window _client_window = 0;
272 static Ecore_Event_Handler *_key_down_handler = 0;
273 static Ecore_Event_Handler *_key_up_handler = 0;
275 static bool _on_the_spot = true;
276 static bool _shared_input_method = false;
277 static double space_key_time = 0.0;
279 static Eina_Bool autoperiod_allow = EINA_FALSE;
280 static Eina_Bool autocap_allow = EINA_FALSE;
281 static Eina_Bool desktop_mode = EINA_FALSE;
283 static Display *__current_display = 0;
284 static int __current_alt_mask = Mod1Mask;
285 static int __current_meta_mask = 0;
286 static int __current_super_mask = 0;
287 static int __current_hyper_mask = 0;
288 static int __current_numlock_mask = Mod2Mask;
290 extern Ecore_IMF_Context *input_panel_ctx;
292 // A hack to shutdown the immodule cleanly even if im_module_exit () is not called when exiting.
293 class FinalizeHandler
297 SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::FinalizeHandler ()\n";
299 ~FinalizeHandler () {
300 SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::~FinalizeHandler ()\n";
305 static FinalizeHandler _finalize_handler;
307 EAPI ConfigPointer isf_imf_context_get_config (void)
312 EAPI EcoreIMFContextISF *
319 get_panel_client_id (void)
321 return _panel_client_id;
335 struct timezone tz; /* is not used since ages */
336 gettimeofday (&tv, &tz);
337 tint = tv.tv_sec * 1000;
338 tint = tint / 1000 * 1000;
339 tint = tint + tv.tv_usec / 1000;
343 /* Function Implementations */
344 static EcoreIMFContextISFImpl *
345 new_ic_impl (EcoreIMFContextISF *parent)
347 EcoreIMFContextISFImpl *impl = NULL;
349 if (_free_ic_impl_list != NULL) {
350 impl = _free_ic_impl_list;
351 _free_ic_impl_list = _free_ic_impl_list->next;
353 impl = new EcoreIMFContextISFImpl;
358 impl->uppercase = false;
359 impl->autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
360 impl->next = _used_ic_impl_list;
361 _used_ic_impl_list = impl;
363 impl->parent = parent;
365 impl->imdata_size = 0;
371 delete_ic_impl (EcoreIMFContextISFImpl *impl)
373 EcoreIMFContextISFImpl *rec = _used_ic_impl_list, *last = 0;
375 for (; rec != 0; last = rec, rec = rec->next) {
378 last->next = rec->next;
380 _used_ic_impl_list = rec->next;
382 rec->next = _free_ic_impl_list;
383 _free_ic_impl_list = rec;
390 rec->imdata_size = 0;
393 rec->client_window = 0;
394 rec->preedit_string = WideString ();
395 rec->preedit_attrlist.clear ();
403 delete_all_ic_impl (void)
405 EcoreIMFContextISFImpl *it = _used_ic_impl_list;
408 _used_ic_impl_list = it->next;
410 it = _used_ic_impl_list;
413 it = _free_ic_impl_list;
415 _free_ic_impl_list = it->next;
417 it = _free_ic_impl_list;
421 static EcoreIMFContextISF *
424 EcoreIMFContextISFImpl *rec = _used_ic_impl_list;
427 if (rec->parent && rec->parent->id == id)
436 _key_down_cb (void *data, int type, void *event)
438 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
440 Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event;
441 if (!ev || !_focused_ic || !_focused_ic->ctx) return ECORE_CALLBACK_RENEW;
443 if (!strcmp (ev->keyname, KEY_END) &&
444 ecore_imf_context_input_panel_state_get (_focused_ic->ctx) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
445 LOGD ("END key is pressed\n");
446 return ECORE_CALLBACK_CANCEL;
449 return ECORE_CALLBACK_RENEW;
453 _key_up_cb (void *data, int type, void *event)
455 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
457 Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event;
458 if (!ev || !_focused_ic || !_focused_ic->ctx) return ECORE_CALLBACK_RENEW;
460 if (!strcmp (ev->keyname, KEY_END) &&
461 ecore_imf_context_input_panel_state_get (_focused_ic->ctx) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
462 LOGD ("END key is released\n");
463 isf_imf_context_input_panel_instant_hide (_focused_ic->ctx);
464 return ECORE_CALLBACK_CANCEL;
467 return ECORE_CALLBACK_RENEW;
471 _check_desktop_mode (Ecore_X_Window win)
473 char *profile = ecore_x_e_window_profile_get (win);
474 if (profile && (strcmp (profile, "desktop") == 0)) {
475 desktop_mode = EINA_TRUE;
477 desktop_mode = EINA_FALSE;
485 _x_prop_change (void *data, int type, void *event)
487 Ecore_X_Event_Window_Property *e = (Ecore_X_Event_Window_Property *)event;
488 Ecore_X_Window xwin = (Ecore_X_Window)data;
490 if (e->win != xwin) return ECORE_CALLBACK_PASS_ON;
492 if (e->atom == ECORE_X_ATOM_E_PROFILE) {
493 _check_desktop_mode (e->win);
496 return ECORE_CALLBACK_PASS_ON;
500 register_key_handler ()
502 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
504 #ifdef ENABLE_BACKKEY
505 if (!_key_down_handler)
506 _key_down_handler = ecore_event_handler_add (ECORE_EVENT_KEY_DOWN, _key_down_cb, NULL);
508 if (!_key_up_handler)
509 _key_up_handler = ecore_event_handler_add (ECORE_EVENT_KEY_UP, _key_up_cb, NULL);
516 unregister_key_handler ()
518 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
520 if (_key_down_handler) {
521 ecore_event_handler_del (_key_down_handler);
522 _key_down_handler = NULL;
525 if (_key_up_handler) {
526 ecore_event_handler_del (_key_up_handler);
527 _key_up_handler = NULL;
534 set_prediction_allow (IMEngineInstancePointer si, bool prediction)
536 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
539 si->set_prediction_allow (prediction);
543 autoperiod_insert (Ecore_IMF_Context *ctx)
545 char *plain_str = NULL;
546 char *markup_str = NULL;
548 Eina_Unicode *ustr = NULL;
549 Ecore_IMF_Event_Delete_Surrounding ev;
553 Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
554 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
557 if (autoperiod_allow == EINA_FALSE)
560 if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
563 ecore_imf_context_surrounding_get (ctx, &markup_str, &cursor_pos);
564 if (!markup_str) goto done;
566 // Convert into plain string
567 plain_str = evas_textblock_text_markup_to_utf8 (NULL, markup_str);
568 if (!plain_str) goto done;
570 // Convert string from UTF-8 to unicode
571 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
572 if (!ustr) goto done;
574 if (cursor_pos < 2) goto done;
576 if (((ustr[cursor_pos-2] != ':') && (ustr[cursor_pos-2] != ';') &&
577 (ustr[cursor_pos-2] != '.') && (ustr[cursor_pos-2] != ',') &&
578 (ustr[cursor_pos-2] != '?') && (ustr[cursor_pos-2] != '!') &&
579 (ustr[cursor_pos-2] != ' ')) && ((ustr[cursor_pos-1] == ' ') || (ustr[cursor_pos-1] == '\240'))) {
583 ecore_imf_context_delete_surrounding_event_add (ctx, -1, 1);
584 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
586 ecore_imf_context_commit_event_add (ctx, ".");
587 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)".");
591 if (markup_str) free (markup_str);
592 if (plain_str) free (plain_str);
593 if (ustr) free (ustr);
594 space_key_time = ecore_time_get ();
598 analyze_surrounding_text (Ecore_IMF_Context *ctx)
600 char *plain_str = NULL;
601 char *markup_str = NULL;
602 const char *puncs[] = {". ", ".\302\240", "! ", "!\302\240", "? ", "?\302\240", "¿ ", "¿\302\240", "¡ ", "¡\302\240" };
603 Eina_Bool ret = EINA_FALSE;
606 Eina_Unicode *tail = NULL;
607 Eina_Unicode *ustr = NULL;
608 const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
609 Eina_Unicode *uni_puncs[punc_num];
610 EcoreIMFContextISF *context_scim;
612 if (!ctx) return EINA_FALSE;
613 context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
614 if (!context_scim || !context_scim->impl) return EINA_FALSE;
616 switch (context_scim->impl->autocapital_type) {
617 case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
619 case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
625 if (context_scim->impl->cursor_pos == 0)
628 for (i = 0; i < punc_num; i++) {
629 uni_puncs[i] = eina_unicode_utf8_to_unicode (puncs[i], NULL);
632 ecore_imf_context_surrounding_get (ctx, &markup_str, &cursor_pos);
633 if (!markup_str) goto done;
635 if (cursor_pos == 0) {
640 // Convert into plain string
641 plain_str = evas_textblock_text_markup_to_utf8 (NULL, markup_str);
642 if (!plain_str) goto done;
644 // Convert string from UTF-8 to unicode
645 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
646 if (!ustr) goto done;
648 if (cursor_pos >= 1) {
649 if (context_scim->impl->autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
650 if (ustr[cursor_pos-1] == ' ' || ustr[cursor_pos-1] == '\302\240') {
656 // Check paragraph separator <PS> and carriage return <br>
657 if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
664 if (cursor_pos >= 2) {
665 tail = eina_unicode_strndup (ustr+cursor_pos-2, 2);
668 for (i = 0; i < punc_num; i++) {
669 if (!eina_unicode_strcmp (tail, uni_puncs[i])) {
680 if (ustr) free (ustr);
681 if (markup_str) free (markup_str);
682 if (plain_str) free (plain_str);
684 for (i = 0; i < punc_num; i++) {
685 if (uni_puncs[i]) free (uni_puncs[i]);
692 caps_mode_check (Ecore_IMF_Context *ctx, Eina_Bool force, Eina_Bool noti)
695 EcoreIMFContextISF *context_scim;
697 if (!ctx) return EINA_FALSE;
698 context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
700 Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
701 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
704 // Check autocapital type
705 if (!context_scim || !context_scim->impl)
708 if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
709 uppercase = EINA_TRUE;
711 if (autocap_allow == EINA_FALSE)
714 if (analyze_surrounding_text (ctx)) {
715 uppercase = EINA_TRUE;
717 uppercase = EINA_FALSE;
722 context_scim->impl->uppercase = uppercase;
724 isf_imf_context_input_panel_caps_mode_set (ctx, uppercase);
726 if (context_scim->impl->uppercase != uppercase) {
727 context_scim->impl->uppercase = uppercase;
729 isf_imf_context_input_panel_caps_mode_set (ctx, uppercase);
737 window_to_screen_geometry_get (Ecore_X_Window client_win, int *x, int *y)
739 Ecore_X_Window root_window, win;
741 int sum_x = 0, sum_y = 0;
743 root_window = ecore_x_window_root_get (client_win);
746 while (root_window != win) {
747 ecore_x_window_geometry_get (win, &win_x, &win_y, NULL, NULL);
750 win = ecore_x_window_parent_get (win);
760 evas_focus_out_cb (void *data, Evas *e, void *event_info)
762 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
766 LOGD ("ctx : %p\n", ctx);
768 if (input_panel_ctx == ctx && _scim_initialized) {
769 isf_imf_context_input_panel_instant_hide (ctx);
773 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
775 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
777 autoperiod_allow = vconf_keynode_get_bool (key);
780 static void autocapital_allow_changed_cb (keynode_t *key, void* data)
782 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
784 autocap_allow = vconf_keynode_get_bool (key);
787 EAPI void context_scim_imdata_get (Ecore_IMF_Context *ctx, void* data, int* length)
789 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
791 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
793 if (data && context_scim->impl->imdata)
794 memcpy (data, context_scim->impl->imdata, context_scim->impl->imdata_size);
796 *length = context_scim->impl->imdata_size;
799 /* Public functions */
801 * isf_imf_context_new
803 * This function will be called by Ecore IMF.
804 * Create a instance of type EcoreIMFContextISF.
806 * Return value: A pointer to the newly created EcoreIMFContextISF instance
808 EAPI EcoreIMFContextISF *
809 isf_imf_context_new (void)
811 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
815 EcoreIMFContextISF *context_scim = new EcoreIMFContextISF;
816 if (context_scim == NULL) {
817 std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
821 if (_context_count == 0) {
822 _context_count = getpid () % 50000;
824 context_scim->id = _context_count++;
826 if (!_scim_initialized) {
828 _scim_initialized = true;
829 isf_imf_input_panel_init ();
831 /* get autoperiod allow vconf value */
832 if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
833 if (val == EINA_TRUE)
834 autoperiod_allow = EINA_TRUE;
837 vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
839 /* get autocapital allow vconf value */
840 if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
841 if (val == EINA_TRUE)
842 autocap_allow = EINA_TRUE;
845 vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
852 * isf_imf_context_shutdown
854 * It will be called when the scim im module is unloaded by ecore. It will do some
858 isf_imf_context_shutdown (void)
860 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
862 if (_scim_initialized) {
863 _scim_initialized = false;
865 LOGD ("immodule shutdown\n");
867 vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
868 vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
870 isf_imf_input_panel_shutdown ();
876 isf_imf_context_add (Ecore_IMF_Context *ctx)
878 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
880 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
882 if (!context_scim) return;
884 context_scim->impl = NULL;
886 if (_backend.null ())
889 IMEngineInstancePointer si;
891 // Use the default instance if "shared input method" mode is enabled.
892 if (_shared_input_method && !_default_instance.null ()) {
893 si = _default_instance;
894 SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
897 // Not in "shared input method" mode, or no default instance, create an instance.
899 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
900 if (factory.null ()) return;
901 si = factory->create_instance ("UTF-8", _instance_count++);
902 if (si.null ()) return;
903 attach_instance (si);
904 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
907 // If "shared input method" mode is enabled, and there is no default instance,
908 // then store this instance as default one.
909 if (_shared_input_method && _default_instance.null ()) {
910 SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
911 _default_instance = si;
914 context_scim->ctx = ctx;
915 context_scim->impl = new_ic_impl (context_scim);
916 if (context_scim->impl == NULL) {
917 std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
921 context_scim->impl->si = si;
922 context_scim->impl->client_window = 0;
923 context_scim->impl->client_canvas = NULL;
924 context_scim->impl->preedit_caret = 0;
925 context_scim->impl->cursor_x = 0;
926 context_scim->impl->cursor_y = 0;
927 context_scim->impl->cursor_pos = -1;
928 context_scim->impl->cursor_top_y = 0;
929 context_scim->impl->is_on = true;
930 context_scim->impl->shared_si = _shared_input_method;
931 context_scim->impl->use_preedit = _on_the_spot;
932 context_scim->impl->preedit_started = false;
933 context_scim->impl->preedit_updating = false;
934 context_scim->impl->need_commit_preedit = false;
935 context_scim->impl->prediction_allow = true;
938 context_scim->next = NULL;
940 context_scim->next = _ic_list;
941 _ic_list = context_scim;
943 if (_shared_input_method)
944 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
946 _panel_client.prepare (context_scim->id);
947 _panel_client.register_input_context (context_scim->id, si->get_factory_uuid ());
948 set_ic_capabilities (context_scim);
949 _panel_client.send ();
951 SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
955 isf_imf_context_del (Ecore_IMF_Context *ctx)
957 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
959 if (!_ic_list) return;
961 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
962 Ecore_IMF_Input_Panel_State input_panel_state = ecore_imf_context_input_panel_state_get (ctx);
965 if (context_scim->id != _ic_list->id) {
966 EcoreIMFContextISF * pre = _ic_list;
967 EcoreIMFContextISF * cur = _ic_list->next;
968 while (cur != NULL) {
969 if (cur->id == context_scim->id) {
970 pre->next = cur->next;
977 _ic_list = _ic_list->next;
981 if (context_scim && context_scim->impl) {
982 _panel_client.prepare (context_scim->id);
984 if (context_scim == _focused_ic)
985 context_scim->impl->si->focus_out ();
987 if (context_scim->impl->client_canvas)
988 evas_event_callback_del_full (context_scim->impl->client_canvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, evas_focus_out_cb, ctx);
990 if (input_panel_ctx == ctx && _scim_initialized) {
991 LOGD ("ctx : %p\n", ctx);
992 if (input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
993 input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
994 ecore_imf_context_input_panel_hide (ctx);
995 input_panel_event_callback_call (ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
999 // Delete the instance.
1001 // In case the instance send out some helper event,
1002 // and this context has been focused out,
1003 // we need set the focused_ic to this context temporary.
1004 EcoreIMFContextISF *old_focused = _focused_ic;
1005 _focused_ic = context_scim;
1006 context_scim->impl->si.reset ();
1007 _focused_ic = old_focused;
1009 if (context_scim == _focused_ic) {
1010 _panel_client.turn_off (context_scim->id);
1011 _panel_client.focus_out (context_scim->id);
1014 _panel_client.remove_input_context (context_scim->id);
1015 _panel_client.send ();
1017 if (context_scim->impl->client_window)
1018 isf_imf_context_client_window_set (ctx, NULL);
1020 if (context_scim->impl) {
1021 delete_ic_impl (context_scim->impl);
1022 context_scim->impl = 0;
1026 isf_imf_context_input_panel_event_callback_clear (ctx);
1028 if (context_scim == _focused_ic)
1032 delete context_scim;
1038 * isf_imf_context_client_canvas_set
1039 * @ctx: a #Ecore_IMF_Context
1040 * @canvas: the client canvas
1042 * This function will be called by Ecore IMF.
1044 * Set the client canvas for the Input Method Context; this is the canvas
1045 * in which the input appears.
1047 * The canvas type can be determined by using the context canvas type.
1048 * Actually only canvas with type "evas" (Evas *) is supported. This canvas
1049 * may be used in order to correctly position status windows, and may also
1050 * be used for purposes internal to the Input Method Context.
1053 isf_imf_context_client_canvas_set (Ecore_IMF_Context *ctx, void *canvas)
1055 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1057 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1059 if (context_scim && context_scim->impl && context_scim->impl->client_canvas != (Evas*) canvas) {
1060 context_scim->impl->client_canvas = (Evas*)canvas;
1062 LOGD ("ctx : %p, canvas : %p\n", ctx, canvas);
1064 evas_event_callback_add (context_scim->impl->client_canvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, evas_focus_out_cb, ctx);
1069 * isf_imf_context_client_window_set
1070 * @ctx: a #Ecore_IMF_Context
1071 * @window: the client window
1073 * This function will be called by Ecore IMF.
1075 * Set the client window for the Input Method Context; this is the Ecore_X_Window
1076 * when using X11, Ecore_Win32_Window when using Win32, etc.
1078 * This window is used in order to correctly position status windows,
1079 * and may also be used for purposes internal to the Input Method Context.
1082 isf_imf_context_client_window_set (Ecore_IMF_Context *ctx, void *window)
1084 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1086 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1088 if (context_scim && context_scim->impl && context_scim->impl->client_window != (Ecore_X_Window)((Ecore_Window)window)) {
1089 context_scim->impl->client_window = (Ecore_X_Window)((Ecore_Window)window);
1091 LOGD ("ctx : %p, client X win ID : %#x\n", ctx, context_scim->impl->client_window);
1093 if ((context_scim->impl->client_window != 0) &&
1094 (context_scim->impl->client_window != _client_window)) {
1095 _client_window = context_scim->impl->client_window;
1097 _check_desktop_mode (_client_window);
1099 ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, _x_prop_change, window);
1105 * isf_imf_context_focus_in
1106 * @ctx: a #Ecore_IMF_Context
1108 * This function will be called by Ecore IMF.
1110 * Notify the Input Method Context that the widget to which its correspond has gained focus.
1113 isf_imf_context_focus_in (Ecore_IMF_Context *ctx)
1115 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1120 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
1123 if (_focused_ic == context_scim) {
1124 SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
1127 SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
1128 if (_focused_ic->ctx)
1129 isf_imf_context_focus_out (_focused_ic->ctx);
1132 bool need_cap = false;
1133 bool need_reset = false;
1134 bool need_reg = false;
1136 if (context_scim && context_scim->impl) {
1137 _focused_ic = context_scim;
1138 isf_imf_context_control_focus_in (ctx);
1140 _panel_client.prepare (context_scim->id);
1142 // Handle the "Shared Input Method" mode.
1143 if (_shared_input_method) {
1144 SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
1145 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1146 if (!factory.null ()) {
1147 if (_default_instance.null () || _default_instance->get_factory_uuid () != factory->get_uuid ()) {
1148 _default_instance = factory->create_instance ("UTF-8", _default_instance.null () ? _instance_count++ : _default_instance->get_id ());
1149 attach_instance (_default_instance);
1150 SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id () << " " << _default_instance->get_factory_uuid () << "\n";
1153 context_scim->impl->shared_si = true;
1154 context_scim->impl->si = _default_instance;
1156 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1157 context_scim->impl->preedit_string.clear ();
1158 context_scim->impl->preedit_attrlist.clear ();
1159 context_scim->impl->preedit_caret = 0;
1160 context_scim->impl->preedit_started = false;
1165 } else if (context_scim->impl->shared_si) {
1166 SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
1167 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1168 if (!factory.null ()) {
1169 context_scim->impl->si = factory->create_instance ("UTF-8", _instance_count++);
1170 context_scim->impl->preedit_string.clear ();
1171 context_scim->impl->preedit_attrlist.clear ();
1172 context_scim->impl->preedit_caret = 0;
1173 context_scim->impl->preedit_started = false;
1174 attach_instance (context_scim->impl->si);
1177 context_scim->impl->shared_si = false;
1178 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id () << " " << context_scim->impl->si->get_factory_uuid () << "\n";
1182 context_scim->impl->si->set_frontend_data (static_cast <void*> (context_scim));
1184 if (need_reg) _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
1185 if (need_cap) set_ic_capabilities (context_scim);
1187 panel_req_focus_in (context_scim);
1188 // panel_req_update_spot_location (context_scim);
1189 // panel_req_update_factory_info (context_scim);
1191 if (need_reset) context_scim->impl->si->reset ();
1192 if (context_scim->impl->is_on) {
1193 _panel_client.turn_on (context_scim->id);
1194 // _panel_client.hide_preedit_string (context_scim->id);
1195 // _panel_client.hide_aux_string (context_scim->id);
1196 // _panel_client.hide_lookup_table (context_scim->id);
1197 context_scim->impl->si->focus_in ();
1198 context_scim->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ctx));
1199 set_prediction_allow (context_scim->impl->si, context_scim->impl->prediction_allow);
1200 if (context_scim->impl->imdata)
1201 context_scim->impl->si->set_imdata ((const char *)context_scim->impl->imdata, context_scim->impl->imdata_size);
1203 _panel_client.turn_off (context_scim->id);
1206 _panel_client.send ();
1209 LOGD ("ctx : %p\n", ctx);
1211 if (ecore_imf_context_input_panel_enabled_get (ctx))
1212 ecore_imf_context_input_panel_show (ctx);
1214 LOGD ("ctx : %p input panel enable : FALSE\n", ctx);
1218 * isf_imf_context_focus_out
1219 * @ctx: a #Ecore_IMF_Context
1221 * This function will be called by Ecore IMF.
1223 * Notify the Input Method Context that the widget to which its correspond has lost focus.
1226 isf_imf_context_focus_out (Ecore_IMF_Context *ctx)
1228 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1231 if (!context_scim) return;
1233 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1235 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1237 WideString wstr = context_scim->impl->preedit_string;
1239 LOGD ("ctx : %p\n", ctx);
1241 if (ecore_imf_context_input_panel_enabled_get (ctx))
1242 ecore_imf_context_input_panel_hide (ctx);
1244 if (context_scim->impl->need_commit_preedit) {
1245 panel_slot_hide_preedit_string (context_scim->id);
1247 if (wstr.length ()) {
1248 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1249 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1251 _panel_client.prepare (context_scim->id);
1252 _panel_client.reset_input_context (context_scim->id);
1253 _panel_client.send ();
1256 lock_scr = check_focus_out_by_lockscreen (ctx);
1259 _panel_client.prepare (context_scim->id);
1261 context_scim->impl->si->focus_out ();
1262 context_scim->impl->si->reset ();
1265 // if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1266 _panel_client.focus_out (context_scim->id);
1267 _panel_client.send ();
1274 * isf_imf_context_reset
1275 * @ctx: a #Ecore_IMF_Context
1277 * This function will be called by Ecore IMF.
1279 * Notify the Input Method Context that a change such as a change in cursor
1280 * position has been made. This will typically cause the Input Method Context
1281 * to clear the preedit state.
1284 isf_imf_context_reset (Ecore_IMF_Context *ctx)
1286 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1288 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1290 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1291 WideString wstr = context_scim->impl->preedit_string;
1293 _panel_client.prepare (context_scim->id);
1294 context_scim->impl->si->reset ();
1295 _panel_client.reset_input_context (context_scim->id);
1296 _panel_client.send ();
1298 if (context_scim->impl->need_commit_preedit) {
1299 panel_slot_hide_preedit_string (context_scim->id);
1301 if (wstr.length ()) {
1302 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1303 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1310 * isf_imf_context_cursor_position_set
1311 * @ctx: a #Ecore_IMF_Context
1312 * @cursor_pos: New cursor position in characters.
1314 * This function will be called by Ecore IMF.
1316 * Notify the Input Method Context that a change in the cursor position has been made.
1319 isf_imf_context_cursor_position_set (Ecore_IMF_Context *ctx, int cursor_pos)
1321 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1323 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1325 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1326 if (context_scim->impl->cursor_pos != cursor_pos) {
1327 LOGD ("ctx : %p, cursor pos : %d\n", ctx, cursor_pos);
1328 context_scim->impl->cursor_pos = cursor_pos;
1330 caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1332 if (context_scim->impl->preedit_updating)
1334 _panel_client.prepare (context_scim->id);
1335 context_scim->impl->si->update_cursor_position (cursor_pos);
1336 panel_req_update_cursor_position (context_scim, cursor_pos);
1337 _panel_client.send ();
1343 * isf_imf_context_cursor_location_set
1344 * @ctx: a #Ecore_IMF_Context
1345 * @x: x position of New cursor.
1346 * @y: y position of New cursor.
1347 * @w: the width of New cursor.
1348 * @h: the height of New cursor.
1350 * This function will be called by Ecore IMF.
1352 * Notify the Input Method Context that a change in the cursor location has been made.
1355 isf_imf_context_cursor_location_set (Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
1357 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1359 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1361 int canvas_x, canvas_y;
1362 int new_cursor_x, new_cursor_y;
1364 if (cw == 0 && ch == 0)
1367 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1368 if (context_scim->impl->client_canvas) {
1369 ee = ecore_evas_ecore_evas_get (context_scim->impl->client_canvas);
1372 ecore_evas_geometry_get (ee, &canvas_x, &canvas_y, NULL, NULL);
1375 if (context_scim->impl->client_window)
1376 window_to_screen_geometry_get (context_scim->impl->client_window, &canvas_x, &canvas_y);
1381 new_cursor_x = canvas_x + cx;
1382 new_cursor_y = canvas_y + cy + ch;
1384 // Don't update spot location while updating preedit string.
1385 if (context_scim->impl->preedit_updating && (context_scim->impl->cursor_y == new_cursor_y))
1388 if (context_scim->impl->cursor_x != new_cursor_x || context_scim->impl->cursor_y != new_cursor_y) {
1389 context_scim->impl->cursor_x = new_cursor_x;
1390 context_scim->impl->cursor_y = new_cursor_y;
1391 context_scim->impl->cursor_top_y = canvas_y + cy;
1392 _panel_client.prepare (context_scim->id);
1393 panel_req_update_spot_location (context_scim);
1394 _panel_client.send ();
1395 SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
1401 * isf_imf_context_input_mode_set
1402 * @ctx: a #Ecore_IMF_Context
1403 * @input_mode: the input mode
1405 * This function will be called by Ecore IMF.
1407 * To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
1408 * is in Ecore_IMF.h.
1411 isf_imf_context_input_mode_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
1413 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1415 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1416 if (context_scim && context_scim->impl) {
1417 context_scim->impl->input_mode = input_mode;
1422 * isf_imf_context_preedit_string_get
1423 * @ctx: a #Ecore_IMF_Context
1424 * @str: the preedit string
1425 * @cursor_pos: the cursor position
1427 * This function will be called by Ecore IMF.
1429 * To get the preedit string of the input method.
1432 isf_imf_context_preedit_string_get (Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
1434 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1436 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1438 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1439 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1443 *str = strdup (mbs.c_str ());
1449 *cursor_pos = context_scim->impl->preedit_caret;
1461 isf_imf_context_preedit_string_with_attributes_get (Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
1463 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1465 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1467 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1468 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1472 *str = strdup (mbs.c_str ());
1478 *cursor_pos = context_scim->impl->preedit_caret;
1482 if (mbs.length ()) {
1483 int start_index, end_index;
1484 int wlen = context_scim->impl->preedit_string.length ();
1485 Ecore_IMF_Preedit_Attr *attr = NULL;
1486 AttributeList::const_iterator i;
1487 bool *attrs_flag = new bool [mbs.length ()];
1488 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1489 for (i = context_scim->impl->preedit_attrlist.begin ();
1490 i != context_scim->impl->preedit_attrlist.end (); ++i) {
1491 start_index = i->get_start ();
1492 end_index = i->get_end ();
1493 if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1494 start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1495 end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1496 if (i->get_type () == SCIM_ATTR_DECORATE) {
1497 attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof (Ecore_IMF_Preedit_Attr));
1500 attr->start_index = start_index;
1501 attr->end_index = end_index;
1503 if (i->get_value () == SCIM_ATTR_DECORATE_UNDERLINE) {
1504 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1505 *attrs = eina_list_append (*attrs, (void *)attr);
1506 } else if (i->get_value () == SCIM_ATTR_DECORATE_REVERSE) {
1507 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1508 *attrs = eina_list_append (*attrs, (void *)attr);
1509 } else if (i->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
1510 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
1511 *attrs = eina_list_append (*attrs, (void *)attr);
1512 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR1) {
1513 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
1514 *attrs = eina_list_append (*attrs, (void *)attr);
1515 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR2) {
1516 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
1517 *attrs = eina_list_append (*attrs, (void *)attr);
1518 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR3) {
1519 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
1520 *attrs = eina_list_append (*attrs, (void *)attr);
1521 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR4) {
1522 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
1523 *attrs = eina_list_append (*attrs, (void *)attr);
1527 switch(i->get_value())
1529 case SCIM_ATTR_DECORATE_UNDERLINE:
1530 case SCIM_ATTR_DECORATE_REVERSE:
1531 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1532 case SCIM_ATTR_DECORATE_BGCOLOR1:
1533 case SCIM_ATTR_DECORATE_BGCOLOR2:
1534 case SCIM_ATTR_DECORATE_BGCOLOR3:
1535 case SCIM_ATTR_DECORATE_BGCOLOR4:
1536 // Record which character has attribute.
1537 for (int pos = start_index; pos < end_index; ++pos)
1538 attrs_flag [pos] = 1;
1543 } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1544 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1545 } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1546 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1550 // Add underline for all characters which don't have attribute.
1551 for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1552 if (!attrs_flag [pos]) {
1553 int begin_pos = pos;
1554 while (pos < mbs.length () && !attrs_flag [pos])
1556 // use REVERSE style as default
1557 attr = (Ecore_IMF_Preedit_Attr *)calloc (1, sizeof (Ecore_IMF_Preedit_Attr));
1560 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1561 attr->start_index = begin_pos;
1562 attr->end_index = pos;
1563 *attrs = eina_list_append(*attrs, (void *)attr);
1566 delete [] attrs_flag;
1582 * isf_imf_context_use_preedit_set
1583 * @ctx: a #Ecore_IMF_Context
1584 * @use_preedit: Whether the IM context should use the preedit string.
1586 * This function will be called by Ecore IMF.
1588 * Set whether the IM context should use the preedit string to display feedback.
1589 * If is 0 (default is 1), then the IM context may use some other method to
1590 * display feedback, such as displaying it in a child of the root window.
1593 isf_imf_context_use_preedit_set (Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
1595 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (use_preedit == EINA_TRUE ? "true" : "false") << "...\n";
1597 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1599 if (!_on_the_spot) return;
1601 if (context_scim && context_scim->impl) {
1602 bool old = context_scim->impl->use_preedit;
1603 context_scim->impl->use_preedit = use_preedit;
1604 if (context_scim == _focused_ic) {
1605 _panel_client.prepare (context_scim->id);
1607 if (old != use_preedit)
1608 set_ic_capabilities (context_scim);
1610 if (context_scim->impl->preedit_string.length ())
1611 slot_show_preedit_string (context_scim->impl->si);
1613 _panel_client.send ();
1619 * isf_imf_context_prediction_allow_set
1620 * @ctx: a #Ecore_IMF_Context
1621 * @prediction: Whether the IM context should use the prediction.
1623 * This function will be called by Ecore IMF.
1625 * Set whether the IM context should use the prediction.
1628 isf_imf_context_prediction_allow_set (Ecore_IMF_Context* ctx, Eina_Bool prediction)
1630 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction == EINA_TRUE ? "true" : "false") << "...\n";
1632 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1634 if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction) {
1635 context_scim->impl->prediction_allow = prediction;
1636 set_prediction_allow (context_scim->impl->si, prediction);
1641 * isf_imf_context_prediction_allow_get
1642 * @ctx: a #Ecore_IMF_Context
1644 * This function will be called by Ecore IMF.
1646 * To get prediction allow flag for the IM context.
1648 * Return value: the prediction allow flag for the IM context
1651 isf_imf_context_prediction_allow_get (Ecore_IMF_Context* ctx)
1653 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1655 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1657 Eina_Bool ret = EINA_FALSE;
1658 if (context_scim && context_scim->impl) {
1659 ret = context_scim->impl->prediction_allow;
1661 std::cerr << __FUNCTION__ << " failed!!!\n";
1667 * isf_imf_context_autocapital_type_set
1668 * @ctx: a #Ecore_IMF_Context
1669 * @autocapital_type: the autocapital type for the IM context.
1671 * This function will be called by Ecore IMF.
1673 * Set autocapital type for the IM context.
1676 isf_imf_context_autocapital_type_set (Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1678 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1680 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1682 if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1683 context_scim->impl->autocapital_type = autocapital_type;
1688 * isf_imf_context_filter_event
1689 * @ctx: a #Ecore_IMF_Context
1690 * @type: The type of event defined by Ecore_IMF_Event_Type.
1691 * @event: The event itself.
1692 * Return value: %TRUE if the input method handled the key event.
1694 * This function will be called by Ecore IMF.
1696 * Allow an Ecore Input Context to internally handle an event. If this function
1697 * returns 1, then no further processing should be done for this event. Input
1698 * methods must be able to accept all types of events (simply returning 0 if
1699 * the event was not handled), but there is no obligation of any events to be
1700 * submitted to this function.
1703 isf_imf_context_filter_event (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
1705 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1707 EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1708 Eina_Bool ret = EINA_FALSE;
1710 if (ic == NULL || ic->impl == NULL)
1714 unsigned int timestamp;
1716 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1717 Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
1718 timestamp = ev->timestamp;
1719 scim_string_to_key (key, ev->key);
1720 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1721 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1722 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1723 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1724 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1725 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1726 } else if (type == ECORE_IMF_EVENT_KEY_UP) {
1727 Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
1728 timestamp = ev->timestamp;
1729 scim_string_to_key (key, ev->key);
1730 key.mask = SCIM_KEY_ReleaseMask;
1731 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1732 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1733 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1734 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1735 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1736 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1737 } else if (type == ECORE_IMF_EVENT_MOUSE_UP) {
1738 if (ecore_imf_context_input_panel_enabled_get (ctx)) {
1739 LOGD ("[Mouse-up event] ctx : %p\n", ctx);
1740 if (ic == _focused_ic)
1741 ecore_imf_context_input_panel_show (ctx);
1743 LOGW ("Can't show IME because there is no focus. ctx : %p\n", ctx);
1750 key.mask &= _valid_key_mask;
1752 _panel_client.prepare (ic->id);
1755 if (!filter_hotkeys (ic, key)) {
1756 if (timestamp == 0) {
1758 // in case of generated event
1759 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1760 char code = key.get_ascii_code ();
1761 if (isgraph (code)) {
1762 char string[2] = {0};
1763 snprintf (string, sizeof (string), "%c", code);
1765 if (strlen (string) != 0) {
1766 ecore_imf_context_commit_event_add (ic->ctx, string);
1767 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)string);
1768 caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1773 _panel_client.send ();
1777 if (!_focused_ic || !_focused_ic->impl->is_on ||
1778 !_focused_ic->impl->si->process_key_event (key)) {
1783 _panel_client.send ();
1789 * Set up an ISE specific data
1791 * @param[in] ctx a #Ecore_IMF_Context
1792 * @param[in] data pointer of data to sets up to ISE
1793 * @param[in] length length of data
1795 EAPI void isf_imf_context_imdata_set (Ecore_IMF_Context *ctx, const void* data, int length)
1797 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " data length ( " << length << ") ...\n";
1798 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1800 if (context_scim == NULL || data == NULL || length <= 0)
1803 if (context_scim && context_scim->impl) {
1804 if (context_scim->impl->imdata)
1805 free (context_scim->impl->imdata);
1807 context_scim->impl->imdata = calloc (1, length);
1808 memcpy (context_scim->impl->imdata, data, length);
1809 context_scim->impl->imdata_size = length;
1811 if (context_scim->impl->si && _focused_ic == context_scim) {
1812 _panel_client.prepare (context_scim->id);
1813 context_scim->impl->si->set_imdata ((const char *)data, length);
1814 _panel_client.send ();
1818 isf_imf_context_input_panel_imdata_set (ctx, data, length);
1822 * Get the ISE specific data from ISE
1824 * @param[in] ctx a #Ecore_IMF_Context
1825 * @param[out] data pointer of data to return
1826 * @param[out] length length of data
1828 EAPI void isf_imf_context_imdata_get (Ecore_IMF_Context *ctx, void* data, int* length)
1830 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1832 isf_imf_context_input_panel_imdata_get (ctx, data, length);
1835 /* Panel Slot functions */
1837 panel_slot_reload_config (int context)
1839 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1845 panel_slot_exit (int /* context */)
1847 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1853 panel_slot_update_candidate_item_layout (int context, const std::vector<uint32> &row_items)
1855 EcoreIMFContextISF *ic = find_ic (context);
1856 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " row size=" << row_items.size () << " ic=" << ic << "\n";
1857 if (ic && ic->impl) {
1858 _panel_client.prepare (ic->id);
1859 ic->impl->si->update_candidate_item_layout (row_items);
1860 _panel_client.send ();
1865 panel_slot_update_lookup_table_page_size (int context, int page_size)
1867 EcoreIMFContextISF *ic = find_ic (context);
1868 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
1869 if (ic && ic->impl) {
1870 _panel_client.prepare (ic->id);
1871 ic->impl->si->update_lookup_table_page_size (page_size);
1872 _panel_client.send ();
1877 panel_slot_lookup_table_page_up (int context)
1879 EcoreIMFContextISF *ic = find_ic (context);
1880 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1881 if (ic && ic->impl) {
1882 _panel_client.prepare (ic->id);
1883 ic->impl->si->lookup_table_page_up ();
1884 _panel_client.send ();
1889 panel_slot_lookup_table_page_down (int context)
1891 EcoreIMFContextISF *ic = find_ic (context);
1892 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1893 if (ic && ic->impl) {
1894 _panel_client.prepare (ic->id);
1895 ic->impl->si->lookup_table_page_down ();
1896 _panel_client.send ();
1901 panel_slot_trigger_property (int context, const String &property)
1903 EcoreIMFContextISF *ic = find_ic (context);
1904 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
1905 if (ic && ic->impl) {
1906 _panel_client.prepare (ic->id);
1907 ic->impl->si->trigger_property (property);
1908 _panel_client.send ();
1913 panel_slot_process_helper_event (int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
1915 EcoreIMFContextISF *ic = find_ic (context);
1916 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
1917 << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic != NULL ? ic->impl : 0) << " ic-uuid="
1918 << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "" ) << "\n";
1919 if (ic && ic->impl && ic->impl->si->get_factory_uuid () == target_uuid) {
1920 _panel_client.prepare (ic->id);
1921 SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
1922 ic->impl->si->process_helper_event (helper_uuid, trans);
1923 _panel_client.send ();
1928 panel_slot_move_preedit_caret (int context, int caret_pos)
1930 EcoreIMFContextISF *ic = find_ic (context);
1931 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
1932 if (ic && ic->impl) {
1933 _panel_client.prepare (ic->id);
1934 ic->impl->si->move_preedit_caret (caret_pos);
1935 _panel_client.send ();
1940 panel_slot_update_preedit_caret (int context, int caret)
1942 EcoreIMFContextISF *ic = find_ic (context);
1943 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
1945 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
1946 ic->impl->preedit_caret = caret;
1947 if (ic->impl->use_preedit) {
1948 if (!ic->impl->preedit_started) {
1949 ecore_imf_context_preedit_start_event_add (ic->ctx);
1950 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
1951 ic->impl->preedit_started = true;
1953 ecore_imf_context_preedit_changed_event_add (ic->ctx);
1954 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1956 _panel_client.prepare (ic->id);
1957 _panel_client.update_preedit_caret (ic->id, caret);
1958 _panel_client.send ();
1964 panel_slot_select_aux (int context, int aux_index)
1966 EcoreIMFContextISF *ic = find_ic (context);
1967 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " aux=" << aux_index << " ic=" << ic << "\n";
1968 if (ic && ic->impl) {
1969 _panel_client.prepare (ic->id);
1970 ic->impl->si->select_aux (aux_index);
1971 _panel_client.send ();
1976 panel_slot_select_candidate (int context, int cand_index)
1978 EcoreIMFContextISF *ic = find_ic (context);
1979 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
1980 if (ic && ic->impl) {
1981 _panel_client.prepare (ic->id);
1982 ic->impl->si->select_candidate (cand_index);
1983 _panel_client.send ();
1988 _keyname_to_keycode (const char *keyname)
1992 Display *display = (Display *)ecore_x_display_get ();
1994 keysym = XStringToKeysym (keyname);
1996 if (!strncmp (keyname, "Keycode-", 8)) {
1997 keycode = atoi (keyname + 8);
1999 keycode = XKeysymToKeycode (display, keysym);
2006 feed_key_event (EcoreIMFContextISF *ic, const KeyEvent &key, bool fake)
2008 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2010 if (key.code <= 0x7F ||
2011 (key.code >= SCIM_KEY_BackSpace && key.code <= SCIM_KEY_Delete) ||
2012 (key.code >= SCIM_KEY_Home && key.code <= SCIM_KEY_Hyper_R)) {
2013 // ascii code and function keys
2014 send_x_key_event (key, fake);
2022 panel_slot_process_key_event (int context, const KeyEvent &key)
2024 EcoreIMFContextISF *ic = find_ic (context);
2025 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2027 if (feed_key_event (ic, key, false) == EINA_TRUE) return;
2029 if (ic && ic->impl) {
2030 _panel_client.prepare (ic->id);
2032 if (!filter_hotkeys (ic, key)) {
2033 if (!_focused_ic || !_focused_ic->impl->is_on ||
2034 !_focused_ic->impl->si->process_key_event (key)) {
2035 _fallback_instance->process_key_event (key);
2039 _panel_client.send ();
2044 panel_slot_commit_string (int context, const WideString &wstr)
2046 EcoreIMFContextISF *ic = find_ic (context);
2047 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2049 if (ic && ic->impl) {
2050 if (_focused_ic != ic)
2053 if (ic->impl->need_commit_preedit)
2054 panel_slot_hide_preedit_string (ic->id);
2055 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2056 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2061 panel_slot_forward_key_event (int context, const KeyEvent &key)
2063 EcoreIMFContextISF *ic = find_ic (context);
2064 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2066 if (strlen (key.get_key_string ().c_str ()) >= 116)
2069 feed_key_event (ic, key, true);
2073 panel_slot_request_help (int context)
2075 EcoreIMFContextISF *ic = find_ic (context);
2076 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2077 if (ic && ic->impl) {
2078 _panel_client.prepare (ic->id);
2079 panel_req_show_help (ic);
2080 _panel_client.send ();
2085 panel_slot_request_factory_menu (int context)
2087 EcoreIMFContextISF *ic = find_ic (context);
2088 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2089 if (ic && ic->impl) {
2090 _panel_client.prepare (ic->id);
2091 panel_req_show_factory_menu (ic);
2092 _panel_client.send ();
2097 panel_slot_change_factory (int context, const String &uuid)
2099 EcoreIMFContextISF *ic = find_ic (context);
2100 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
2101 if (ic && ic->impl) {
2102 _panel_client.prepare (ic->id);
2103 ic->impl->si->reset ();
2104 open_specific_factory (ic, uuid);
2105 _panel_client.send ();
2110 panel_slot_reset_keyboard_ise (int context)
2112 EcoreIMFContextISF *ic = find_ic (context);
2113 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2114 if (ic && ic->impl) {
2115 WideString wstr = ic->impl->preedit_string;
2116 if (ic->impl->need_commit_preedit) {
2117 panel_slot_hide_preedit_string (ic->id);
2119 if (wstr.length ()) {
2120 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2121 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2124 _panel_client.prepare (ic->id);
2125 ic->impl->si->reset ();
2126 _panel_client.send ();
2131 panel_slot_update_keyboard_ise (int context)
2133 EcoreIMFContextISF *ic = find_ic (context);
2134 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2136 _backend->add_module (_config, "socket", false);
2140 panel_slot_show_preedit_string (int context)
2142 EcoreIMFContextISF *ic = find_ic (context);
2143 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << "\n";
2145 if (ic && ic->impl && _focused_ic == ic) {
2146 if (!ic->impl->is_on)
2147 ic->impl->is_on = true;
2149 if (ic->impl->use_preedit) {
2150 if (!ic->impl->preedit_started) {
2151 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
2152 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2153 ic->impl->preedit_started = true;
2154 ic->impl->need_commit_preedit = true;
2157 _panel_client.prepare (ic->id);
2158 _panel_client.show_preedit_string (ic->id);
2159 _panel_client.send ();
2165 panel_slot_hide_preedit_string (int context)
2167 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2169 EcoreIMFContextISF *ic = find_ic (context);
2171 if (ic && ic->impl && _focused_ic == ic) {
2172 if (!ic->impl->is_on)
2173 ic->impl->is_on = true;
2176 if (ic->impl->preedit_string.length ()) {
2177 ic->impl->preedit_string = WideString ();
2178 ic->impl->preedit_caret = 0;
2179 ic->impl->preedit_attrlist.clear ();
2182 if (ic->impl->use_preedit) {
2184 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2185 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2187 if (ic->impl->preedit_started) {
2188 ecore_imf_context_preedit_end_event_add (ic->ctx);
2189 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2190 ic->impl->preedit_started = false;
2191 ic->impl->need_commit_preedit = false;
2194 _panel_client.prepare (ic->id);
2195 _panel_client.hide_preedit_string (ic->id);
2196 _panel_client.send ();
2202 panel_slot_update_preedit_string (int context,
2203 const WideString &str,
2204 const AttributeList &attrs)
2206 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2208 EcoreIMFContextISF *ic = find_ic (context);
2210 if (ic && ic->impl && _focused_ic == ic) {
2211 if (!ic->impl->is_on)
2212 ic->impl->is_on = true;
2214 if (ic->impl->preedit_string != str || str.length ()) {
2215 ic->impl->preedit_string = str;
2216 ic->impl->preedit_attrlist = attrs;
2218 if (ic->impl->use_preedit) {
2219 if (!ic->impl->preedit_started) {
2220 ecore_imf_context_preedit_start_event_add (ic->ctx);
2221 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2222 ic->impl->preedit_started = true;
2223 ic->impl->need_commit_preedit = true;
2225 ic->impl->preedit_caret = str.length ();
2226 ic->impl->preedit_updating = true;
2227 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2228 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2229 ic->impl->preedit_updating = false;
2231 _panel_client.prepare (ic->id);
2232 _panel_client.update_preedit_string (ic->id, str, attrs);
2233 _panel_client.send ();
2240 panel_slot_get_surrounding_text (int context, int maxlen_before, int maxlen_after)
2242 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2244 EcoreIMFContextISF *ic = find_ic (context);
2246 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2248 WideString text = WideString ();
2249 slot_get_surrounding_text (ic->impl->si, text, cursor, maxlen_before, maxlen_after);
2250 _panel_client.prepare (ic->id);
2251 _panel_client.update_surrounding_text (ic->id, text, cursor);
2252 _panel_client.send ();
2257 panel_slot_delete_surrounding_text (int context, int offset, int len)
2259 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2261 EcoreIMFContextISF *ic = find_ic (context);
2263 if (ic && ic->impl && _focused_ic == ic && ic->impl->si)
2264 slot_delete_surrounding_text (ic->impl->si, offset, len);
2268 panel_slot_update_displayed_candidate_number (int context, int number)
2270 EcoreIMFContextISF *ic = find_ic (context);
2271 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " number=" << number << " ic=" << ic << "\n";
2272 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2273 _panel_client.prepare (ic->id);
2274 ic->impl->si->update_displayed_candidate_number (number);
2275 _panel_client.send ();
2280 panel_slot_candidate_more_window_show (int context)
2282 EcoreIMFContextISF *ic = find_ic (context);
2283 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2284 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2285 _panel_client.prepare (ic->id);
2286 ic->impl->si->candidate_more_window_show ();
2287 _panel_client.send ();
2292 panel_slot_candidate_more_window_hide (int context)
2294 EcoreIMFContextISF *ic = find_ic (context);
2295 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2296 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2297 _panel_client.prepare (ic->id);
2298 ic->impl->si->candidate_more_window_hide ();
2299 _panel_client.send ();
2304 panel_slot_longpress_candidate (int context, int index)
2306 EcoreIMFContextISF *ic = find_ic (context);
2307 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " index=" << index << " ic=" << ic << "\n";
2308 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2309 _panel_client.prepare (ic->id);
2310 ic->impl->si->longpress_candidate (index);
2311 _panel_client.send ();
2316 panel_slot_update_client_id (int context, int client_id)
2318 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " client_id=" << client_id << "\n";
2320 _panel_client_id = client_id;
2323 /* Panel Requestion functions. */
2325 panel_req_show_help (EcoreIMFContextISF *ic)
2327 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2331 help = String (_("Smart Common Input Method platform ")) +
2332 String (SCIM_VERSION) +
2333 String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2335 if (ic && ic->impl) {
2336 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2338 help += utf8_wcstombs (sf->get_name ());
2339 help += String (_(":\n\n"));
2341 help += utf8_wcstombs (sf->get_help ());
2342 help += String (_("\n\n"));
2344 help += utf8_wcstombs (sf->get_credits ());
2346 _panel_client.show_help (ic->id, help);
2351 panel_req_show_factory_menu (EcoreIMFContextISF *ic)
2353 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2355 std::vector<IMEngineFactoryPointer> factories;
2356 std::vector <PanelFactoryInfo> menu;
2358 _backend->get_factories_for_encoding (factories, "UTF-8");
2360 for (size_t i = 0; i < factories.size (); ++ i) {
2361 menu.push_back (PanelFactoryInfo (
2362 factories [i]->get_uuid (),
2363 utf8_wcstombs (factories [i]->get_name ()),
2364 factories [i]->get_language (),
2365 factories [i]->get_icon_file ()));
2369 _panel_client.show_factory_menu (ic->id, menu);
2373 panel_req_update_factory_info (EcoreIMFContextISF *ic)
2375 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2377 if (ic && ic->impl && ic == _focused_ic) {
2378 PanelFactoryInfo info;
2379 if (ic->impl->is_on) {
2380 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2382 info = PanelFactoryInfo (sf->get_uuid (), utf8_wcstombs (sf->get_name ()), sf->get_language (), sf->get_icon_file ());
2384 info = PanelFactoryInfo (String (""), String (_("English/Keyboard")), String ("C"), String (SCIM_KEYBOARD_ICON_FILE));
2386 _panel_client.update_factory_info (ic->id, info);
2391 panel_req_focus_in (EcoreIMFContextISF *ic)
2393 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2395 _panel_client.focus_in (ic->id, ic->impl->si->get_factory_uuid ());
2399 panel_req_update_spot_location (EcoreIMFContextISF *ic)
2401 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2403 _panel_client.update_spot_location (ic->id, ic->impl->cursor_x, ic->impl->cursor_y, ic->impl->cursor_top_y);
2407 panel_req_update_cursor_position (EcoreIMFContextISF *ic, int cursor_pos)
2409 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2411 _panel_client.update_cursor_position (ic->id, cursor_pos);
2415 filter_hotkeys (EcoreIMFContextISF *ic, const KeyEvent &key)
2417 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2421 _frontend_hotkey_matcher.push_key_event (key);
2422 _imengine_hotkey_matcher.push_key_event (key);
2424 FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result ();
2426 if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER) {
2427 if (!ic->impl->is_on)
2432 _display_input_language (ic);
2434 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON) {
2435 if (!ic->impl->is_on) {
2437 _display_input_language (ic);
2440 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF) {
2441 if (ic->impl->is_on) {
2443 _display_input_language (ic);
2446 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY) {
2447 open_next_factory (ic);
2449 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY) {
2450 open_previous_factory (ic);
2452 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU) {
2453 panel_req_show_factory_menu (ic);
2455 } else if (_imengine_hotkey_matcher.is_matched ()) {
2456 ISEInfo info = _imengine_hotkey_matcher.get_match_result ();
2457 ISE_TYPE type = info.type;
2458 if (type == IMENGINE_T)
2459 open_specific_factory (ic, info.uuid);
2460 else if (type == HELPER_T)
2461 _panel_client.start_helper (ic->id, info.uuid);
2468 panel_initialize (void)
2470 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2472 String display_name;
2474 const char *p = getenv ("DISPLAY");
2475 if (p) display_name = String (p);
2478 if (_panel_client.open_connection (_config->get_name (), display_name) >= 0) {
2479 int fd = _panel_client.get_connection_number ();
2481 _panel_iochannel_read_handler = ecore_main_fd_handler_add (fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
2482 // _panel_iochannel_err_handler = ecore_main_fd_handler_add (fd, ECORE_FD_ERROR, panel_iochannel_handler, NULL, NULL, NULL);
2484 SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
2486 EcoreIMFContextISF *context_scim = _ic_list;
2487 while (context_scim != NULL) {
2488 _panel_client.prepare (context_scim->id);
2489 _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
2490 _panel_client.send ();
2491 context_scim = context_scim->next;
2495 _panel_client.prepare (_focused_ic->id);
2496 panel_req_focus_in (_focused_ic);
2497 _panel_client.send ();
2502 std::cerr << "panel_initialize () failed!!!\n";
2507 panel_finalize (void)
2509 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2511 _panel_client.close_connection ();
2513 if (_panel_iochannel_read_handler) {
2514 ecore_main_fd_handler_del (_panel_iochannel_read_handler);
2515 _panel_iochannel_read_handler = 0;
2517 if (_panel_iochannel_err_handler) {
2518 ecore_main_fd_handler_del (_panel_iochannel_err_handler);
2519 _panel_iochannel_err_handler = 0;
2524 panel_iochannel_handler (void *data, Ecore_Fd_Handler *fd_handler)
2526 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2528 if (fd_handler == _panel_iochannel_read_handler) {
2529 if (_panel_client.has_pending_event () && !_panel_client.filter_event ()) {
2531 panel_initialize ();
2532 return ECORE_CALLBACK_CANCEL;
2534 } else if (fd_handler == _panel_iochannel_err_handler) {
2536 panel_initialize ();
2537 return ECORE_CALLBACK_CANCEL;
2539 return ECORE_CALLBACK_RENEW;
2543 turn_on_ic (EcoreIMFContextISF *ic)
2545 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2547 if (ic && ic->impl && !ic->impl->is_on) {
2548 ic->impl->is_on = true;
2550 if (ic == _focused_ic) {
2551 panel_req_focus_in (ic);
2552 // panel_req_update_spot_location (ic);
2553 panel_req_update_factory_info (ic);
2554 _panel_client.turn_on (ic->id);
2555 // _panel_client.hide_preedit_string (ic->id);
2556 // _panel_client.hide_aux_string (ic->id);
2557 // _panel_client.hide_lookup_table (ic->id);
2558 ic->impl->si->focus_in ();
2559 ic->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ic->ctx));
2560 set_prediction_allow (ic->impl->si, ic->impl->prediction_allow);
2563 //Record the IC on/off status
2564 if (_shared_input_method) {
2565 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
2569 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2570 ecore_imf_context_preedit_start_event_add (ic->ctx);
2571 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2572 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2573 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2574 ic->impl->preedit_started = true;
2580 turn_off_ic (EcoreIMFContextISF *ic)
2582 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2584 if (ic && ic->impl && ic->impl->is_on) {
2585 ic->impl->is_on = false;
2587 if (ic == _focused_ic) {
2588 ic->impl->si->focus_out ();
2590 // panel_req_update_factory_info (ic);
2591 _panel_client.turn_off (ic->id);
2594 //Record the IC on/off status
2595 if (_shared_input_method) {
2596 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2600 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2601 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2602 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2603 ecore_imf_context_preedit_end_event_add (ic->ctx);
2604 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2605 ic->impl->preedit_started = false;
2611 set_ic_capabilities (EcoreIMFContextISF *ic)
2613 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2615 if (ic && ic->impl) {
2616 unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2618 if (!_on_the_spot || !ic->impl->use_preedit)
2619 cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2621 ic->impl->si->update_client_capabilities (cap);
2626 check_socket_frontend (void)
2628 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2630 SocketAddress address;
2631 SocketClient client;
2635 address.set_address (scim_get_default_socket_frontend_address ());
2637 if (!client.connect (address))
2640 if (!scim_socket_open_connection (magic,
2641 String ("ConnectionTester"),
2642 String ("SocketFrontEnd"),
2654 std::vector<String> config_list;
2655 std::vector<String> engine_list;
2656 std::vector<String> helper_list;
2657 std::vector<String> load_engine_list;
2659 std::vector<String>::iterator it;
2661 bool manual = false;
2663 String config_module_name = "simple";
2665 SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore ISF IMModule...\n";
2667 // Get system language.
2668 _language = scim_get_locale_language (scim_get_current_locale ());
2671 // If no Socket FrontEnd is running, then launch one.
2672 // And set manual to false.
2673 bool check_result = check_socket_frontend ();
2674 if (!check_result) {
2675 std::cerr << "Launching a ISF daemon with Socket FrontEnd...\n";
2677 scim_get_imengine_module_list (engine_list);
2678 scim_get_helper_module_list (helper_list);
2680 for (it = engine_list.begin (); it != engine_list.end (); it++) {
2681 if (*it != "socket")
2682 load_engine_list.push_back (*it);
2684 for (it = helper_list.begin (); it != helper_list.end (); it++)
2685 load_engine_list.push_back (*it);
2686 const char *new_argv [] = { "--no-stay", 0 };
2689 (load_engine_list.size () > 0 ? scim_combine_string_list (load_engine_list, ',') : "none"),
2695 // If there is one Socket FrontEnd running and it's not manual mode,
2696 // then just use this Socket Frontend.
2698 for (int i = 0; i < 200; ++i) {
2700 config_module_name = "socket";
2701 load_engine_list.clear ();
2702 load_engine_list.push_back ("socket");
2705 scim_usleep (50000);
2706 check_result = check_socket_frontend ();
2711 if (config_module_name != "dummy") {
2712 //load config module
2713 SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
2714 _config_module = new ConfigModule (config_module_name);
2716 //create config instance
2717 if (_config_module != NULL && _config_module->valid ())
2718 _config = _config_module->create_config ();
2721 if (_config.null ()) {
2722 SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
2724 if (_config_module) delete _config_module;
2725 _config_module = NULL;
2727 _config = new DummyConfig ();
2728 config_module_name = "dummy";
2731 reload_config_callback (_config);
2732 _config->signal_connect_reload (slot (reload_config_callback));
2735 _backend = new CommonBackEnd (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list);
2737 if (_backend.null ()) {
2738 std::cerr << "Cannot create BackEnd Object!\n";
2740 _backend->initialize (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list, false, false);
2741 _fallback_factory = _backend->get_factory (SCIM_COMPOSE_KEY_FACTORY_UUID);
2744 if (_fallback_factory.null ())
2745 _fallback_factory = new DummyIMEngineFactory ();
2747 _fallback_instance = _fallback_factory->create_instance (String ("UTF-8"), 0);
2748 _fallback_instance->signal_connect_commit_string (slot (fallback_commit_string_cb));
2750 // Attach Panel Client signal.
2751 _panel_client.signal_connect_reload_config (slot (panel_slot_reload_config));
2752 _panel_client.signal_connect_exit (slot (panel_slot_exit));
2753 _panel_client.signal_connect_update_candidate_item_layout (slot (panel_slot_update_candidate_item_layout));
2754 _panel_client.signal_connect_update_lookup_table_page_size (slot (panel_slot_update_lookup_table_page_size));
2755 _panel_client.signal_connect_lookup_table_page_up (slot (panel_slot_lookup_table_page_up));
2756 _panel_client.signal_connect_lookup_table_page_down (slot (panel_slot_lookup_table_page_down));
2757 _panel_client.signal_connect_trigger_property (slot (panel_slot_trigger_property));
2758 _panel_client.signal_connect_process_helper_event (slot (panel_slot_process_helper_event));
2759 _panel_client.signal_connect_move_preedit_caret (slot (panel_slot_move_preedit_caret));
2760 _panel_client.signal_connect_update_preedit_caret (slot (panel_slot_update_preedit_caret));
2761 _panel_client.signal_connect_select_aux (slot (panel_slot_select_aux));
2762 _panel_client.signal_connect_select_candidate (slot (panel_slot_select_candidate));
2763 _panel_client.signal_connect_process_key_event (slot (panel_slot_process_key_event));
2764 _panel_client.signal_connect_commit_string (slot (panel_slot_commit_string));
2765 _panel_client.signal_connect_forward_key_event (slot (panel_slot_forward_key_event));
2766 _panel_client.signal_connect_request_help (slot (panel_slot_request_help));
2767 _panel_client.signal_connect_request_factory_menu (slot (panel_slot_request_factory_menu));
2768 _panel_client.signal_connect_change_factory (slot (panel_slot_change_factory));
2769 _panel_client.signal_connect_reset_keyboard_ise (slot (panel_slot_reset_keyboard_ise));
2770 _panel_client.signal_connect_update_keyboard_ise (slot (panel_slot_update_keyboard_ise));
2771 _panel_client.signal_connect_show_preedit_string (slot (panel_slot_show_preedit_string));
2772 _panel_client.signal_connect_hide_preedit_string (slot (panel_slot_hide_preedit_string));
2773 _panel_client.signal_connect_update_preedit_string (slot (panel_slot_update_preedit_string));
2774 _panel_client.signal_connect_get_surrounding_text (slot (panel_slot_get_surrounding_text));
2775 _panel_client.signal_connect_delete_surrounding_text (slot (panel_slot_delete_surrounding_text));
2776 _panel_client.signal_connect_update_displayed_candidate_number (slot (panel_slot_update_displayed_candidate_number));
2777 _panel_client.signal_connect_candidate_more_window_show (slot (panel_slot_candidate_more_window_show));
2778 _panel_client.signal_connect_candidate_more_window_hide (slot (panel_slot_candidate_more_window_hide));
2779 _panel_client.signal_connect_longpress_candidate (slot (panel_slot_longpress_candidate));
2780 _panel_client.signal_connect_update_client_id (slot (panel_slot_update_client_id));
2782 if (!panel_initialize ()) {
2783 std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
2790 SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
2792 // Reset this first so that the shared instance could be released correctly afterwards.
2793 _default_instance.reset ();
2795 SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2796 while (_used_ic_impl_list) {
2797 // In case in "shared input method" mode,
2798 // all contexts share only one instance,
2799 // so we need point the reference pointer correctly before finalizing.
2800 _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2801 isf_imf_context_del (_used_ic_impl_list->parent->ctx);
2804 delete_all_ic_impl ();
2806 _fallback_instance.reset ();
2807 _fallback_factory.reset ();
2809 SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
2812 SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2815 if (_config_module) {
2816 SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
2817 delete _config_module;
2824 _scim_initialized = false;
2826 _panel_client.reset_signal_handler ();
2831 _popup_message (const char *_ptext)
2836 notification_status_message_post(_ptext);
2840 _display_input_language (EcoreIMFContextISF *ic)
2842 IMEngineFactoryPointer sf;
2844 if (ic && ic->impl) {
2845 if (ic->impl->is_on) {
2846 sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2847 _popup_message (scim_get_language_name (sf->get_language ()).c_str ());
2850 _popup_message (scim_get_language_name ("en").c_str());
2856 open_next_factory (EcoreIMFContextISF *ic)
2858 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2859 IMEngineFactoryPointer sf = _backend->get_next_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2863 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2864 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2865 ic->impl->preedit_string = WideString ();
2866 ic->impl->preedit_caret = 0;
2867 attach_instance (ic->impl->si);
2868 _backend->set_default_factory (_language, sf->get_uuid ());
2869 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2870 _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2871 set_ic_capabilities (ic);
2874 if (_shared_input_method) {
2875 _default_instance = ic->impl->si;
2876 ic->impl->shared_si = true;
2878 _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2883 open_previous_factory (EcoreIMFContextISF *ic)
2888 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2889 IMEngineFactoryPointer sf = _backend->get_previous_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2893 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2894 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2895 ic->impl->preedit_string = WideString ();
2896 ic->impl->preedit_caret = 0;
2897 attach_instance (ic->impl->si);
2898 _backend->set_default_factory (_language, sf->get_uuid ());
2899 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2900 _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2901 set_ic_capabilities (ic);
2904 if (_shared_input_method) {
2905 _default_instance = ic->impl->si;
2906 ic->impl->shared_si = true;
2908 _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2913 open_specific_factory (EcoreIMFContextISF *ic,
2919 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2921 // The same input method is selected, just turn on the IC.
2922 if (ic->impl->si->get_factory_uuid () == uuid) {
2927 IMEngineFactoryPointer sf = _backend->get_factory (uuid);
2929 if (uuid.length () && !sf.null ()) {
2931 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2932 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2933 ic->impl->preedit_string = WideString ();
2934 ic->impl->preedit_caret = 0;
2935 attach_instance (ic->impl->si);
2936 _backend->set_default_factory (_language, sf->get_uuid ());
2937 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2938 set_ic_capabilities (ic);
2941 if (_shared_input_method) {
2942 _default_instance = ic->impl->si;
2943 ic->impl->shared_si = true;
2946 std::cerr << "open_specific_factory () is failed!!!!!!\n";
2947 LOGE ("open_specific_factory () is failed. ic : %x uuid : %s", ic->id, uuid.c_str());
2949 // turn_off_ic comment out panel_req_update_factory_info ()
2951 if (ic && ic->impl->is_on) {
2952 ic->impl->is_on = false;
2954 if (ic == _focused_ic) {
2955 ic->impl->si->focus_out ();
2957 panel_req_update_factory_info (ic);
2958 _panel_client.turn_off (ic->id);
2961 //Record the IC on/off status
2962 if (_shared_input_method) {
2963 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2967 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2968 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2969 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2970 ecore_imf_context_preedit_end_event_add (ic->ctx);
2971 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2972 ic->impl->preedit_started = false;
2978 static void initialize_modifier_bits (Display *display)
2980 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2982 if (__current_display == display)
2985 __current_display = display;
2988 __current_alt_mask = Mod1Mask;
2989 __current_meta_mask = ShiftMask | Mod1Mask;
2990 __current_super_mask = 0;
2991 __current_hyper_mask = 0;
2992 __current_numlock_mask = Mod2Mask;
2996 XModifierKeymap *mods = NULL;
2998 ::KeyCode ctrl_l = XKeysymToKeycode (display, XK_Control_L);
2999 ::KeyCode ctrl_r = XKeysymToKeycode (display, XK_Control_R);
3000 ::KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
3001 ::KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
3002 ::KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
3003 ::KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
3004 ::KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
3005 ::KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
3006 ::KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
3007 ::KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
3008 ::KeyCode numlock = XKeysymToKeycode (display, XK_Num_Lock);
3012 mods = XGetModifierMapping (display);
3016 __current_alt_mask = 0;
3017 __current_meta_mask = 0;
3018 __current_super_mask = 0;
3019 __current_hyper_mask = 0;
3020 __current_numlock_mask = 0;
3022 /* We skip the first three sets for Shift, Lock, and Control. The
3023 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
3024 for (i = 3; i < 8; i++) {
3025 for (j = 0; j < mods->max_keypermod; j++) {
3026 ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
3027 if (! code) continue;
3028 if (code == alt_l || code == alt_r)
3029 __current_alt_mask |= (1 << i);
3030 else if (code == meta_l || code == meta_r)
3031 __current_meta_mask |= (1 << i);
3032 else if (code == super_l || code == super_r)
3033 __current_super_mask |= (1 << i);
3034 else if (code == hyper_l || code == hyper_r)
3035 __current_hyper_mask |= (1 << i);
3036 else if (code == numlock)
3037 __current_numlock_mask |= (1 << i);
3041 /* Check whether there is a combine keys mapped to Meta */
3042 if (__current_meta_mask == 0) {
3045 KeySym keysym_l, keysym_r;
3047 xkey.type = KeyPress;
3048 xkey.display = display;
3050 xkey.send_event = False;
3051 xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
3053 xkey.same_screen = False;
3054 xkey.subwindow = None;
3056 xkey.root = DefaultRootWindow (display);
3057 xkey.state = ShiftMask;
3059 xkey.keycode = meta_l;
3060 XLookupString (&xkey, buf, 32, &keysym_l, 0);
3061 xkey.keycode = meta_r;
3062 XLookupString (&xkey, buf, 32, &keysym_r, 0);
3064 if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
3065 __current_meta_mask = ShiftMask + __current_alt_mask;
3066 else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
3067 __current_meta_mask = ShiftMask + ControlMask;
3070 XFreeModifiermap (mods);
3073 static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask)
3075 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3077 unsigned int state = 0;
3079 initialize_modifier_bits (display);
3081 if (scimkeymask & SCIM_KEY_ShiftMask) state |= ShiftMask;
3082 if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
3083 if (scimkeymask & SCIM_KEY_ControlMask) state |= ControlMask;
3084 if (scimkeymask & SCIM_KEY_AltMask) state |= __current_alt_mask;
3085 if (scimkeymask & SCIM_KEY_MetaMask) state |= __current_meta_mask;
3086 if (scimkeymask & SCIM_KEY_SuperMask) state |= __current_super_mask;
3087 if (scimkeymask & SCIM_KEY_HyperMask) state |= __current_hyper_mask;
3088 if (scimkeymask & SCIM_KEY_NumLockMask) state |= __current_numlock_mask;
3093 static XKeyEvent createKeyEvent (bool press, int keycode, int modifiers, bool fake)
3095 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3099 Display *display = (Display *)ecore_x_display_get ();
3100 int revert = RevertToParent;
3102 XGetInputFocus (display, &focus_win, &revert);
3104 event.display = display;
3105 event.window = focus_win;
3106 event.root = DefaultRootWindow (display);
3107 event.subwindow = None;
3111 event.time = get_time ();
3117 event.same_screen = True;
3118 event.state = modifiers;
3119 event.keycode = keycode;
3121 event.type = KeyPress;
3123 event.type = KeyRelease;
3124 event.send_event = False;
3130 static void send_x_key_event (const KeyEvent &key, bool fake)
3132 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3134 ::KeyCode keycode = 0;
3135 ::KeySym keysym = 0;
3137 char key_string[256] = {0};
3138 char keysym_str[256] = {0};
3140 // Obtain the X11 display.
3141 Display *display = (Display *)ecore_x_display_get ();
3142 if (display == NULL) {
3143 std::cerr << "ecore_x_display_get () failed\n";
3147 if (strncmp (key.get_key_string ().c_str (), "KeyRelease+", 11) == 0) {
3148 snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str () + 11);
3150 snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str ());
3153 if (strncmp (key_string, "Shift+", 6) == 0) {
3154 snprintf (keysym_str, sizeof (keysym_str), "%s", key_string + 6);
3156 snprintf (keysym_str, sizeof (keysym_str), "%s", key_string);
3159 // get x keysym, keycode, keyname, and key
3160 keysym = XStringToKeysym (keysym_str);
3161 if (keysym == NoSymbol)
3164 keycode = _keyname_to_keycode (keysym_str);
3165 if (XkbKeycodeToKeysym (display, keycode, 0, 0) != keysym) {
3166 if (XkbKeycodeToKeysym (display, keycode, 0, 1) == keysym)
3177 int keycode_min, keycode_max, keycode_num;
3180 XDisplayKeycodes (display, &keycode_min, &keycode_max);
3181 keysyms = XGetKeyboardMapping (display, keycode_min,
3182 keycode_max - keycode_min + 1,
3184 mod = (mod + 1) & 0x7;
3185 i = (keycode_max - keycode_min - mod - 1) * keycode_num;
3187 keysyms[i] = keysym;
3188 XChangeKeyboardMapping (display, keycode_min, keycode_num,
3189 keysyms, (keycode_max - keycode_min));
3191 XSync (display, False);
3192 keycode = keycode_max - mod - 1;
3195 unsigned int modifier = scim_x11_keymask_scim_to_x11 (display, key.mask);
3198 modifier |= ShiftMask;
3201 if (key.is_key_press ()) {
3203 event = createKeyEvent (true, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3204 XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3207 event = createKeyEvent (true, keycode, modifier, fake);
3208 XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3210 event = createKeyEvent (false, keycode, modifier, fake);
3211 XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3214 event = createKeyEvent (false, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3215 XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3221 attach_instance (const IMEngineInstancePointer &si)
3223 si->signal_connect_show_preedit_string (
3224 slot (slot_show_preedit_string));
3225 si->signal_connect_show_aux_string (
3226 slot (slot_show_aux_string));
3227 si->signal_connect_show_lookup_table (
3228 slot (slot_show_lookup_table));
3230 si->signal_connect_hide_preedit_string (
3231 slot (slot_hide_preedit_string));
3232 si->signal_connect_hide_aux_string (
3233 slot (slot_hide_aux_string));
3234 si->signal_connect_hide_lookup_table (
3235 slot (slot_hide_lookup_table));
3237 si->signal_connect_update_preedit_caret (
3238 slot (slot_update_preedit_caret));
3239 si->signal_connect_update_preedit_string (
3240 slot (slot_update_preedit_string));
3241 si->signal_connect_update_aux_string (
3242 slot (slot_update_aux_string));
3243 si->signal_connect_update_lookup_table (
3244 slot (slot_update_lookup_table));
3246 si->signal_connect_commit_string (
3247 slot (slot_commit_string));
3249 si->signal_connect_forward_key_event (
3250 slot (slot_forward_key_event));
3252 si->signal_connect_register_properties (
3253 slot (slot_register_properties));
3255 si->signal_connect_update_property (
3256 slot (slot_update_property));
3258 si->signal_connect_beep (
3261 si->signal_connect_start_helper (
3262 slot (slot_start_helper));
3264 si->signal_connect_stop_helper (
3265 slot (slot_stop_helper));
3267 si->signal_connect_send_helper_event (
3268 slot (slot_send_helper_event));
3270 si->signal_connect_get_surrounding_text (
3271 slot (slot_get_surrounding_text));
3273 si->signal_connect_delete_surrounding_text (
3274 slot (slot_delete_surrounding_text));
3276 si->signal_connect_expand_candidate (
3277 slot (slot_expand_candidate));
3278 si->signal_connect_contract_candidate (
3279 slot (slot_contract_candidate));
3281 si->signal_connect_set_candidate_style (
3282 slot (slot_set_candidate_style));
3285 // Implementation of slot functions
3287 slot_show_preedit_string (IMEngineInstanceBase *si)
3289 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3291 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3293 if (ic && ic->impl && _focused_ic == ic) {
3294 if (ic->impl->use_preedit) {
3295 if (!ic->impl->preedit_started) {
3296 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3297 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3298 ic->impl->preedit_started = true;
3300 //if (ic->impl->preedit_string.length ())
3301 // ecore_imf_context_preedit_changed_event_add (_focused_ic->ctx);
3303 _panel_client.show_preedit_string (ic->id);
3309 slot_show_aux_string (IMEngineInstanceBase *si)
3311 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3313 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3315 if (ic && ic->impl && _focused_ic == ic)
3316 _panel_client.show_aux_string (ic->id);
3320 slot_show_lookup_table (IMEngineInstanceBase *si)
3322 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3324 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3326 if (ic && ic->impl && _focused_ic == ic)
3327 _panel_client.show_lookup_table (ic->id);
3331 slot_hide_preedit_string (IMEngineInstanceBase *si)
3333 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3335 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3337 if (ic && ic->impl && _focused_ic == ic) {
3339 if (ic->impl->preedit_string.length ()) {
3340 ic->impl->preedit_string = WideString ();
3341 ic->impl->preedit_caret = 0;
3342 ic->impl->preedit_attrlist.clear ();
3345 if (ic->impl->use_preedit) {
3347 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3348 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3350 if (ic->impl->preedit_started) {
3351 ecore_imf_context_preedit_end_event_add (ic->ctx);
3352 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
3353 ic->impl->preedit_started = false;
3356 _panel_client.hide_preedit_string (ic->id);
3362 slot_hide_aux_string (IMEngineInstanceBase *si)
3364 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3366 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3368 if (ic && ic->impl && _focused_ic == ic)
3369 _panel_client.hide_aux_string (ic->id);
3373 slot_hide_lookup_table (IMEngineInstanceBase *si)
3375 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3377 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3379 if (ic && ic->impl && _focused_ic == ic)
3380 _panel_client.hide_lookup_table (ic->id);
3384 slot_update_preedit_caret (IMEngineInstanceBase *si, int caret)
3386 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3388 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3390 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
3391 ic->impl->preedit_caret = caret;
3392 if (ic->impl->use_preedit) {
3393 if (!ic->impl->preedit_started) {
3394 ecore_imf_context_preedit_start_event_add (ic->ctx);
3395 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3396 ic->impl->preedit_started = true;
3398 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3399 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3401 _panel_client.update_preedit_caret (ic->id, caret);
3407 slot_update_preedit_string (IMEngineInstanceBase *si,
3408 const WideString & str,
3409 const AttributeList & attrs)
3411 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3413 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3415 if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length ())) {
3416 ic->impl->preedit_string = str;
3417 ic->impl->preedit_attrlist = attrs;
3418 if (ic->impl->use_preedit) {
3419 if (!ic->impl->preedit_started) {
3420 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3421 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3422 ic->impl->preedit_started = true;
3424 ic->impl->preedit_caret = str.length ();
3425 ic->impl->preedit_updating = true;
3426 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3427 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3428 ic->impl->preedit_updating = false;
3430 _panel_client.update_preedit_string (ic->id, str, attrs);
3436 slot_update_aux_string (IMEngineInstanceBase *si,
3437 const WideString & str,
3438 const AttributeList & attrs)
3440 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3442 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3444 if (ic && ic->impl && _focused_ic == ic)
3445 _panel_client.update_aux_string (ic->id, str, attrs);
3449 slot_commit_string (IMEngineInstanceBase *si,
3450 const WideString & str)
3452 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3454 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3456 if (ic && ic->ctx) {
3457 if (strcmp (utf8_wcstombs (str).c_str (), " ") == 0)
3458 autoperiod_insert (ic->ctx);
3460 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (str).c_str ());
3461 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3466 slot_forward_key_event (IMEngineInstanceBase *si,
3467 const KeyEvent & key)
3469 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3471 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3473 if (ic && _focused_ic == ic) {
3474 if (!_fallback_instance->process_key_event (key)) {
3475 feed_key_event (ic, key, true);
3481 slot_update_lookup_table (IMEngineInstanceBase *si,
3482 const LookupTable & table)
3484 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3486 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3488 if (ic && ic->impl && _focused_ic == ic)
3489 _panel_client.update_lookup_table (ic->id, table);
3493 slot_register_properties (IMEngineInstanceBase *si,
3494 const PropertyList & properties)
3496 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3498 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3500 if (ic && ic->impl && _focused_ic == ic)
3501 _panel_client.register_properties (ic->id, properties);
3505 slot_update_property (IMEngineInstanceBase *si,
3506 const Property & property)
3508 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3510 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3512 if (ic && ic->impl && _focused_ic == ic)
3513 _panel_client.update_property (ic->id, property);
3517 slot_beep (IMEngineInstanceBase *si)
3519 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3521 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3523 if (ic && ic->impl && _focused_ic == ic)
3528 slot_start_helper (IMEngineInstanceBase *si,
3529 const String &helper_uuid)
3531 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3533 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3534 << (ic != NULL ? ic->id : -1) << " ic=" << ic
3535 << " ic-uuid=" << ((ic != NULL ) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3538 _panel_client.start_helper (ic->id, helper_uuid);
3542 slot_stop_helper (IMEngineInstanceBase *si,
3543 const String &helper_uuid)
3545 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3547 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic != NULL ? ic->id : -1) << " ic=" << ic << "...\n";
3550 _panel_client.stop_helper (ic->id, helper_uuid);
3554 slot_send_helper_event (IMEngineInstanceBase *si,
3555 const String &helper_uuid,
3556 const Transaction &trans)
3558 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3560 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3561 << (ic != NULL ? ic->id : -1) << " ic=" << ic
3562 << " ic-uuid=" << ((ic != NULL) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3565 _panel_client.send_helper_event (ic->id, helper_uuid, trans);
3569 slot_get_surrounding_text (IMEngineInstanceBase *si,
3575 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3577 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3579 if (ic && ic->impl && _focused_ic == ic) {
3580 char *surrounding = NULL;
3582 if (ecore_imf_context_surrounding_get (_focused_ic->ctx, &surrounding, &cursor_index)) {
3583 SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
3584 SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
3585 WideString before = utf8_mbstowcs (String (surrounding));
3586 if (cursor_index > (int)before.length())
3588 WideString after = before;
3589 before = before.substr (0, cursor_index);
3590 after = after.substr (cursor_index, after.length () - cursor_index);
3591 if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length ())
3592 before = WideString (before.begin () + (before.length () - maxlen_before), before.end ());
3593 else if (maxlen_before == 0)
3594 before = WideString ();
3595 if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length ())
3596 after = WideString (after.begin (), after.begin () + maxlen_after);
3597 else if (maxlen_after == 0)
3598 after = WideString ();
3599 text = before + after;
3600 cursor = before.length ();
3608 slot_delete_surrounding_text (IMEngineInstanceBase *si,
3612 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3614 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3616 if (ic && ic->impl && _focused_ic == ic) {
3617 Ecore_IMF_Event_Delete_Surrounding ev;
3618 ev.ctx = _focused_ic->ctx;
3621 ecore_imf_context_delete_surrounding_event_add (_focused_ic->ctx, offset, len);
3622 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
3629 slot_expand_candidate (IMEngineInstanceBase *si)
3631 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3633 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3635 if (ic && ic->impl && _focused_ic == ic)
3636 _panel_client.expand_candidate (ic->id);
3640 slot_contract_candidate (IMEngineInstanceBase *si)
3642 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3644 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3646 if (ic && ic->impl && _focused_ic == ic)
3647 _panel_client.contract_candidate (ic->id);
3651 slot_set_candidate_style (IMEngineInstanceBase *si, ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line, ISF_CANDIDATE_MODE_T mode)
3653 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3655 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3657 if (ic && ic->impl && _focused_ic == ic)
3658 _panel_client.set_candidate_style (ic->id, portrait_line, mode);
3662 reload_config_callback (const ConfigPointer &config)
3664 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3666 _frontend_hotkey_matcher.load_hotkeys (config);
3667 _imengine_hotkey_matcher.load_hotkeys (config);
3670 scim_string_to_key (key,
3671 config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
3672 String ("Shift+Control+Alt+Lock")));
3674 _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
3675 _valid_key_mask |= SCIM_KEY_ReleaseMask;
3676 // Special treatment for two backslash keys on jp106 keyboard.
3677 _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
3679 _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
3680 _shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
3682 // Get keyboard layout setting
3683 // Flush the global config first, in order to load the new configs from disk.
3684 scim_global_config_flush ();
3686 _keyboard_layout = scim_get_default_keyboard_layout ();
3690 fallback_commit_string_cb (IMEngineInstanceBase *si,
3691 const WideString &str)
3693 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3695 if (_focused_ic && _focused_ic->impl) {
3696 ecore_imf_context_commit_event_add (_focused_ic->ctx, utf8_wcstombs (str).c_str ());
3697 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3702 vi:ts=4:expandtab:nowrap