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 if (ecore_imf_context_input_panel_enabled_get (ctx) == EINA_TRUE)
1139 isf_imf_context_control_focus_in (ctx);
1141 _panel_client.prepare (context_scim->id);
1143 // Handle the "Shared Input Method" mode.
1144 if (_shared_input_method) {
1145 SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
1146 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1147 if (!factory.null ()) {
1148 if (_default_instance.null () || _default_instance->get_factory_uuid () != factory->get_uuid ()) {
1149 _default_instance = factory->create_instance ("UTF-8", _default_instance.null () ? _instance_count++ : _default_instance->get_id ());
1150 attach_instance (_default_instance);
1151 SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id () << " " << _default_instance->get_factory_uuid () << "\n";
1154 context_scim->impl->shared_si = true;
1155 context_scim->impl->si = _default_instance;
1157 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1158 context_scim->impl->preedit_string.clear ();
1159 context_scim->impl->preedit_attrlist.clear ();
1160 context_scim->impl->preedit_caret = 0;
1161 context_scim->impl->preedit_started = false;
1166 } else if (context_scim->impl->shared_si) {
1167 SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
1168 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1169 if (!factory.null ()) {
1170 context_scim->impl->si = factory->create_instance ("UTF-8", _instance_count++);
1171 context_scim->impl->preedit_string.clear ();
1172 context_scim->impl->preedit_attrlist.clear ();
1173 context_scim->impl->preedit_caret = 0;
1174 context_scim->impl->preedit_started = false;
1175 attach_instance (context_scim->impl->si);
1178 context_scim->impl->shared_si = false;
1179 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id () << " " << context_scim->impl->si->get_factory_uuid () << "\n";
1183 context_scim->impl->si->set_frontend_data (static_cast <void*> (context_scim));
1185 if (need_reg) _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
1186 if (need_cap) set_ic_capabilities (context_scim);
1188 panel_req_focus_in (context_scim);
1189 // panel_req_update_spot_location (context_scim);
1190 // panel_req_update_factory_info (context_scim);
1192 if (need_reset) context_scim->impl->si->reset ();
1193 if (context_scim->impl->is_on) {
1194 _panel_client.turn_on (context_scim->id);
1195 // _panel_client.hide_preedit_string (context_scim->id);
1196 // _panel_client.hide_aux_string (context_scim->id);
1197 // _panel_client.hide_lookup_table (context_scim->id);
1198 context_scim->impl->si->focus_in ();
1199 context_scim->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ctx));
1200 set_prediction_allow (context_scim->impl->si, context_scim->impl->prediction_allow);
1201 if (context_scim->impl->imdata)
1202 context_scim->impl->si->set_imdata ((const char *)context_scim->impl->imdata, context_scim->impl->imdata_size);
1204 _panel_client.turn_off (context_scim->id);
1207 _panel_client.send ();
1210 LOGD ("ctx : %p\n", ctx);
1212 if (ecore_imf_context_input_panel_enabled_get (ctx))
1213 ecore_imf_context_input_panel_show (ctx);
1215 LOGD ("ctx : %p input panel enable : FALSE\n", ctx);
1219 * isf_imf_context_focus_out
1220 * @ctx: a #Ecore_IMF_Context
1222 * This function will be called by Ecore IMF.
1224 * Notify the Input Method Context that the widget to which its correspond has lost focus.
1227 isf_imf_context_focus_out (Ecore_IMF_Context *ctx)
1229 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1232 if (!context_scim) return;
1234 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1236 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1238 WideString wstr = context_scim->impl->preedit_string;
1240 LOGD ("ctx : %p\n", ctx);
1242 if (ecore_imf_context_input_panel_enabled_get (ctx))
1243 ecore_imf_context_input_panel_hide (ctx);
1245 if (context_scim->impl->need_commit_preedit) {
1246 panel_slot_hide_preedit_string (context_scim->id);
1248 if (wstr.length ()) {
1249 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1250 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1252 _panel_client.prepare (context_scim->id);
1253 _panel_client.reset_input_context (context_scim->id);
1254 _panel_client.send ();
1257 lock_scr = check_focus_out_by_lockscreen (ctx);
1260 _panel_client.prepare (context_scim->id);
1262 context_scim->impl->si->focus_out ();
1263 context_scim->impl->si->reset ();
1266 // if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1267 _panel_client.focus_out (context_scim->id);
1268 _panel_client.send ();
1275 * isf_imf_context_reset
1276 * @ctx: a #Ecore_IMF_Context
1278 * This function will be called by Ecore IMF.
1280 * Notify the Input Method Context that a change such as a change in cursor
1281 * position has been made. This will typically cause the Input Method Context
1282 * to clear the preedit state.
1285 isf_imf_context_reset (Ecore_IMF_Context *ctx)
1287 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1289 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1291 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1292 WideString wstr = context_scim->impl->preedit_string;
1294 _panel_client.prepare (context_scim->id);
1295 context_scim->impl->si->reset ();
1296 _panel_client.reset_input_context (context_scim->id);
1297 _panel_client.send ();
1299 if (context_scim->impl->need_commit_preedit) {
1300 panel_slot_hide_preedit_string (context_scim->id);
1302 if (wstr.length ()) {
1303 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1304 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1311 * isf_imf_context_cursor_position_set
1312 * @ctx: a #Ecore_IMF_Context
1313 * @cursor_pos: New cursor position in characters.
1315 * This function will be called by Ecore IMF.
1317 * Notify the Input Method Context that a change in the cursor position has been made.
1320 isf_imf_context_cursor_position_set (Ecore_IMF_Context *ctx, int cursor_pos)
1322 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1324 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1326 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1327 if (context_scim->impl->cursor_pos != cursor_pos) {
1328 LOGD ("ctx : %p, cursor pos : %d\n", ctx, cursor_pos);
1329 context_scim->impl->cursor_pos = cursor_pos;
1331 caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1333 if (context_scim->impl->preedit_updating)
1335 _panel_client.prepare (context_scim->id);
1336 context_scim->impl->si->update_cursor_position (cursor_pos);
1337 panel_req_update_cursor_position (context_scim, cursor_pos);
1338 _panel_client.send ();
1344 * isf_imf_context_cursor_location_set
1345 * @ctx: a #Ecore_IMF_Context
1346 * @x: x position of New cursor.
1347 * @y: y position of New cursor.
1348 * @w: the width of New cursor.
1349 * @h: the height of New cursor.
1351 * This function will be called by Ecore IMF.
1353 * Notify the Input Method Context that a change in the cursor location has been made.
1356 isf_imf_context_cursor_location_set (Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
1358 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1360 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1362 int canvas_x, canvas_y;
1363 int new_cursor_x, new_cursor_y;
1365 if (cw == 0 && ch == 0)
1368 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1369 if (context_scim->impl->client_canvas) {
1370 ee = ecore_evas_ecore_evas_get (context_scim->impl->client_canvas);
1373 ecore_evas_geometry_get (ee, &canvas_x, &canvas_y, NULL, NULL);
1376 if (context_scim->impl->client_window)
1377 window_to_screen_geometry_get (context_scim->impl->client_window, &canvas_x, &canvas_y);
1382 new_cursor_x = canvas_x + cx;
1383 new_cursor_y = canvas_y + cy + ch;
1385 // Don't update spot location while updating preedit string.
1386 if (context_scim->impl->preedit_updating && (context_scim->impl->cursor_y == new_cursor_y))
1389 if (context_scim->impl->cursor_x != new_cursor_x || context_scim->impl->cursor_y != new_cursor_y) {
1390 context_scim->impl->cursor_x = new_cursor_x;
1391 context_scim->impl->cursor_y = new_cursor_y;
1392 context_scim->impl->cursor_top_y = canvas_y + cy;
1393 _panel_client.prepare (context_scim->id);
1394 panel_req_update_spot_location (context_scim);
1395 _panel_client.send ();
1396 SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
1402 * isf_imf_context_input_mode_set
1403 * @ctx: a #Ecore_IMF_Context
1404 * @input_mode: the input mode
1406 * This function will be called by Ecore IMF.
1408 * To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
1409 * is in Ecore_IMF.h.
1412 isf_imf_context_input_mode_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
1414 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1416 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1417 if (context_scim && context_scim->impl) {
1418 context_scim->impl->input_mode = input_mode;
1423 * isf_imf_context_preedit_string_get
1424 * @ctx: a #Ecore_IMF_Context
1425 * @str: the preedit string
1426 * @cursor_pos: the cursor position
1428 * This function will be called by Ecore IMF.
1430 * To get the preedit string of the input method.
1433 isf_imf_context_preedit_string_get (Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
1435 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1437 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1439 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1440 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1444 *str = strdup (mbs.c_str ());
1450 *cursor_pos = context_scim->impl->preedit_caret;
1462 isf_imf_context_preedit_string_with_attributes_get (Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
1464 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1466 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1468 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1469 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1473 *str = strdup (mbs.c_str ());
1479 *cursor_pos = context_scim->impl->preedit_caret;
1483 if (mbs.length ()) {
1484 int start_index, end_index;
1485 int wlen = context_scim->impl->preedit_string.length ();
1486 Ecore_IMF_Preedit_Attr *attr = NULL;
1487 AttributeList::const_iterator i;
1488 bool *attrs_flag = new bool [mbs.length ()];
1489 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1490 for (i = context_scim->impl->preedit_attrlist.begin ();
1491 i != context_scim->impl->preedit_attrlist.end (); ++i) {
1492 start_index = i->get_start ();
1493 end_index = i->get_end ();
1494 if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1495 start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1496 end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1497 if (i->get_type () == SCIM_ATTR_DECORATE) {
1498 attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof (Ecore_IMF_Preedit_Attr));
1501 attr->start_index = start_index;
1502 attr->end_index = end_index;
1504 if (i->get_value () == SCIM_ATTR_DECORATE_UNDERLINE) {
1505 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1506 *attrs = eina_list_append (*attrs, (void *)attr);
1507 } else if (i->get_value () == SCIM_ATTR_DECORATE_REVERSE) {
1508 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1509 *attrs = eina_list_append (*attrs, (void *)attr);
1510 } else if (i->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
1511 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
1512 *attrs = eina_list_append (*attrs, (void *)attr);
1513 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR1) {
1514 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
1515 *attrs = eina_list_append (*attrs, (void *)attr);
1516 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR2) {
1517 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
1518 *attrs = eina_list_append (*attrs, (void *)attr);
1519 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR3) {
1520 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
1521 *attrs = eina_list_append (*attrs, (void *)attr);
1522 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR4) {
1523 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
1524 *attrs = eina_list_append (*attrs, (void *)attr);
1528 switch(i->get_value())
1530 case SCIM_ATTR_DECORATE_UNDERLINE:
1531 case SCIM_ATTR_DECORATE_REVERSE:
1532 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1533 case SCIM_ATTR_DECORATE_BGCOLOR1:
1534 case SCIM_ATTR_DECORATE_BGCOLOR2:
1535 case SCIM_ATTR_DECORATE_BGCOLOR3:
1536 case SCIM_ATTR_DECORATE_BGCOLOR4:
1537 // Record which character has attribute.
1538 for (int pos = start_index; pos < end_index; ++pos)
1539 attrs_flag [pos] = 1;
1544 } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1545 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1546 } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1547 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1551 // Add underline for all characters which don't have attribute.
1552 for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1553 if (!attrs_flag [pos]) {
1554 int begin_pos = pos;
1555 while (pos < mbs.length () && !attrs_flag [pos])
1557 // use REVERSE style as default
1558 attr = (Ecore_IMF_Preedit_Attr *)calloc (1, sizeof (Ecore_IMF_Preedit_Attr));
1561 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1562 attr->start_index = begin_pos;
1563 attr->end_index = pos;
1564 *attrs = eina_list_append(*attrs, (void *)attr);
1567 delete [] attrs_flag;
1583 * isf_imf_context_use_preedit_set
1584 * @ctx: a #Ecore_IMF_Context
1585 * @use_preedit: Whether the IM context should use the preedit string.
1587 * This function will be called by Ecore IMF.
1589 * Set whether the IM context should use the preedit string to display feedback.
1590 * If is 0 (default is 1), then the IM context may use some other method to
1591 * display feedback, such as displaying it in a child of the root window.
1594 isf_imf_context_use_preedit_set (Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
1596 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (use_preedit == EINA_TRUE ? "true" : "false") << "...\n";
1598 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1600 if (!_on_the_spot) return;
1602 if (context_scim && context_scim->impl) {
1603 bool old = context_scim->impl->use_preedit;
1604 context_scim->impl->use_preedit = use_preedit;
1605 if (context_scim == _focused_ic) {
1606 _panel_client.prepare (context_scim->id);
1608 if (old != use_preedit)
1609 set_ic_capabilities (context_scim);
1611 if (context_scim->impl->preedit_string.length ())
1612 slot_show_preedit_string (context_scim->impl->si);
1614 _panel_client.send ();
1620 * isf_imf_context_prediction_allow_set
1621 * @ctx: a #Ecore_IMF_Context
1622 * @prediction: Whether the IM context should use the prediction.
1624 * This function will be called by Ecore IMF.
1626 * Set whether the IM context should use the prediction.
1629 isf_imf_context_prediction_allow_set (Ecore_IMF_Context* ctx, Eina_Bool prediction)
1631 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction == EINA_TRUE ? "true" : "false") << "...\n";
1633 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1635 if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction) {
1636 context_scim->impl->prediction_allow = prediction;
1637 set_prediction_allow (context_scim->impl->si, prediction);
1642 * isf_imf_context_prediction_allow_get
1643 * @ctx: a #Ecore_IMF_Context
1645 * This function will be called by Ecore IMF.
1647 * To get prediction allow flag for the IM context.
1649 * Return value: the prediction allow flag for the IM context
1652 isf_imf_context_prediction_allow_get (Ecore_IMF_Context* ctx)
1654 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1656 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1658 Eina_Bool ret = EINA_FALSE;
1659 if (context_scim && context_scim->impl) {
1660 ret = context_scim->impl->prediction_allow;
1662 std::cerr << __FUNCTION__ << " failed!!!\n";
1668 * isf_imf_context_autocapital_type_set
1669 * @ctx: a #Ecore_IMF_Context
1670 * @autocapital_type: the autocapital type for the IM context.
1672 * This function will be called by Ecore IMF.
1674 * Set autocapital type for the IM context.
1677 isf_imf_context_autocapital_type_set (Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1679 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1681 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1683 if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1684 context_scim->impl->autocapital_type = autocapital_type;
1689 * isf_imf_context_filter_event
1690 * @ctx: a #Ecore_IMF_Context
1691 * @type: The type of event defined by Ecore_IMF_Event_Type.
1692 * @event: The event itself.
1693 * Return value: %TRUE if the input method handled the key event.
1695 * This function will be called by Ecore IMF.
1697 * Allow an Ecore Input Context to internally handle an event. If this function
1698 * returns 1, then no further processing should be done for this event. Input
1699 * methods must be able to accept all types of events (simply returning 0 if
1700 * the event was not handled), but there is no obligation of any events to be
1701 * submitted to this function.
1704 isf_imf_context_filter_event (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
1706 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1708 EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1709 Eina_Bool ret = EINA_FALSE;
1711 if (ic == NULL || ic->impl == NULL)
1715 unsigned int timestamp;
1717 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1718 Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
1719 timestamp = ev->timestamp;
1720 scim_string_to_key (key, ev->key);
1721 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1722 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1723 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1724 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1725 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1726 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1727 } else if (type == ECORE_IMF_EVENT_KEY_UP) {
1728 Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
1729 timestamp = ev->timestamp;
1730 scim_string_to_key (key, ev->key);
1731 key.mask = SCIM_KEY_ReleaseMask;
1732 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1733 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1734 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1735 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1736 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1737 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1738 } else if (type == ECORE_IMF_EVENT_MOUSE_UP) {
1739 if (ecore_imf_context_input_panel_enabled_get (ctx)) {
1740 LOGD ("[Mouse-up event] ctx : %p\n", ctx);
1741 if (ic == _focused_ic)
1742 ecore_imf_context_input_panel_show (ctx);
1744 LOGW ("Can't show IME because there is no focus. ctx : %p\n", ctx);
1751 key.mask &= _valid_key_mask;
1753 _panel_client.prepare (ic->id);
1756 if (!filter_hotkeys (ic, key)) {
1757 if (timestamp == 0) {
1759 // in case of generated event
1760 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1761 char code = key.get_ascii_code ();
1762 if (isgraph (code)) {
1763 char string[2] = {0};
1764 snprintf (string, sizeof (string), "%c", code);
1766 if (strlen (string) != 0) {
1767 ecore_imf_context_commit_event_add (ic->ctx, string);
1768 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)string);
1769 caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1774 _panel_client.send ();
1778 if (!_focused_ic || !_focused_ic->impl->is_on ||
1779 !_focused_ic->impl->si->process_key_event (key)) {
1784 _panel_client.send ();
1790 * Set up an ISE specific data
1792 * @param[in] ctx a #Ecore_IMF_Context
1793 * @param[in] data pointer of data to sets up to ISE
1794 * @param[in] length length of data
1796 EAPI void isf_imf_context_imdata_set (Ecore_IMF_Context *ctx, const void* data, int length)
1798 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " data length ( " << length << ") ...\n";
1799 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1801 if (context_scim == NULL || data == NULL || length <= 0)
1804 if (context_scim && context_scim->impl) {
1805 if (context_scim->impl->imdata)
1806 free (context_scim->impl->imdata);
1808 context_scim->impl->imdata = calloc (1, length);
1809 memcpy (context_scim->impl->imdata, data, length);
1810 context_scim->impl->imdata_size = length;
1812 if (context_scim->impl->si && _focused_ic == context_scim) {
1813 _panel_client.prepare (context_scim->id);
1814 context_scim->impl->si->set_imdata ((const char *)data, length);
1815 _panel_client.send ();
1819 isf_imf_context_input_panel_imdata_set (ctx, data, length);
1823 * Get the ISE specific data from ISE
1825 * @param[in] ctx a #Ecore_IMF_Context
1826 * @param[out] data pointer of data to return
1827 * @param[out] length length of data
1829 EAPI void isf_imf_context_imdata_get (Ecore_IMF_Context *ctx, void* data, int* length)
1831 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1833 isf_imf_context_input_panel_imdata_get (ctx, data, length);
1836 /* Panel Slot functions */
1838 panel_slot_reload_config (int context)
1840 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1846 panel_slot_exit (int /* context */)
1848 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1854 panel_slot_update_candidate_item_layout (int context, const std::vector<uint32> &row_items)
1856 EcoreIMFContextISF *ic = find_ic (context);
1857 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " row size=" << row_items.size () << " ic=" << ic << "\n";
1858 if (ic && ic->impl) {
1859 _panel_client.prepare (ic->id);
1860 ic->impl->si->update_candidate_item_layout (row_items);
1861 _panel_client.send ();
1866 panel_slot_update_lookup_table_page_size (int context, int page_size)
1868 EcoreIMFContextISF *ic = find_ic (context);
1869 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
1870 if (ic && ic->impl) {
1871 _panel_client.prepare (ic->id);
1872 ic->impl->si->update_lookup_table_page_size (page_size);
1873 _panel_client.send ();
1878 panel_slot_lookup_table_page_up (int context)
1880 EcoreIMFContextISF *ic = find_ic (context);
1881 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1882 if (ic && ic->impl) {
1883 _panel_client.prepare (ic->id);
1884 ic->impl->si->lookup_table_page_up ();
1885 _panel_client.send ();
1890 panel_slot_lookup_table_page_down (int context)
1892 EcoreIMFContextISF *ic = find_ic (context);
1893 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1894 if (ic && ic->impl) {
1895 _panel_client.prepare (ic->id);
1896 ic->impl->si->lookup_table_page_down ();
1897 _panel_client.send ();
1902 panel_slot_trigger_property (int context, const String &property)
1904 EcoreIMFContextISF *ic = find_ic (context);
1905 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
1906 if (ic && ic->impl) {
1907 _panel_client.prepare (ic->id);
1908 ic->impl->si->trigger_property (property);
1909 _panel_client.send ();
1914 panel_slot_process_helper_event (int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
1916 EcoreIMFContextISF *ic = find_ic (context);
1917 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
1918 << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic != NULL ? ic->impl : 0) << " ic-uuid="
1919 << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "" ) << "\n";
1920 if (ic && ic->impl && ic->impl->si->get_factory_uuid () == target_uuid) {
1921 _panel_client.prepare (ic->id);
1922 SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
1923 ic->impl->si->process_helper_event (helper_uuid, trans);
1924 _panel_client.send ();
1929 panel_slot_move_preedit_caret (int context, int caret_pos)
1931 EcoreIMFContextISF *ic = find_ic (context);
1932 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
1933 if (ic && ic->impl) {
1934 _panel_client.prepare (ic->id);
1935 ic->impl->si->move_preedit_caret (caret_pos);
1936 _panel_client.send ();
1941 panel_slot_update_preedit_caret (int context, int caret)
1943 EcoreIMFContextISF *ic = find_ic (context);
1944 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
1946 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
1947 ic->impl->preedit_caret = caret;
1948 if (ic->impl->use_preedit) {
1949 if (!ic->impl->preedit_started) {
1950 ecore_imf_context_preedit_start_event_add (ic->ctx);
1951 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
1952 ic->impl->preedit_started = true;
1954 ecore_imf_context_preedit_changed_event_add (ic->ctx);
1955 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1957 _panel_client.prepare (ic->id);
1958 _panel_client.update_preedit_caret (ic->id, caret);
1959 _panel_client.send ();
1965 panel_slot_select_aux (int context, int aux_index)
1967 EcoreIMFContextISF *ic = find_ic (context);
1968 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " aux=" << aux_index << " ic=" << ic << "\n";
1969 if (ic && ic->impl) {
1970 _panel_client.prepare (ic->id);
1971 ic->impl->si->select_aux (aux_index);
1972 _panel_client.send ();
1977 panel_slot_select_candidate (int context, int cand_index)
1979 EcoreIMFContextISF *ic = find_ic (context);
1980 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
1981 if (ic && ic->impl) {
1982 _panel_client.prepare (ic->id);
1983 ic->impl->si->select_candidate (cand_index);
1984 _panel_client.send ();
1989 _keyname_to_keycode (const char *keyname)
1993 Display *display = (Display *)ecore_x_display_get ();
1995 keysym = XStringToKeysym (keyname);
1997 if (!strncmp (keyname, "Keycode-", 8)) {
1998 keycode = atoi (keyname + 8);
2000 keycode = XKeysymToKeycode (display, keysym);
2007 feed_key_event (EcoreIMFContextISF *ic, const KeyEvent &key, bool fake)
2009 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2011 if (key.code <= 0x7F ||
2012 (key.code >= SCIM_KEY_BackSpace && key.code <= SCIM_KEY_Delete) ||
2013 (key.code >= SCIM_KEY_Home && key.code <= SCIM_KEY_Hyper_R)) {
2014 // ascii code and function keys
2015 send_x_key_event (key, fake);
2023 panel_slot_process_key_event (int context, const KeyEvent &key)
2025 EcoreIMFContextISF *ic = find_ic (context);
2026 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2028 if (feed_key_event (ic, key, false) == EINA_TRUE) return;
2030 if (ic && ic->impl) {
2031 _panel_client.prepare (ic->id);
2033 if (!filter_hotkeys (ic, key)) {
2034 if (!_focused_ic || !_focused_ic->impl->is_on ||
2035 !_focused_ic->impl->si->process_key_event (key)) {
2036 _fallback_instance->process_key_event (key);
2040 _panel_client.send ();
2045 panel_slot_commit_string (int context, const WideString &wstr)
2047 EcoreIMFContextISF *ic = find_ic (context);
2048 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2050 if (ic && ic->impl) {
2051 if (_focused_ic != ic)
2054 if (ic->impl->need_commit_preedit)
2055 panel_slot_hide_preedit_string (ic->id);
2056 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2057 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2062 panel_slot_forward_key_event (int context, const KeyEvent &key)
2064 EcoreIMFContextISF *ic = find_ic (context);
2065 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2067 if (strlen (key.get_key_string ().c_str ()) >= 116)
2070 feed_key_event (ic, key, true);
2074 panel_slot_request_help (int context)
2076 EcoreIMFContextISF *ic = find_ic (context);
2077 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2078 if (ic && ic->impl) {
2079 _panel_client.prepare (ic->id);
2080 panel_req_show_help (ic);
2081 _panel_client.send ();
2086 panel_slot_request_factory_menu (int context)
2088 EcoreIMFContextISF *ic = find_ic (context);
2089 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2090 if (ic && ic->impl) {
2091 _panel_client.prepare (ic->id);
2092 panel_req_show_factory_menu (ic);
2093 _panel_client.send ();
2098 panel_slot_change_factory (int context, const String &uuid)
2100 EcoreIMFContextISF *ic = find_ic (context);
2101 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
2102 if (ic && ic->impl) {
2103 _panel_client.prepare (ic->id);
2104 ic->impl->si->reset ();
2105 open_specific_factory (ic, uuid);
2106 _panel_client.send ();
2111 panel_slot_reset_keyboard_ise (int context)
2113 EcoreIMFContextISF *ic = find_ic (context);
2114 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2115 if (ic && ic->impl) {
2116 WideString wstr = ic->impl->preedit_string;
2117 if (ic->impl->need_commit_preedit) {
2118 panel_slot_hide_preedit_string (ic->id);
2120 if (wstr.length ()) {
2121 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2122 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2125 _panel_client.prepare (ic->id);
2126 ic->impl->si->reset ();
2127 _panel_client.send ();
2132 panel_slot_update_keyboard_ise (int context)
2134 EcoreIMFContextISF *ic = find_ic (context);
2135 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2137 _backend->add_module (_config, "socket", false);
2141 panel_slot_show_preedit_string (int context)
2143 EcoreIMFContextISF *ic = find_ic (context);
2144 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << "\n";
2146 if (ic && ic->impl && _focused_ic == ic) {
2147 if (!ic->impl->is_on)
2148 ic->impl->is_on = true;
2150 if (ic->impl->use_preedit) {
2151 if (!ic->impl->preedit_started) {
2152 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
2153 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2154 ic->impl->preedit_started = true;
2155 ic->impl->need_commit_preedit = true;
2158 _panel_client.prepare (ic->id);
2159 _panel_client.show_preedit_string (ic->id);
2160 _panel_client.send ();
2166 panel_slot_hide_preedit_string (int context)
2168 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2170 EcoreIMFContextISF *ic = find_ic (context);
2172 if (ic && ic->impl && _focused_ic == ic) {
2173 if (!ic->impl->is_on)
2174 ic->impl->is_on = true;
2177 if (ic->impl->preedit_string.length ()) {
2178 ic->impl->preedit_string = WideString ();
2179 ic->impl->preedit_caret = 0;
2180 ic->impl->preedit_attrlist.clear ();
2183 if (ic->impl->use_preedit) {
2185 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2186 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2188 if (ic->impl->preedit_started) {
2189 ecore_imf_context_preedit_end_event_add (ic->ctx);
2190 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2191 ic->impl->preedit_started = false;
2192 ic->impl->need_commit_preedit = false;
2195 _panel_client.prepare (ic->id);
2196 _panel_client.hide_preedit_string (ic->id);
2197 _panel_client.send ();
2203 panel_slot_update_preedit_string (int context,
2204 const WideString &str,
2205 const AttributeList &attrs)
2207 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2209 EcoreIMFContextISF *ic = find_ic (context);
2211 if (ic && ic->impl && _focused_ic == ic) {
2212 if (!ic->impl->is_on)
2213 ic->impl->is_on = true;
2215 if (ic->impl->preedit_string != str || str.length ()) {
2216 ic->impl->preedit_string = str;
2217 ic->impl->preedit_attrlist = attrs;
2219 if (ic->impl->use_preedit) {
2220 if (!ic->impl->preedit_started) {
2221 ecore_imf_context_preedit_start_event_add (ic->ctx);
2222 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2223 ic->impl->preedit_started = true;
2224 ic->impl->need_commit_preedit = true;
2226 ic->impl->preedit_caret = str.length ();
2227 ic->impl->preedit_updating = true;
2228 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2229 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2230 ic->impl->preedit_updating = false;
2232 _panel_client.prepare (ic->id);
2233 _panel_client.update_preedit_string (ic->id, str, attrs);
2234 _panel_client.send ();
2241 panel_slot_get_surrounding_text (int context, int maxlen_before, int maxlen_after)
2243 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2245 EcoreIMFContextISF *ic = find_ic (context);
2247 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2249 WideString text = WideString ();
2250 slot_get_surrounding_text (ic->impl->si, text, cursor, maxlen_before, maxlen_after);
2251 _panel_client.prepare (ic->id);
2252 _panel_client.update_surrounding_text (ic->id, text, cursor);
2253 _panel_client.send ();
2258 panel_slot_delete_surrounding_text (int context, int offset, int len)
2260 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2262 EcoreIMFContextISF *ic = find_ic (context);
2264 if (ic && ic->impl && _focused_ic == ic && ic->impl->si)
2265 slot_delete_surrounding_text (ic->impl->si, offset, len);
2269 panel_slot_update_displayed_candidate_number (int context, int number)
2271 EcoreIMFContextISF *ic = find_ic (context);
2272 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " number=" << number << " ic=" << ic << "\n";
2273 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2274 _panel_client.prepare (ic->id);
2275 ic->impl->si->update_displayed_candidate_number (number);
2276 _panel_client.send ();
2281 panel_slot_candidate_more_window_show (int context)
2283 EcoreIMFContextISF *ic = find_ic (context);
2284 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2285 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2286 _panel_client.prepare (ic->id);
2287 ic->impl->si->candidate_more_window_show ();
2288 _panel_client.send ();
2293 panel_slot_candidate_more_window_hide (int context)
2295 EcoreIMFContextISF *ic = find_ic (context);
2296 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2297 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2298 _panel_client.prepare (ic->id);
2299 ic->impl->si->candidate_more_window_hide ();
2300 _panel_client.send ();
2305 panel_slot_longpress_candidate (int context, int index)
2307 EcoreIMFContextISF *ic = find_ic (context);
2308 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " index=" << index << " ic=" << ic << "\n";
2309 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2310 _panel_client.prepare (ic->id);
2311 ic->impl->si->longpress_candidate (index);
2312 _panel_client.send ();
2317 panel_slot_update_client_id (int context, int client_id)
2319 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " client_id=" << client_id << "\n";
2321 _panel_client_id = client_id;
2324 /* Panel Requestion functions. */
2326 panel_req_show_help (EcoreIMFContextISF *ic)
2328 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2332 help = String (_("Smart Common Input Method platform ")) +
2333 String (SCIM_VERSION) +
2334 String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2336 if (ic && ic->impl) {
2337 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2339 help += utf8_wcstombs (sf->get_name ());
2340 help += String (_(":\n\n"));
2342 help += utf8_wcstombs (sf->get_help ());
2343 help += String (_("\n\n"));
2345 help += utf8_wcstombs (sf->get_credits ());
2347 _panel_client.show_help (ic->id, help);
2352 panel_req_show_factory_menu (EcoreIMFContextISF *ic)
2354 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2356 std::vector<IMEngineFactoryPointer> factories;
2357 std::vector <PanelFactoryInfo> menu;
2359 _backend->get_factories_for_encoding (factories, "UTF-8");
2361 for (size_t i = 0; i < factories.size (); ++ i) {
2362 menu.push_back (PanelFactoryInfo (
2363 factories [i]->get_uuid (),
2364 utf8_wcstombs (factories [i]->get_name ()),
2365 factories [i]->get_language (),
2366 factories [i]->get_icon_file ()));
2370 _panel_client.show_factory_menu (ic->id, menu);
2374 panel_req_update_factory_info (EcoreIMFContextISF *ic)
2376 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2378 if (ic && ic->impl && ic == _focused_ic) {
2379 PanelFactoryInfo info;
2380 if (ic->impl->is_on) {
2381 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2383 info = PanelFactoryInfo (sf->get_uuid (), utf8_wcstombs (sf->get_name ()), sf->get_language (), sf->get_icon_file ());
2385 info = PanelFactoryInfo (String (""), String (_("English/Keyboard")), String ("C"), String (SCIM_KEYBOARD_ICON_FILE));
2387 _panel_client.update_factory_info (ic->id, info);
2392 panel_req_focus_in (EcoreIMFContextISF *ic)
2394 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2396 _panel_client.focus_in (ic->id, ic->impl->si->get_factory_uuid ());
2400 panel_req_update_spot_location (EcoreIMFContextISF *ic)
2402 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2404 _panel_client.update_spot_location (ic->id, ic->impl->cursor_x, ic->impl->cursor_y, ic->impl->cursor_top_y);
2408 panel_req_update_cursor_position (EcoreIMFContextISF *ic, int cursor_pos)
2410 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2412 _panel_client.update_cursor_position (ic->id, cursor_pos);
2416 filter_hotkeys (EcoreIMFContextISF *ic, const KeyEvent &key)
2418 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2422 _frontend_hotkey_matcher.push_key_event (key);
2423 _imengine_hotkey_matcher.push_key_event (key);
2425 FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result ();
2427 if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER) {
2428 if (!ic->impl->is_on)
2433 _display_input_language (ic);
2435 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON) {
2436 if (!ic->impl->is_on) {
2438 _display_input_language (ic);
2441 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF) {
2442 if (ic->impl->is_on) {
2444 _display_input_language (ic);
2447 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY) {
2448 open_next_factory (ic);
2450 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY) {
2451 open_previous_factory (ic);
2453 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU) {
2454 panel_req_show_factory_menu (ic);
2456 } else if (_imengine_hotkey_matcher.is_matched ()) {
2457 ISEInfo info = _imengine_hotkey_matcher.get_match_result ();
2458 ISE_TYPE type = info.type;
2459 if (type == IMENGINE_T)
2460 open_specific_factory (ic, info.uuid);
2461 else if (type == HELPER_T)
2462 _panel_client.start_helper (ic->id, info.uuid);
2469 panel_initialize (void)
2471 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2473 String display_name;
2475 const char *p = getenv ("DISPLAY");
2476 if (p) display_name = String (p);
2479 if (_panel_client.open_connection (_config->get_name (), display_name) >= 0) {
2480 int fd = _panel_client.get_connection_number ();
2482 _panel_iochannel_read_handler = ecore_main_fd_handler_add (fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
2483 // _panel_iochannel_err_handler = ecore_main_fd_handler_add (fd, ECORE_FD_ERROR, panel_iochannel_handler, NULL, NULL, NULL);
2485 SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
2487 EcoreIMFContextISF *context_scim = _ic_list;
2488 while (context_scim != NULL) {
2489 _panel_client.prepare (context_scim->id);
2490 _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
2491 _panel_client.send ();
2492 context_scim = context_scim->next;
2496 _panel_client.prepare (_focused_ic->id);
2497 panel_req_focus_in (_focused_ic);
2498 _panel_client.send ();
2503 std::cerr << "panel_initialize () failed!!!\n";
2508 panel_finalize (void)
2510 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2512 _panel_client.close_connection ();
2514 if (_panel_iochannel_read_handler) {
2515 ecore_main_fd_handler_del (_panel_iochannel_read_handler);
2516 _panel_iochannel_read_handler = 0;
2518 if (_panel_iochannel_err_handler) {
2519 ecore_main_fd_handler_del (_panel_iochannel_err_handler);
2520 _panel_iochannel_err_handler = 0;
2525 panel_iochannel_handler (void *data, Ecore_Fd_Handler *fd_handler)
2527 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2529 if (fd_handler == _panel_iochannel_read_handler) {
2530 if (_panel_client.has_pending_event () && !_panel_client.filter_event ()) {
2532 panel_initialize ();
2533 return ECORE_CALLBACK_CANCEL;
2535 } else if (fd_handler == _panel_iochannel_err_handler) {
2537 panel_initialize ();
2538 return ECORE_CALLBACK_CANCEL;
2540 return ECORE_CALLBACK_RENEW;
2544 turn_on_ic (EcoreIMFContextISF *ic)
2546 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2548 if (ic && ic->impl && !ic->impl->is_on) {
2549 ic->impl->is_on = true;
2551 if (ic == _focused_ic) {
2552 panel_req_focus_in (ic);
2553 // panel_req_update_spot_location (ic);
2554 panel_req_update_factory_info (ic);
2555 _panel_client.turn_on (ic->id);
2556 // _panel_client.hide_preedit_string (ic->id);
2557 // _panel_client.hide_aux_string (ic->id);
2558 // _panel_client.hide_lookup_table (ic->id);
2559 ic->impl->si->focus_in ();
2560 ic->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ic->ctx));
2561 set_prediction_allow (ic->impl->si, ic->impl->prediction_allow);
2564 //Record the IC on/off status
2565 if (_shared_input_method) {
2566 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
2570 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2571 ecore_imf_context_preedit_start_event_add (ic->ctx);
2572 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2573 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2574 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2575 ic->impl->preedit_started = true;
2581 turn_off_ic (EcoreIMFContextISF *ic)
2583 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2585 if (ic && ic->impl && ic->impl->is_on) {
2586 ic->impl->is_on = false;
2588 if (ic == _focused_ic) {
2589 ic->impl->si->focus_out ();
2591 // panel_req_update_factory_info (ic);
2592 _panel_client.turn_off (ic->id);
2595 //Record the IC on/off status
2596 if (_shared_input_method) {
2597 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2601 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2602 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2603 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2604 ecore_imf_context_preedit_end_event_add (ic->ctx);
2605 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2606 ic->impl->preedit_started = false;
2612 set_ic_capabilities (EcoreIMFContextISF *ic)
2614 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2616 if (ic && ic->impl) {
2617 unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2619 if (!_on_the_spot || !ic->impl->use_preedit)
2620 cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2622 ic->impl->si->update_client_capabilities (cap);
2627 check_socket_frontend (void)
2629 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2631 SocketAddress address;
2632 SocketClient client;
2636 address.set_address (scim_get_default_socket_frontend_address ());
2638 if (!client.connect (address))
2641 if (!scim_socket_open_connection (magic,
2642 String ("ConnectionTester"),
2643 String ("SocketFrontEnd"),
2655 std::vector<String> config_list;
2656 std::vector<String> engine_list;
2657 std::vector<String> helper_list;
2658 std::vector<String> load_engine_list;
2660 std::vector<String>::iterator it;
2662 bool manual = false;
2664 String config_module_name = "simple";
2666 SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore ISF IMModule...\n";
2668 // Get system language.
2669 _language = scim_get_locale_language (scim_get_current_locale ());
2672 // If no Socket FrontEnd is running, then launch one.
2673 // And set manual to false.
2674 bool check_result = check_socket_frontend ();
2675 if (!check_result) {
2676 std::cerr << "Launching a ISF daemon with Socket FrontEnd...\n";
2678 scim_get_imengine_module_list (engine_list);
2679 scim_get_helper_module_list (helper_list);
2681 for (it = engine_list.begin (); it != engine_list.end (); it++) {
2682 if (*it != "socket")
2683 load_engine_list.push_back (*it);
2685 for (it = helper_list.begin (); it != helper_list.end (); it++)
2686 load_engine_list.push_back (*it);
2687 const char *new_argv [] = { "--no-stay", 0 };
2690 (load_engine_list.size () > 0 ? scim_combine_string_list (load_engine_list, ',') : "none"),
2696 // If there is one Socket FrontEnd running and it's not manual mode,
2697 // then just use this Socket Frontend.
2699 for (int i = 0; i < 200; ++i) {
2701 config_module_name = "socket";
2702 load_engine_list.clear ();
2703 load_engine_list.push_back ("socket");
2706 scim_usleep (50000);
2707 check_result = check_socket_frontend ();
2712 if (config_module_name != "dummy") {
2713 //load config module
2714 SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
2715 _config_module = new ConfigModule (config_module_name);
2717 //create config instance
2718 if (_config_module != NULL && _config_module->valid ())
2719 _config = _config_module->create_config ();
2722 if (_config.null ()) {
2723 SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
2725 if (_config_module) delete _config_module;
2726 _config_module = NULL;
2728 _config = new DummyConfig ();
2729 config_module_name = "dummy";
2732 reload_config_callback (_config);
2733 _config->signal_connect_reload (slot (reload_config_callback));
2736 _backend = new CommonBackEnd (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list);
2738 if (_backend.null ()) {
2739 std::cerr << "Cannot create BackEnd Object!\n";
2741 _backend->initialize (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list, false, false);
2742 _fallback_factory = _backend->get_factory (SCIM_COMPOSE_KEY_FACTORY_UUID);
2745 if (_fallback_factory.null ())
2746 _fallback_factory = new DummyIMEngineFactory ();
2748 _fallback_instance = _fallback_factory->create_instance (String ("UTF-8"), 0);
2749 _fallback_instance->signal_connect_commit_string (slot (fallback_commit_string_cb));
2751 // Attach Panel Client signal.
2752 _panel_client.signal_connect_reload_config (slot (panel_slot_reload_config));
2753 _panel_client.signal_connect_exit (slot (panel_slot_exit));
2754 _panel_client.signal_connect_update_candidate_item_layout (slot (panel_slot_update_candidate_item_layout));
2755 _panel_client.signal_connect_update_lookup_table_page_size (slot (panel_slot_update_lookup_table_page_size));
2756 _panel_client.signal_connect_lookup_table_page_up (slot (panel_slot_lookup_table_page_up));
2757 _panel_client.signal_connect_lookup_table_page_down (slot (panel_slot_lookup_table_page_down));
2758 _panel_client.signal_connect_trigger_property (slot (panel_slot_trigger_property));
2759 _panel_client.signal_connect_process_helper_event (slot (panel_slot_process_helper_event));
2760 _panel_client.signal_connect_move_preedit_caret (slot (panel_slot_move_preedit_caret));
2761 _panel_client.signal_connect_update_preedit_caret (slot (panel_slot_update_preedit_caret));
2762 _panel_client.signal_connect_select_aux (slot (panel_slot_select_aux));
2763 _panel_client.signal_connect_select_candidate (slot (panel_slot_select_candidate));
2764 _panel_client.signal_connect_process_key_event (slot (panel_slot_process_key_event));
2765 _panel_client.signal_connect_commit_string (slot (panel_slot_commit_string));
2766 _panel_client.signal_connect_forward_key_event (slot (panel_slot_forward_key_event));
2767 _panel_client.signal_connect_request_help (slot (panel_slot_request_help));
2768 _panel_client.signal_connect_request_factory_menu (slot (panel_slot_request_factory_menu));
2769 _panel_client.signal_connect_change_factory (slot (panel_slot_change_factory));
2770 _panel_client.signal_connect_reset_keyboard_ise (slot (panel_slot_reset_keyboard_ise));
2771 _panel_client.signal_connect_update_keyboard_ise (slot (panel_slot_update_keyboard_ise));
2772 _panel_client.signal_connect_show_preedit_string (slot (panel_slot_show_preedit_string));
2773 _panel_client.signal_connect_hide_preedit_string (slot (panel_slot_hide_preedit_string));
2774 _panel_client.signal_connect_update_preedit_string (slot (panel_slot_update_preedit_string));
2775 _panel_client.signal_connect_get_surrounding_text (slot (panel_slot_get_surrounding_text));
2776 _panel_client.signal_connect_delete_surrounding_text (slot (panel_slot_delete_surrounding_text));
2777 _panel_client.signal_connect_update_displayed_candidate_number (slot (panel_slot_update_displayed_candidate_number));
2778 _panel_client.signal_connect_candidate_more_window_show (slot (panel_slot_candidate_more_window_show));
2779 _panel_client.signal_connect_candidate_more_window_hide (slot (panel_slot_candidate_more_window_hide));
2780 _panel_client.signal_connect_longpress_candidate (slot (panel_slot_longpress_candidate));
2781 _panel_client.signal_connect_update_client_id (slot (panel_slot_update_client_id));
2783 if (!panel_initialize ()) {
2784 std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
2791 SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
2793 // Reset this first so that the shared instance could be released correctly afterwards.
2794 _default_instance.reset ();
2796 SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2797 while (_used_ic_impl_list) {
2798 // In case in "shared input method" mode,
2799 // all contexts share only one instance,
2800 // so we need point the reference pointer correctly before finalizing.
2801 _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2802 isf_imf_context_del (_used_ic_impl_list->parent->ctx);
2805 delete_all_ic_impl ();
2807 _fallback_instance.reset ();
2808 _fallback_factory.reset ();
2810 SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
2813 SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2816 if (_config_module) {
2817 SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
2818 delete _config_module;
2825 _scim_initialized = false;
2827 _panel_client.reset_signal_handler ();
2832 _popup_message (const char *_ptext)
2837 notification_status_message_post(_ptext);
2841 _display_input_language (EcoreIMFContextISF *ic)
2843 IMEngineFactoryPointer sf;
2845 if (ic && ic->impl) {
2846 if (ic->impl->is_on) {
2847 sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2848 _popup_message (scim_get_language_name (sf->get_language ()).c_str ());
2851 _popup_message (scim_get_language_name ("en").c_str());
2857 open_next_factory (EcoreIMFContextISF *ic)
2859 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2860 IMEngineFactoryPointer sf = _backend->get_next_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2864 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2865 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2866 ic->impl->preedit_string = WideString ();
2867 ic->impl->preedit_caret = 0;
2868 attach_instance (ic->impl->si);
2869 _backend->set_default_factory (_language, sf->get_uuid ());
2870 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2871 _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2872 set_ic_capabilities (ic);
2875 if (_shared_input_method) {
2876 _default_instance = ic->impl->si;
2877 ic->impl->shared_si = true;
2879 _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2884 open_previous_factory (EcoreIMFContextISF *ic)
2889 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2890 IMEngineFactoryPointer sf = _backend->get_previous_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2894 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2895 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2896 ic->impl->preedit_string = WideString ();
2897 ic->impl->preedit_caret = 0;
2898 attach_instance (ic->impl->si);
2899 _backend->set_default_factory (_language, sf->get_uuid ());
2900 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2901 _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2902 set_ic_capabilities (ic);
2905 if (_shared_input_method) {
2906 _default_instance = ic->impl->si;
2907 ic->impl->shared_si = true;
2909 _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2914 open_specific_factory (EcoreIMFContextISF *ic,
2920 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2922 // The same input method is selected, just turn on the IC.
2923 if (ic->impl->si->get_factory_uuid () == uuid) {
2928 IMEngineFactoryPointer sf = _backend->get_factory (uuid);
2930 if (uuid.length () && !sf.null ()) {
2932 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2933 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2934 ic->impl->preedit_string = WideString ();
2935 ic->impl->preedit_caret = 0;
2936 attach_instance (ic->impl->si);
2937 _backend->set_default_factory (_language, sf->get_uuid ());
2938 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2939 set_ic_capabilities (ic);
2942 if (_shared_input_method) {
2943 _default_instance = ic->impl->si;
2944 ic->impl->shared_si = true;
2947 std::cerr << "open_specific_factory () is failed!!!!!!\n";
2948 LOGE ("open_specific_factory () is failed. ic : %x uuid : %s", ic->id, uuid.c_str());
2950 // turn_off_ic comment out panel_req_update_factory_info ()
2952 if (ic && ic->impl->is_on) {
2953 ic->impl->is_on = false;
2955 if (ic == _focused_ic) {
2956 ic->impl->si->focus_out ();
2958 panel_req_update_factory_info (ic);
2959 _panel_client.turn_off (ic->id);
2962 //Record the IC on/off status
2963 if (_shared_input_method) {
2964 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2968 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2969 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2970 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2971 ecore_imf_context_preedit_end_event_add (ic->ctx);
2972 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2973 ic->impl->preedit_started = false;
2979 static void initialize_modifier_bits (Display *display)
2981 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2983 if (__current_display == display)
2986 __current_display = display;
2989 __current_alt_mask = Mod1Mask;
2990 __current_meta_mask = ShiftMask | Mod1Mask;
2991 __current_super_mask = 0;
2992 __current_hyper_mask = 0;
2993 __current_numlock_mask = Mod2Mask;
2997 XModifierKeymap *mods = NULL;
2999 ::KeyCode ctrl_l = XKeysymToKeycode (display, XK_Control_L);
3000 ::KeyCode ctrl_r = XKeysymToKeycode (display, XK_Control_R);
3001 ::KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
3002 ::KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
3003 ::KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
3004 ::KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
3005 ::KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
3006 ::KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
3007 ::KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
3008 ::KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
3009 ::KeyCode numlock = XKeysymToKeycode (display, XK_Num_Lock);
3013 mods = XGetModifierMapping (display);
3017 __current_alt_mask = 0;
3018 __current_meta_mask = 0;
3019 __current_super_mask = 0;
3020 __current_hyper_mask = 0;
3021 __current_numlock_mask = 0;
3023 /* We skip the first three sets for Shift, Lock, and Control. The
3024 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
3025 for (i = 3; i < 8; i++) {
3026 for (j = 0; j < mods->max_keypermod; j++) {
3027 ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
3028 if (! code) continue;
3029 if (code == alt_l || code == alt_r)
3030 __current_alt_mask |= (1 << i);
3031 else if (code == meta_l || code == meta_r)
3032 __current_meta_mask |= (1 << i);
3033 else if (code == super_l || code == super_r)
3034 __current_super_mask |= (1 << i);
3035 else if (code == hyper_l || code == hyper_r)
3036 __current_hyper_mask |= (1 << i);
3037 else if (code == numlock)
3038 __current_numlock_mask |= (1 << i);
3042 /* Check whether there is a combine keys mapped to Meta */
3043 if (__current_meta_mask == 0) {
3046 KeySym keysym_l, keysym_r;
3048 xkey.type = KeyPress;
3049 xkey.display = display;
3051 xkey.send_event = False;
3052 xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
3054 xkey.same_screen = False;
3055 xkey.subwindow = None;
3057 xkey.root = DefaultRootWindow (display);
3058 xkey.state = ShiftMask;
3060 xkey.keycode = meta_l;
3061 XLookupString (&xkey, buf, 32, &keysym_l, 0);
3062 xkey.keycode = meta_r;
3063 XLookupString (&xkey, buf, 32, &keysym_r, 0);
3065 if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
3066 __current_meta_mask = ShiftMask + __current_alt_mask;
3067 else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
3068 __current_meta_mask = ShiftMask + ControlMask;
3071 XFreeModifiermap (mods);
3074 static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask)
3076 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3078 unsigned int state = 0;
3080 initialize_modifier_bits (display);
3082 if (scimkeymask & SCIM_KEY_ShiftMask) state |= ShiftMask;
3083 if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
3084 if (scimkeymask & SCIM_KEY_ControlMask) state |= ControlMask;
3085 if (scimkeymask & SCIM_KEY_AltMask) state |= __current_alt_mask;
3086 if (scimkeymask & SCIM_KEY_MetaMask) state |= __current_meta_mask;
3087 if (scimkeymask & SCIM_KEY_SuperMask) state |= __current_super_mask;
3088 if (scimkeymask & SCIM_KEY_HyperMask) state |= __current_hyper_mask;
3089 if (scimkeymask & SCIM_KEY_NumLockMask) state |= __current_numlock_mask;
3094 static XKeyEvent createKeyEvent (bool press, int keycode, int modifiers, bool fake)
3096 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3100 Display *display = (Display *)ecore_x_display_get ();
3101 int revert = RevertToParent;
3103 XGetInputFocus (display, &focus_win, &revert);
3105 event.display = display;
3106 event.window = focus_win;
3107 event.root = DefaultRootWindow (display);
3108 event.subwindow = None;
3112 event.time = get_time ();
3118 event.same_screen = True;
3119 event.state = modifiers;
3120 event.keycode = keycode;
3122 event.type = KeyPress;
3124 event.type = KeyRelease;
3125 event.send_event = False;
3131 static void send_x_key_event (const KeyEvent &key, bool fake)
3133 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3135 ::KeyCode keycode = 0;
3136 ::KeySym keysym = 0;
3138 char key_string[256] = {0};
3139 char keysym_str[256] = {0};
3141 // Obtain the X11 display.
3142 Display *display = (Display *)ecore_x_display_get ();
3143 if (display == NULL) {
3144 std::cerr << "ecore_x_display_get () failed\n";
3148 if (strncmp (key.get_key_string ().c_str (), "KeyRelease+", 11) == 0) {
3149 snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str () + 11);
3151 snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str ());
3154 if (strncmp (key_string, "Shift+", 6) == 0) {
3155 snprintf (keysym_str, sizeof (keysym_str), "%s", key_string + 6);
3157 snprintf (keysym_str, sizeof (keysym_str), "%s", key_string);
3160 // get x keysym, keycode, keyname, and key
3161 keysym = XStringToKeysym (keysym_str);
3162 if (keysym == NoSymbol)
3165 keycode = _keyname_to_keycode (keysym_str);
3166 if (XkbKeycodeToKeysym (display, keycode, 0, 0) != keysym) {
3167 if (XkbKeycodeToKeysym (display, keycode, 0, 1) == keysym)
3178 int keycode_min, keycode_max, keycode_num;
3181 XDisplayKeycodes (display, &keycode_min, &keycode_max);
3182 keysyms = XGetKeyboardMapping (display, keycode_min,
3183 keycode_max - keycode_min + 1,
3185 mod = (mod + 1) & 0x7;
3186 i = (keycode_max - keycode_min - mod - 1) * keycode_num;
3188 keysyms[i] = keysym;
3189 XChangeKeyboardMapping (display, keycode_min, keycode_num,
3190 keysyms, (keycode_max - keycode_min));
3192 XSync (display, False);
3193 keycode = keycode_max - mod - 1;
3196 unsigned int modifier = scim_x11_keymask_scim_to_x11 (display, key.mask);
3199 modifier |= ShiftMask;
3202 if (key.is_key_press ()) {
3204 event = createKeyEvent (true, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3205 XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3208 event = createKeyEvent (true, keycode, modifier, fake);
3209 XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3211 event = createKeyEvent (false, keycode, modifier, fake);
3212 XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3215 event = createKeyEvent (false, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3216 XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3222 attach_instance (const IMEngineInstancePointer &si)
3224 si->signal_connect_show_preedit_string (
3225 slot (slot_show_preedit_string));
3226 si->signal_connect_show_aux_string (
3227 slot (slot_show_aux_string));
3228 si->signal_connect_show_lookup_table (
3229 slot (slot_show_lookup_table));
3231 si->signal_connect_hide_preedit_string (
3232 slot (slot_hide_preedit_string));
3233 si->signal_connect_hide_aux_string (
3234 slot (slot_hide_aux_string));
3235 si->signal_connect_hide_lookup_table (
3236 slot (slot_hide_lookup_table));
3238 si->signal_connect_update_preedit_caret (
3239 slot (slot_update_preedit_caret));
3240 si->signal_connect_update_preedit_string (
3241 slot (slot_update_preedit_string));
3242 si->signal_connect_update_aux_string (
3243 slot (slot_update_aux_string));
3244 si->signal_connect_update_lookup_table (
3245 slot (slot_update_lookup_table));
3247 si->signal_connect_commit_string (
3248 slot (slot_commit_string));
3250 si->signal_connect_forward_key_event (
3251 slot (slot_forward_key_event));
3253 si->signal_connect_register_properties (
3254 slot (slot_register_properties));
3256 si->signal_connect_update_property (
3257 slot (slot_update_property));
3259 si->signal_connect_beep (
3262 si->signal_connect_start_helper (
3263 slot (slot_start_helper));
3265 si->signal_connect_stop_helper (
3266 slot (slot_stop_helper));
3268 si->signal_connect_send_helper_event (
3269 slot (slot_send_helper_event));
3271 si->signal_connect_get_surrounding_text (
3272 slot (slot_get_surrounding_text));
3274 si->signal_connect_delete_surrounding_text (
3275 slot (slot_delete_surrounding_text));
3277 si->signal_connect_expand_candidate (
3278 slot (slot_expand_candidate));
3279 si->signal_connect_contract_candidate (
3280 slot (slot_contract_candidate));
3282 si->signal_connect_set_candidate_style (
3283 slot (slot_set_candidate_style));
3286 // Implementation of slot functions
3288 slot_show_preedit_string (IMEngineInstanceBase *si)
3290 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3292 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3294 if (ic && ic->impl && _focused_ic == ic) {
3295 if (ic->impl->use_preedit) {
3296 if (!ic->impl->preedit_started) {
3297 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3298 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3299 ic->impl->preedit_started = true;
3301 //if (ic->impl->preedit_string.length ())
3302 // ecore_imf_context_preedit_changed_event_add (_focused_ic->ctx);
3304 _panel_client.show_preedit_string (ic->id);
3310 slot_show_aux_string (IMEngineInstanceBase *si)
3312 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3314 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3316 if (ic && ic->impl && _focused_ic == ic)
3317 _panel_client.show_aux_string (ic->id);
3321 slot_show_lookup_table (IMEngineInstanceBase *si)
3323 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3325 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3327 if (ic && ic->impl && _focused_ic == ic)
3328 _panel_client.show_lookup_table (ic->id);
3332 slot_hide_preedit_string (IMEngineInstanceBase *si)
3334 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3336 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3338 if (ic && ic->impl && _focused_ic == ic) {
3340 if (ic->impl->preedit_string.length ()) {
3341 ic->impl->preedit_string = WideString ();
3342 ic->impl->preedit_caret = 0;
3343 ic->impl->preedit_attrlist.clear ();
3346 if (ic->impl->use_preedit) {
3348 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3349 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3351 if (ic->impl->preedit_started) {
3352 ecore_imf_context_preedit_end_event_add (ic->ctx);
3353 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
3354 ic->impl->preedit_started = false;
3357 _panel_client.hide_preedit_string (ic->id);
3363 slot_hide_aux_string (IMEngineInstanceBase *si)
3365 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3367 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3369 if (ic && ic->impl && _focused_ic == ic)
3370 _panel_client.hide_aux_string (ic->id);
3374 slot_hide_lookup_table (IMEngineInstanceBase *si)
3376 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3378 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3380 if (ic && ic->impl && _focused_ic == ic)
3381 _panel_client.hide_lookup_table (ic->id);
3385 slot_update_preedit_caret (IMEngineInstanceBase *si, int caret)
3387 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3389 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3391 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
3392 ic->impl->preedit_caret = caret;
3393 if (ic->impl->use_preedit) {
3394 if (!ic->impl->preedit_started) {
3395 ecore_imf_context_preedit_start_event_add (ic->ctx);
3396 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3397 ic->impl->preedit_started = true;
3399 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3400 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3402 _panel_client.update_preedit_caret (ic->id, caret);
3408 slot_update_preedit_string (IMEngineInstanceBase *si,
3409 const WideString & str,
3410 const AttributeList & attrs)
3412 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3414 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3416 if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length ())) {
3417 ic->impl->preedit_string = str;
3418 ic->impl->preedit_attrlist = attrs;
3419 if (ic->impl->use_preedit) {
3420 if (!ic->impl->preedit_started) {
3421 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3422 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3423 ic->impl->preedit_started = true;
3425 ic->impl->preedit_caret = str.length ();
3426 ic->impl->preedit_updating = true;
3427 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3428 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3429 ic->impl->preedit_updating = false;
3431 _panel_client.update_preedit_string (ic->id, str, attrs);
3437 slot_update_aux_string (IMEngineInstanceBase *si,
3438 const WideString & str,
3439 const AttributeList & attrs)
3441 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3443 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3445 if (ic && ic->impl && _focused_ic == ic)
3446 _panel_client.update_aux_string (ic->id, str, attrs);
3450 slot_commit_string (IMEngineInstanceBase *si,
3451 const WideString & str)
3453 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3455 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3457 if (ic && ic->ctx) {
3458 if (strcmp (utf8_wcstombs (str).c_str (), " ") == 0)
3459 autoperiod_insert (ic->ctx);
3461 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (str).c_str ());
3462 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3467 slot_forward_key_event (IMEngineInstanceBase *si,
3468 const KeyEvent & key)
3470 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3472 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3474 if (ic && _focused_ic == ic) {
3475 if (!_fallback_instance->process_key_event (key)) {
3476 feed_key_event (ic, key, true);
3482 slot_update_lookup_table (IMEngineInstanceBase *si,
3483 const LookupTable & table)
3485 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3487 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3489 if (ic && ic->impl && _focused_ic == ic)
3490 _panel_client.update_lookup_table (ic->id, table);
3494 slot_register_properties (IMEngineInstanceBase *si,
3495 const PropertyList & properties)
3497 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3499 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3501 if (ic && ic->impl && _focused_ic == ic)
3502 _panel_client.register_properties (ic->id, properties);
3506 slot_update_property (IMEngineInstanceBase *si,
3507 const Property & property)
3509 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3511 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3513 if (ic && ic->impl && _focused_ic == ic)
3514 _panel_client.update_property (ic->id, property);
3518 slot_beep (IMEngineInstanceBase *si)
3520 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3522 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3524 if (ic && ic->impl && _focused_ic == ic)
3529 slot_start_helper (IMEngineInstanceBase *si,
3530 const String &helper_uuid)
3532 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3534 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3535 << (ic != NULL ? ic->id : -1) << " ic=" << ic
3536 << " ic-uuid=" << ((ic != NULL ) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3539 _panel_client.start_helper (ic->id, helper_uuid);
3543 slot_stop_helper (IMEngineInstanceBase *si,
3544 const String &helper_uuid)
3546 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3548 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic != NULL ? ic->id : -1) << " ic=" << ic << "...\n";
3551 _panel_client.stop_helper (ic->id, helper_uuid);
3555 slot_send_helper_event (IMEngineInstanceBase *si,
3556 const String &helper_uuid,
3557 const Transaction &trans)
3559 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3561 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3562 << (ic != NULL ? ic->id : -1) << " ic=" << ic
3563 << " ic-uuid=" << ((ic != NULL) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3566 _panel_client.send_helper_event (ic->id, helper_uuid, trans);
3570 slot_get_surrounding_text (IMEngineInstanceBase *si,
3576 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3578 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3580 if (ic && ic->impl && _focused_ic == ic) {
3581 char *surrounding = NULL;
3583 if (ecore_imf_context_surrounding_get (_focused_ic->ctx, &surrounding, &cursor_index)) {
3584 SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
3585 SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
3586 WideString before = utf8_mbstowcs (String (surrounding));
3587 if (cursor_index > (int)before.length())
3589 WideString after = before;
3590 before = before.substr (0, cursor_index);
3591 after = after.substr (cursor_index, after.length () - cursor_index);
3592 if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length ())
3593 before = WideString (before.begin () + (before.length () - maxlen_before), before.end ());
3594 else if (maxlen_before == 0)
3595 before = WideString ();
3596 if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length ())
3597 after = WideString (after.begin (), after.begin () + maxlen_after);
3598 else if (maxlen_after == 0)
3599 after = WideString ();
3600 text = before + after;
3601 cursor = before.length ();
3609 slot_delete_surrounding_text (IMEngineInstanceBase *si,
3613 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3615 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3617 if (ic && ic->impl && _focused_ic == ic) {
3618 Ecore_IMF_Event_Delete_Surrounding ev;
3619 ev.ctx = _focused_ic->ctx;
3622 ecore_imf_context_delete_surrounding_event_add (_focused_ic->ctx, offset, len);
3623 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
3630 slot_expand_candidate (IMEngineInstanceBase *si)
3632 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3634 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3636 if (ic && ic->impl && _focused_ic == ic)
3637 _panel_client.expand_candidate (ic->id);
3641 slot_contract_candidate (IMEngineInstanceBase *si)
3643 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3645 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3647 if (ic && ic->impl && _focused_ic == ic)
3648 _panel_client.contract_candidate (ic->id);
3652 slot_set_candidate_style (IMEngineInstanceBase *si, ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line, ISF_CANDIDATE_MODE_T mode)
3654 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3656 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3658 if (ic && ic->impl && _focused_ic == ic)
3659 _panel_client.set_candidate_style (ic->id, portrait_line, mode);
3663 reload_config_callback (const ConfigPointer &config)
3665 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3667 _frontend_hotkey_matcher.load_hotkeys (config);
3668 _imengine_hotkey_matcher.load_hotkeys (config);
3671 scim_string_to_key (key,
3672 config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
3673 String ("Shift+Control+Alt+Lock")));
3675 _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
3676 _valid_key_mask |= SCIM_KEY_ReleaseMask;
3677 // Special treatment for two backslash keys on jp106 keyboard.
3678 _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
3680 _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
3681 _shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
3683 // Get keyboard layout setting
3684 // Flush the global config first, in order to load the new configs from disk.
3685 scim_global_config_flush ();
3687 _keyboard_layout = scim_get_default_keyboard_layout ();
3691 fallback_commit_string_cb (IMEngineInstanceBase *si,
3692 const WideString &str)
3694 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3696 if (_focused_ic && _focused_ic->impl) {
3697 ecore_imf_context_commit_event_add (_focused_ic->ctx, utf8_wcstombs (str).c_str ());
3698 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3703 vi:ts=4:expandtab:nowrap