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;
85 bool prediction_allow;
86 int next_shift_status;
87 int shift_mode_enabled;
89 EcoreIMFContextISFImpl *next;
92 /* Input Context handling functions. */
93 static EcoreIMFContextISFImpl *new_ic_impl (EcoreIMFContextISF *parent);
94 static void delete_ic_impl (EcoreIMFContextISFImpl *impl);
95 static void delete_all_ic_impl (void);
97 static EcoreIMFContextISF *find_ic (int id);
100 /* private functions */
101 static void panel_slot_reload_config (int context);
102 static void panel_slot_exit (int context);
103 static void panel_slot_update_candidate_item_layout (int context,
104 const std::vector<uint32> &row_items);
105 static void panel_slot_update_lookup_table_page_size(int context,
107 static void panel_slot_lookup_table_page_up (int context);
108 static void panel_slot_lookup_table_page_down (int context);
109 static void panel_slot_trigger_property (int context,
110 const String &property);
111 static void panel_slot_process_helper_event (int context,
112 const String &target_uuid,
113 const String &helper_uuid,
114 const Transaction &trans);
115 static void panel_slot_move_preedit_caret (int context,
117 static void panel_slot_update_preedit_caret (int context,
119 static void panel_slot_select_aux (int context,
121 static void panel_slot_select_candidate (int context,
123 static void panel_slot_process_key_event (int context,
124 const KeyEvent &key);
125 static void panel_slot_commit_string (int context,
126 const WideString &wstr);
127 static void panel_slot_forward_key_event (int context,
128 const KeyEvent &key);
129 static void panel_slot_request_help (int context);
130 static void panel_slot_request_factory_menu (int context);
131 static void panel_slot_change_factory (int context,
133 static void panel_slot_reset_keyboard_ise (int context);
134 static void panel_slot_update_keyboard_ise (int context);
135 static void panel_slot_show_preedit_string (int context);
136 static void panel_slot_hide_preedit_string (int context);
137 static void panel_slot_update_preedit_string (int context,
138 const WideString &str,
139 const AttributeList &attrs);
140 static void panel_slot_get_surrounding_text (int context,
143 static void panel_slot_delete_surrounding_text (int context,
147 static void panel_req_focus_in (EcoreIMFContextISF *ic);
148 static void panel_req_update_factory_info (EcoreIMFContextISF *ic);
149 static void panel_req_update_spot_location (EcoreIMFContextISF *ic);
150 static void panel_req_update_cursor_position (EcoreIMFContextISF *ic, int cursor_pos);
151 static void panel_req_show_help (EcoreIMFContextISF *ic);
152 static void panel_req_show_factory_menu (EcoreIMFContextISF *ic);
154 /* Panel iochannel handler*/
155 static bool panel_initialize (void);
156 static void panel_finalize (void);
157 static Eina_Bool panel_iochannel_handler (void *data,
158 Ecore_Fd_Handler *fd_handler);
160 /* utility functions */
161 static bool filter_hotkeys (EcoreIMFContextISF *ic,
162 const KeyEvent &key);
163 static void turn_on_ic (EcoreIMFContextISF *ic);
164 static void turn_off_ic (EcoreIMFContextISF *ic);
165 static void set_ic_capabilities (EcoreIMFContextISF *ic);
167 static void initialize (void);
168 static void finalize (void);
170 static void open_next_factory (EcoreIMFContextISF *ic);
171 static void open_previous_factory (EcoreIMFContextISF *ic);
172 static void open_specific_factory (EcoreIMFContextISF *ic,
174 static void initialize_modifier_bits (Display *display);
175 static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask);
176 static XKeyEvent createKeyEvent (bool press, int keycode, int modifiers, bool fake);
177 static void send_x_key_event (const KeyEvent &key, bool fake);
179 static void attach_instance (const IMEngineInstancePointer &si);
182 static void slot_show_preedit_string (IMEngineInstanceBase *si);
183 static void slot_show_aux_string (IMEngineInstanceBase *si);
184 static void slot_show_lookup_table (IMEngineInstanceBase *si);
186 static void slot_hide_preedit_string (IMEngineInstanceBase *si);
187 static void slot_hide_aux_string (IMEngineInstanceBase *si);
188 static void slot_hide_lookup_table (IMEngineInstanceBase *si);
190 static void slot_update_preedit_caret (IMEngineInstanceBase *si,
192 static void slot_update_preedit_string (IMEngineInstanceBase *si,
193 const WideString &str,
194 const AttributeList &attrs);
195 static void slot_update_aux_string (IMEngineInstanceBase *si,
196 const WideString &str,
197 const AttributeList &attrs);
198 static void slot_commit_string (IMEngineInstanceBase *si,
199 const WideString &str);
200 static void slot_forward_key_event (IMEngineInstanceBase *si,
201 const KeyEvent &key);
202 static void slot_update_lookup_table (IMEngineInstanceBase *si,
203 const LookupTable &table);
205 static void slot_register_properties (IMEngineInstanceBase *si,
206 const PropertyList &properties);
207 static void slot_update_property (IMEngineInstanceBase *si,
208 const Property &property);
209 static void slot_beep (IMEngineInstanceBase *si);
210 static void slot_start_helper (IMEngineInstanceBase *si,
211 const String &helper_uuid);
212 static void slot_stop_helper (IMEngineInstanceBase *si,
213 const String &helper_uuid);
214 static void slot_send_helper_event (IMEngineInstanceBase *si,
215 const String &helper_uuid,
216 const Transaction &trans);
217 static bool slot_get_surrounding_text (IMEngineInstanceBase *si,
222 static bool slot_delete_surrounding_text (IMEngineInstanceBase *si,
226 static void slot_expand_candidate (IMEngineInstanceBase *si);
227 static void slot_contract_candidate (IMEngineInstanceBase *si);
229 static void slot_set_candidate_style (IMEngineInstanceBase *si,
230 ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line,
231 ISF_CANDIDATE_MODE_T mode);
233 static void reload_config_callback (const ConfigPointer &config);
235 static void fallback_commit_string_cb (IMEngineInstanceBase *si,
236 const WideString &str);
237 static void _display_input_language (EcoreIMFContextISF *ic);
239 /* Local variables declaration */
240 static String _language;
241 static EcoreIMFContextISFImpl *_used_ic_impl_list = 0;
242 static EcoreIMFContextISFImpl *_free_ic_impl_list = 0;
243 static EcoreIMFContextISF *_ic_list = 0;
245 static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
246 static int _valid_key_mask = SCIM_KEY_AllMasks;
248 static FrontEndHotkeyMatcher _frontend_hotkey_matcher;
249 static IMEngineHotkeyMatcher _imengine_hotkey_matcher;
251 static IMEngineInstancePointer _default_instance;
253 static ConfigModule *_config_module = 0;
254 static ConfigPointer _config;
255 static BackEndPointer _backend;
257 static EcoreIMFContextISF *_focused_ic = 0;
259 static bool _scim_initialized = false;
261 static int _instance_count = 0;
262 static int _context_count = 0;
264 static IMEngineFactoryPointer _fallback_factory;
265 static IMEngineInstancePointer _fallback_instance;
266 static PanelClient _panel_client;
267 static int _panel_client_id = 0;
269 static Ecore_Fd_Handler *_panel_iochannel_read_handler = 0;
270 static Ecore_Fd_Handler *_panel_iochannel_err_handler = 0;
272 static Ecore_X_Window _client_window = 0;
273 static Ecore_Event_Handler *_key_down_handler = 0;
274 static Ecore_Event_Handler *_key_up_handler = 0;
276 static bool _on_the_spot = true;
277 static bool _shared_input_method = false;
278 static double space_key_time = 0.0;
280 static Eina_Bool autoperiod_allow = EINA_FALSE;
281 static Eina_Bool autocap_allow = EINA_FALSE;
282 static Eina_Bool desktop_mode = EINA_FALSE;
284 static Display *__current_display = 0;
285 static int __current_alt_mask = Mod1Mask;
286 static int __current_meta_mask = 0;
287 static int __current_super_mask = 0;
288 static int __current_hyper_mask = 0;
289 static int __current_numlock_mask = Mod2Mask;
291 #define SHIFT_MODE_OFF 0xffe1
292 #define SHIFT_MODE_ON 0xffe2
293 #define SHIFT_MODE_LOCK 0xffe6
294 #define SHIFT_MODE_ENABLE 0x9fe7
295 #define SHIFT_MODE_DISABLE 0x9fe8
297 extern Ecore_IMF_Context *input_panel_ctx;
299 // A hack to shutdown the immodule cleanly even if im_module_exit () is not called when exiting.
300 class FinalizeHandler
304 SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::FinalizeHandler ()\n";
306 ~FinalizeHandler () {
307 SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::~FinalizeHandler ()\n";
312 static FinalizeHandler _finalize_handler;
314 EAPI ConfigPointer isf_imf_context_get_config (void)
319 EAPI EcoreIMFContextISF *
326 get_panel_client_id (void)
328 return _panel_client_id;
342 struct timezone tz; /* is not used since ages */
343 gettimeofday (&tv, &tz);
344 tint = tv.tv_sec * 1000;
345 tint = tint / 1000 * 1000;
346 tint = tint + tv.tv_usec / 1000;
350 /* Function Implementations */
351 static EcoreIMFContextISFImpl *
352 new_ic_impl (EcoreIMFContextISF *parent)
354 EcoreIMFContextISFImpl *impl = NULL;
356 if (_free_ic_impl_list != NULL) {
357 impl = _free_ic_impl_list;
358 _free_ic_impl_list = _free_ic_impl_list->next;
360 impl = new EcoreIMFContextISFImpl;
365 impl->autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
366 impl->next_shift_status = 0;
367 impl->shift_mode_enabled = 0;
368 impl->next = _used_ic_impl_list;
369 _used_ic_impl_list = impl;
371 impl->parent = parent;
373 impl->imdata_size = 0;
379 delete_ic_impl (EcoreIMFContextISFImpl *impl)
381 EcoreIMFContextISFImpl *rec = _used_ic_impl_list, *last = 0;
383 for (; rec != 0; last = rec, rec = rec->next) {
386 last->next = rec->next;
388 _used_ic_impl_list = rec->next;
390 rec->next = _free_ic_impl_list;
391 _free_ic_impl_list = rec;
398 rec->imdata_size = 0;
401 rec->client_window = 0;
402 rec->preedit_string = WideString ();
403 rec->preedit_attrlist.clear ();
411 delete_all_ic_impl (void)
413 EcoreIMFContextISFImpl *it = _used_ic_impl_list;
416 _used_ic_impl_list = it->next;
418 it = _used_ic_impl_list;
421 it = _free_ic_impl_list;
423 _free_ic_impl_list = it->next;
425 it = _free_ic_impl_list;
429 static EcoreIMFContextISF *
432 EcoreIMFContextISFImpl *rec = _used_ic_impl_list;
435 if (rec->parent && rec->parent->id == id)
444 _key_down_cb (void *data, int type, void *event)
446 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
448 Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event;
449 if (!ev || !_focused_ic || !_focused_ic->ctx) return ECORE_CALLBACK_RENEW;
451 if (!strcmp (ev->keyname, KEY_END) &&
452 ecore_imf_context_input_panel_state_get (_focused_ic->ctx) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
453 LOGD ("END key is pressed\n");
454 return ECORE_CALLBACK_CANCEL;
457 return ECORE_CALLBACK_RENEW;
461 _key_up_cb (void *data, int type, void *event)
463 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
465 Evas_Event_Key_Down *ev = (Evas_Event_Key_Down *)event;
466 if (!ev || !_focused_ic || !_focused_ic->ctx) return ECORE_CALLBACK_RENEW;
468 if (!strcmp (ev->keyname, KEY_END) &&
469 ecore_imf_context_input_panel_state_get (_focused_ic->ctx) != ECORE_IMF_INPUT_PANEL_STATE_HIDE) {
470 LOGD ("END key is released\n");
471 isf_imf_context_input_panel_instant_hide (_focused_ic->ctx);
472 return ECORE_CALLBACK_CANCEL;
475 return ECORE_CALLBACK_RENEW;
479 _check_desktop_mode (Ecore_X_Window win)
481 char *profile = ecore_x_e_window_profile_get (win);
482 if (profile && (strcmp (profile, "desktop") == 0)) {
483 desktop_mode = EINA_TRUE;
485 desktop_mode = EINA_FALSE;
493 _x_prop_change (void *data, int type, void *event)
495 Ecore_X_Event_Window_Property *e = (Ecore_X_Event_Window_Property *)event;
496 Ecore_X_Window xwin = (Ecore_X_Window)data;
498 if (e->win != xwin) return ECORE_CALLBACK_PASS_ON;
500 if (e->atom == ECORE_X_ATOM_E_PROFILE) {
501 _check_desktop_mode (e->win);
504 return ECORE_CALLBACK_PASS_ON;
508 register_key_handler ()
510 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
512 #ifdef ENABLE_BACKKEY
513 if (!_key_down_handler)
514 _key_down_handler = ecore_event_handler_add (ECORE_EVENT_KEY_DOWN, _key_down_cb, NULL);
516 if (!_key_up_handler)
517 _key_up_handler = ecore_event_handler_add (ECORE_EVENT_KEY_UP, _key_up_cb, NULL);
524 unregister_key_handler ()
526 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
528 if (_key_down_handler) {
529 ecore_event_handler_del (_key_down_handler);
530 _key_down_handler = NULL;
533 if (_key_up_handler) {
534 ecore_event_handler_del (_key_up_handler);
535 _key_up_handler = NULL;
542 set_prediction_allow (IMEngineInstancePointer si, bool prediction)
544 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
547 si->set_prediction_allow (prediction);
551 autoperiod_insert (Ecore_IMF_Context *ctx)
553 char *plain_str = NULL;
554 char *markup_str = NULL;
556 Eina_Unicode *ustr = NULL;
557 Ecore_IMF_Event_Delete_Surrounding ev;
561 Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
562 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
565 if (autoperiod_allow == EINA_FALSE)
568 if ((ecore_time_get () - space_key_time) > DOUBLE_SPACE_INTERVAL)
571 ecore_imf_context_surrounding_get (ctx, &markup_str, &cursor_pos);
572 if (!markup_str) goto done;
574 // Convert into plain string
575 plain_str = evas_textblock_text_markup_to_utf8 (NULL, markup_str);
576 if (!plain_str) goto done;
578 // Convert string from UTF-8 to unicode
579 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
580 if (!ustr) goto done;
582 if (cursor_pos < 2) goto done;
584 if (((ustr[cursor_pos-2] != ':') && (ustr[cursor_pos-2] != ';') &&
585 (ustr[cursor_pos-2] != '.') && (ustr[cursor_pos-2] != ',') &&
586 (ustr[cursor_pos-2] != '?') && (ustr[cursor_pos-2] != '!') &&
587 (ustr[cursor_pos-2] != ' ')) && ((ustr[cursor_pos-1] == ' ') || (ustr[cursor_pos-1] == '\240'))) {
591 ecore_imf_context_delete_surrounding_event_add (ctx, -1, 1);
592 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
594 ecore_imf_context_commit_event_add (ctx, ".");
595 ecore_imf_context_event_callback_call (ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)".");
599 if (markup_str) free (markup_str);
600 if (plain_str) free (plain_str);
601 if (ustr) free (ustr);
602 space_key_time = ecore_time_get ();
606 analyze_surrounding_text (Ecore_IMF_Context *ctx)
608 char *plain_str = NULL;
609 char *markup_str = NULL;
610 const char *puncs[] = {". ", ".\302\240", "! ", "!\302\240", "? ", "?\302\240", "¿ ", "¿\302\240", "¡ ", "¡\302\240" };
611 Eina_Bool ret = EINA_FALSE;
614 Eina_Unicode *tail = NULL;
615 Eina_Unicode *ustr = NULL;
616 const int punc_num = sizeof (puncs) / sizeof (puncs[0]);
617 Eina_Unicode *uni_puncs[punc_num];
618 EcoreIMFContextISF *context_scim;
620 if (!ctx) return EINA_FALSE;
621 context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
622 if (!context_scim || !context_scim->impl) return EINA_FALSE;
624 switch (context_scim->impl->autocapital_type) {
625 case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
627 case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
633 if (context_scim->impl->cursor_pos == 0)
636 for (i = 0; i < punc_num; i++) {
637 uni_puncs[i] = eina_unicode_utf8_to_unicode (puncs[i], NULL);
640 ecore_imf_context_surrounding_get (ctx, &markup_str, &cursor_pos);
641 if (!markup_str) goto done;
643 if (cursor_pos == 0) {
648 // Convert into plain string
649 plain_str = evas_textblock_text_markup_to_utf8 (NULL, markup_str);
650 if (!plain_str) goto done;
652 // Convert string from UTF-8 to unicode
653 ustr = eina_unicode_utf8_to_unicode (plain_str, NULL);
654 if (!ustr) goto done;
656 if (cursor_pos >= 1) {
657 if (context_scim->impl->autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD) {
658 if (ustr[cursor_pos-1] == ' ' || ustr[cursor_pos-1] == '\302\240') {
664 // Check paragraph separator <PS> and carriage return <br>
665 if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n')) {
672 if (cursor_pos >= 2) {
673 tail = eina_unicode_strndup (ustr+cursor_pos-2, 2);
676 for (i = 0; i < punc_num; i++) {
677 if (!eina_unicode_strcmp (tail, uni_puncs[i])) {
688 if (ustr) free (ustr);
689 if (markup_str) free (markup_str);
690 if (plain_str) free (plain_str);
692 for (i = 0; i < punc_num; i++) {
693 if (uni_puncs[i]) free (uni_puncs[i]);
700 caps_mode_check (Ecore_IMF_Context *ctx, Eina_Bool force, Eina_Bool noti)
703 EcoreIMFContextISF *context_scim;
705 if (!ctx) return EINA_FALSE;
706 context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
708 if (!context_scim || !context_scim->impl)
711 if (context_scim->impl->next_shift_status == SHIFT_MODE_LOCK) return EINA_TRUE;
713 Ecore_IMF_Input_Panel_Layout layout = ecore_imf_context_input_panel_layout_get (ctx);
714 if (layout != ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL)
717 // Check autocapital type
718 if (ecore_imf_context_input_panel_caps_lock_mode_get (ctx)) {
719 uppercase = EINA_TRUE;
721 if (autocap_allow == EINA_FALSE)
724 if (analyze_surrounding_text (ctx)) {
725 uppercase = EINA_TRUE;
727 uppercase = EINA_FALSE;
732 context_scim->impl->next_shift_status = uppercase ? SHIFT_MODE_ON : SHIFT_MODE_OFF;
734 isf_imf_context_input_panel_caps_mode_set (ctx, uppercase);
736 if (context_scim->impl->next_shift_status != (uppercase ? SHIFT_MODE_ON : SHIFT_MODE_OFF)) {
737 context_scim->impl->next_shift_status = uppercase ? SHIFT_MODE_ON : SHIFT_MODE_OFF;
739 isf_imf_context_input_panel_caps_mode_set (ctx, uppercase);
747 window_to_screen_geometry_get (Ecore_X_Window client_win, int *x, int *y)
749 Ecore_X_Window root_window, win;
751 int sum_x = 0, sum_y = 0;
753 root_window = ecore_x_window_root_get (client_win);
756 while (root_window != win) {
757 ecore_x_window_geometry_get (win, &win_x, &win_y, NULL, NULL);
760 win = ecore_x_window_parent_get (win);
770 evas_focus_out_cb (void *data, Evas *e, void *event_info)
772 Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)data;
776 LOGD ("ctx : %p\n", ctx);
778 if (input_panel_ctx == ctx && _scim_initialized) {
779 isf_imf_context_input_panel_instant_hide (ctx);
783 static void autoperiod_allow_changed_cb (keynode_t *key, void* data)
785 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
787 autoperiod_allow = vconf_keynode_get_bool (key);
790 static void autocapital_allow_changed_cb (keynode_t *key, void* data)
792 SCIM_DEBUG_MAIN (3) << __FUNCTION__ << "...\n";
794 autocap_allow = vconf_keynode_get_bool (key);
797 EAPI void context_scim_imdata_get (Ecore_IMF_Context *ctx, void* data, int* length)
799 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
801 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
803 if (data && context_scim->impl->imdata)
804 memcpy (data, context_scim->impl->imdata, context_scim->impl->imdata_size);
806 *length = context_scim->impl->imdata_size;
810 imengine_layout_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Layout layout)
812 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
814 if (context_scim && context_scim->impl) {
815 context_scim->impl->si->set_layout (layout);
819 /* Public functions */
821 * isf_imf_context_new
823 * This function will be called by Ecore IMF.
824 * Create a instance of type EcoreIMFContextISF.
826 * Return value: A pointer to the newly created EcoreIMFContextISF instance
828 EAPI EcoreIMFContextISF *
829 isf_imf_context_new (void)
831 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
835 EcoreIMFContextISF *context_scim = new EcoreIMFContextISF;
836 if (context_scim == NULL) {
837 std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
841 if (_context_count == 0) {
842 _context_count = getpid () % 50000;
844 context_scim->id = _context_count++;
846 if (!_scim_initialized) {
849 _scim_initialized = true;
850 isf_imf_input_panel_init ();
852 /* get autoperiod allow vconf value */
853 if (vconf_get_bool (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, &val) == 0) {
854 if (val == EINA_TRUE)
855 autoperiod_allow = EINA_TRUE;
858 vconf_notify_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb, NULL);
860 /* get autocapital allow vconf value */
861 if (vconf_get_bool (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, &val) == 0) {
862 if (val == EINA_TRUE)
863 autocap_allow = EINA_TRUE;
866 vconf_notify_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb, NULL);
873 * isf_imf_context_shutdown
875 * It will be called when the scim im module is unloaded by ecore. It will do some
879 isf_imf_context_shutdown (void)
881 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
883 if (_scim_initialized) {
884 _scim_initialized = false;
886 LOGD ("immodule shutdown\n");
888 vconf_ignore_key_changed (VCONFKEY_AUTOPERIOD_ALLOW_BOOL, autoperiod_allow_changed_cb);
889 vconf_ignore_key_changed (VCONFKEY_AUTOCAPITAL_ALLOW_BOOL, autocapital_allow_changed_cb);
891 isf_imf_input_panel_shutdown ();
898 isf_imf_context_add (Ecore_IMF_Context *ctx)
900 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
902 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
904 if (!context_scim) return;
906 context_scim->impl = NULL;
908 if (_backend.null ())
911 IMEngineInstancePointer si;
913 // Use the default instance if "shared input method" mode is enabled.
914 if (_shared_input_method && !_default_instance.null ()) {
915 si = _default_instance;
916 SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
919 // Not in "shared input method" mode, or no default instance, create an instance.
921 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
922 if (factory.null ()) return;
923 si = factory->create_instance ("UTF-8", _instance_count++);
924 if (si.null ()) return;
925 attach_instance (si);
926 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
929 // If "shared input method" mode is enabled, and there is no default instance,
930 // then store this instance as default one.
931 if (_shared_input_method && _default_instance.null ()) {
932 SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
933 _default_instance = si;
936 context_scim->ctx = ctx;
937 context_scim->impl = new_ic_impl (context_scim);
938 if (context_scim->impl == NULL) {
939 std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
943 context_scim->impl->si = si;
944 context_scim->impl->client_window = 0;
945 context_scim->impl->client_canvas = NULL;
946 context_scim->impl->preedit_caret = 0;
947 context_scim->impl->cursor_x = 0;
948 context_scim->impl->cursor_y = 0;
949 context_scim->impl->cursor_pos = -1;
950 context_scim->impl->cursor_top_y = 0;
951 context_scim->impl->is_on = true;
952 context_scim->impl->shared_si = _shared_input_method;
953 context_scim->impl->use_preedit = _on_the_spot;
954 context_scim->impl->preedit_started = false;
955 context_scim->impl->preedit_updating = false;
956 context_scim->impl->need_commit_preedit = false;
957 context_scim->impl->prediction_allow = true;
960 context_scim->next = NULL;
962 context_scim->next = _ic_list;
963 _ic_list = context_scim;
965 if (_shared_input_method)
966 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
968 _panel_client.prepare (context_scim->id);
969 _panel_client.register_input_context (context_scim->id, si->get_factory_uuid ());
970 set_ic_capabilities (context_scim);
971 _panel_client.send ();
973 SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
977 isf_imf_context_del (Ecore_IMF_Context *ctx)
979 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
981 if (!_ic_list) return;
983 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
984 Ecore_IMF_Input_Panel_State input_panel_state = ecore_imf_context_input_panel_state_get (ctx);
987 if (context_scim->id != _ic_list->id) {
988 EcoreIMFContextISF * pre = _ic_list;
989 EcoreIMFContextISF * cur = _ic_list->next;
990 while (cur != NULL) {
991 if (cur->id == context_scim->id) {
992 pre->next = cur->next;
999 _ic_list = _ic_list->next;
1003 if (context_scim && context_scim->impl) {
1004 _panel_client.prepare (context_scim->id);
1006 if (context_scim == _focused_ic)
1007 context_scim->impl->si->focus_out ();
1009 if (context_scim->impl->client_canvas)
1010 evas_event_callback_del_full (context_scim->impl->client_canvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, evas_focus_out_cb, ctx);
1012 if (input_panel_ctx == ctx && _scim_initialized) {
1013 LOGD ("ctx : %p\n", ctx);
1014 if (input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW ||
1015 input_panel_state == ECORE_IMF_INPUT_PANEL_STATE_SHOW) {
1016 ecore_imf_context_input_panel_hide (ctx);
1017 input_panel_event_callback_call (ECORE_IMF_INPUT_PANEL_STATE_EVENT, ECORE_IMF_INPUT_PANEL_STATE_HIDE);
1021 // Delete the instance.
1023 // In case the instance send out some helper event,
1024 // and this context has been focused out,
1025 // we need set the focused_ic to this context temporary.
1026 EcoreIMFContextISF *old_focused = _focused_ic;
1027 _focused_ic = context_scim;
1028 context_scim->impl->si.reset ();
1029 _focused_ic = old_focused;
1031 if (context_scim == _focused_ic) {
1032 _panel_client.turn_off (context_scim->id);
1033 _panel_client.focus_out (context_scim->id);
1036 _panel_client.remove_input_context (context_scim->id);
1037 _panel_client.send ();
1039 if (context_scim->impl->client_window)
1040 isf_imf_context_client_window_set (ctx, NULL);
1042 if (context_scim->impl) {
1043 delete_ic_impl (context_scim->impl);
1044 context_scim->impl = 0;
1048 isf_imf_context_input_panel_event_callback_clear (ctx);
1050 if (context_scim == _focused_ic)
1054 delete context_scim;
1060 * isf_imf_context_client_canvas_set
1061 * @ctx: a #Ecore_IMF_Context
1062 * @canvas: the client canvas
1064 * This function will be called by Ecore IMF.
1066 * Set the client canvas for the Input Method Context; this is the canvas
1067 * in which the input appears.
1069 * The canvas type can be determined by using the context canvas type.
1070 * Actually only canvas with type "evas" (Evas *) is supported. This canvas
1071 * may be used in order to correctly position status windows, and may also
1072 * be used for purposes internal to the Input Method Context.
1075 isf_imf_context_client_canvas_set (Ecore_IMF_Context *ctx, void *canvas)
1077 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1079 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1081 if (context_scim && context_scim->impl && context_scim->impl->client_canvas != (Evas*) canvas) {
1082 context_scim->impl->client_canvas = (Evas*)canvas;
1084 LOGD ("ctx : %p, canvas : %p\n", ctx, canvas);
1086 evas_event_callback_add (context_scim->impl->client_canvas, EVAS_CALLBACK_CANVAS_FOCUS_OUT, evas_focus_out_cb, ctx);
1091 * isf_imf_context_client_window_set
1092 * @ctx: a #Ecore_IMF_Context
1093 * @window: the client window
1095 * This function will be called by Ecore IMF.
1097 * Set the client window for the Input Method Context; this is the Ecore_X_Window
1098 * when using X11, Ecore_Win32_Window when using Win32, etc.
1100 * This window is used in order to correctly position status windows,
1101 * and may also be used for purposes internal to the Input Method Context.
1104 isf_imf_context_client_window_set (Ecore_IMF_Context *ctx, void *window)
1106 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1108 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1110 if (context_scim && context_scim->impl && context_scim->impl->client_window != (Ecore_X_Window)((Ecore_Window)window)) {
1111 context_scim->impl->client_window = (Ecore_X_Window)((Ecore_Window)window);
1113 LOGD ("ctx : %p, client X win ID : %#x\n", ctx, context_scim->impl->client_window);
1115 if ((context_scim->impl->client_window != 0) &&
1116 (context_scim->impl->client_window != _client_window)) {
1117 _client_window = context_scim->impl->client_window;
1119 _check_desktop_mode (_client_window);
1121 ecore_event_handler_add (ECORE_X_EVENT_WINDOW_PROPERTY, _x_prop_change, window);
1127 * isf_imf_context_focus_in
1128 * @ctx: a #Ecore_IMF_Context
1130 * This function will be called by Ecore IMF.
1132 * Notify the Input Method Context that the widget to which its correspond has gained focus.
1135 isf_imf_context_focus_in (Ecore_IMF_Context *ctx)
1137 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1142 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
1145 if (_focused_ic == context_scim) {
1146 SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
1149 SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
1150 if (_focused_ic->ctx)
1151 isf_imf_context_focus_out (_focused_ic->ctx);
1154 bool need_cap = false;
1155 bool need_reset = false;
1156 bool need_reg = false;
1158 if (context_scim && context_scim->impl) {
1159 _focused_ic = context_scim;
1160 isf_imf_context_control_focus_in (ctx);
1162 _panel_client.prepare (context_scim->id);
1164 // Handle the "Shared Input Method" mode.
1165 if (_shared_input_method) {
1166 SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
1167 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1168 if (!factory.null ()) {
1169 if (_default_instance.null () || _default_instance->get_factory_uuid () != factory->get_uuid ()) {
1170 _default_instance = factory->create_instance ("UTF-8", _default_instance.null () ? _instance_count++ : _default_instance->get_id ());
1171 attach_instance (_default_instance);
1172 SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id () << " " << _default_instance->get_factory_uuid () << "\n";
1175 context_scim->impl->shared_si = true;
1176 context_scim->impl->si = _default_instance;
1178 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1179 context_scim->impl->preedit_string.clear ();
1180 context_scim->impl->preedit_attrlist.clear ();
1181 context_scim->impl->preedit_caret = 0;
1182 context_scim->impl->preedit_started = false;
1187 } else if (context_scim->impl->shared_si) {
1188 SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
1189 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
1190 if (!factory.null ()) {
1191 context_scim->impl->si = factory->create_instance ("UTF-8", _instance_count++);
1192 context_scim->impl->preedit_string.clear ();
1193 context_scim->impl->preedit_attrlist.clear ();
1194 context_scim->impl->preedit_caret = 0;
1195 context_scim->impl->preedit_started = false;
1196 attach_instance (context_scim->impl->si);
1199 context_scim->impl->shared_si = false;
1200 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id () << " " << context_scim->impl->si->get_factory_uuid () << "\n";
1204 context_scim->impl->si->set_frontend_data (static_cast <void*> (context_scim));
1206 if (need_reg) _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
1207 if (need_cap) set_ic_capabilities (context_scim);
1209 panel_req_focus_in (context_scim);
1210 // panel_req_update_spot_location (context_scim);
1211 // panel_req_update_factory_info (context_scim);
1213 if (need_reset) context_scim->impl->si->reset ();
1214 if (context_scim->impl->is_on) {
1215 _panel_client.turn_on (context_scim->id);
1216 // _panel_client.hide_preedit_string (context_scim->id);
1217 // _panel_client.hide_aux_string (context_scim->id);
1218 // _panel_client.hide_lookup_table (context_scim->id);
1219 context_scim->impl->si->focus_in ();
1220 imengine_layout_set (ctx, ecore_imf_context_input_panel_layout_get (ctx));
1221 set_prediction_allow (context_scim->impl->si, context_scim->impl->prediction_allow);
1222 if (context_scim->impl->imdata)
1223 context_scim->impl->si->set_imdata ((const char *)context_scim->impl->imdata, context_scim->impl->imdata_size);
1225 _panel_client.turn_off (context_scim->id);
1228 _panel_client.send ();
1231 LOGD ("ctx : %p\n", ctx);
1233 if (ecore_imf_context_input_panel_enabled_get (ctx))
1234 ecore_imf_context_input_panel_show (ctx);
1236 LOGD ("ctx : %p input panel enable : FALSE\n", ctx);
1240 * isf_imf_context_focus_out
1241 * @ctx: a #Ecore_IMF_Context
1243 * This function will be called by Ecore IMF.
1245 * Notify the Input Method Context that the widget to which its correspond has lost focus.
1248 isf_imf_context_focus_out (Ecore_IMF_Context *ctx)
1250 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1253 if (!context_scim) return;
1255 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1257 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1259 WideString wstr = context_scim->impl->preedit_string;
1261 LOGD ("ctx : %p\n", ctx);
1263 if (ecore_imf_context_input_panel_enabled_get (ctx))
1264 ecore_imf_context_input_panel_hide (ctx);
1266 if (context_scim->impl->need_commit_preedit) {
1267 panel_slot_hide_preedit_string (context_scim->id);
1269 if (wstr.length ()) {
1270 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1271 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1273 _panel_client.prepare (context_scim->id);
1274 _panel_client.reset_input_context (context_scim->id);
1275 _panel_client.send ();
1278 lock_scr = check_focus_out_by_lockscreen (ctx);
1281 _panel_client.prepare (context_scim->id);
1283 context_scim->impl->si->focus_out ();
1284 context_scim->impl->si->reset ();
1287 // if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1288 _panel_client.focus_out (context_scim->id);
1289 _panel_client.send ();
1296 * isf_imf_context_reset
1297 * @ctx: a #Ecore_IMF_Context
1299 * This function will be called by Ecore IMF.
1301 * Notify the Input Method Context that a change such as a change in cursor
1302 * position has been made. This will typically cause the Input Method Context
1303 * to clear the preedit state.
1306 isf_imf_context_reset (Ecore_IMF_Context *ctx)
1308 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1310 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1312 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1313 WideString wstr = context_scim->impl->preedit_string;
1315 _panel_client.prepare (context_scim->id);
1316 context_scim->impl->si->reset ();
1317 _panel_client.reset_input_context (context_scim->id);
1318 _panel_client.send ();
1320 if (context_scim->impl->need_commit_preedit) {
1321 panel_slot_hide_preedit_string (context_scim->id);
1323 if (wstr.length ()) {
1324 ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
1325 ecore_imf_context_event_callback_call (context_scim->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
1332 * isf_imf_context_cursor_position_set
1333 * @ctx: a #Ecore_IMF_Context
1334 * @cursor_pos: New cursor position in characters.
1336 * This function will be called by Ecore IMF.
1338 * Notify the Input Method Context that a change in the cursor position has been made.
1341 isf_imf_context_cursor_position_set (Ecore_IMF_Context *ctx, int cursor_pos)
1343 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1345 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1347 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1348 if (context_scim->impl->cursor_pos != cursor_pos) {
1349 LOGD ("ctx : %p, cursor pos : %d\n", ctx, cursor_pos);
1350 context_scim->impl->cursor_pos = cursor_pos;
1352 caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1354 if (context_scim->impl->preedit_updating)
1356 _panel_client.prepare (context_scim->id);
1357 context_scim->impl->si->update_cursor_position (cursor_pos);
1358 panel_req_update_cursor_position (context_scim, cursor_pos);
1359 _panel_client.send ();
1365 * isf_imf_context_cursor_location_set
1366 * @ctx: a #Ecore_IMF_Context
1367 * @x: x position of New cursor.
1368 * @y: y position of New cursor.
1369 * @w: the width of New cursor.
1370 * @h: the height of New cursor.
1372 * This function will be called by Ecore IMF.
1374 * Notify the Input Method Context that a change in the cursor location has been made.
1377 isf_imf_context_cursor_location_set (Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
1379 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1381 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1383 int canvas_x, canvas_y;
1384 int new_cursor_x, new_cursor_y;
1386 if (cw == 0 && ch == 0)
1389 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1390 if (context_scim->impl->client_canvas) {
1391 ee = ecore_evas_ecore_evas_get (context_scim->impl->client_canvas);
1394 ecore_evas_geometry_get (ee, &canvas_x, &canvas_y, NULL, NULL);
1397 if (context_scim->impl->client_window)
1398 window_to_screen_geometry_get (context_scim->impl->client_window, &canvas_x, &canvas_y);
1403 new_cursor_x = canvas_x + cx;
1404 new_cursor_y = canvas_y + cy + ch;
1406 // Don't update spot location while updating preedit string.
1407 if (context_scim->impl->preedit_updating && (context_scim->impl->cursor_y == new_cursor_y))
1410 if (context_scim->impl->cursor_x != new_cursor_x || context_scim->impl->cursor_y != new_cursor_y) {
1411 context_scim->impl->cursor_x = new_cursor_x;
1412 context_scim->impl->cursor_y = new_cursor_y;
1413 context_scim->impl->cursor_top_y = canvas_y + cy;
1414 _panel_client.prepare (context_scim->id);
1415 panel_req_update_spot_location (context_scim);
1416 _panel_client.send ();
1417 SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
1423 * isf_imf_context_input_mode_set
1424 * @ctx: a #Ecore_IMF_Context
1425 * @input_mode: the input mode
1427 * This function will be called by Ecore IMF.
1429 * To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
1430 * is in Ecore_IMF.h.
1433 isf_imf_context_input_mode_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
1435 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1437 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1438 if (context_scim && context_scim->impl) {
1439 context_scim->impl->input_mode = input_mode;
1444 * isf_imf_context_preedit_string_get
1445 * @ctx: a #Ecore_IMF_Context
1446 * @str: the preedit string
1447 * @cursor_pos: the cursor position
1449 * This function will be called by Ecore IMF.
1451 * To get the preedit string of the input method.
1454 isf_imf_context_preedit_string_get (Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
1456 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1458 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1460 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1461 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1465 *str = strdup (mbs.c_str ());
1471 *cursor_pos = context_scim->impl->preedit_caret;
1483 isf_imf_context_preedit_string_with_attributes_get (Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
1485 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1487 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1489 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1490 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1494 *str = strdup (mbs.c_str ());
1500 *cursor_pos = context_scim->impl->preedit_caret;
1504 if (mbs.length ()) {
1505 int start_index, end_index;
1506 int wlen = context_scim->impl->preedit_string.length ();
1507 Ecore_IMF_Preedit_Attr *attr = NULL;
1508 AttributeList::const_iterator i;
1509 bool *attrs_flag = new bool [mbs.length ()];
1510 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1511 for (i = context_scim->impl->preedit_attrlist.begin ();
1512 i != context_scim->impl->preedit_attrlist.end (); ++i) {
1513 start_index = i->get_start ();
1514 end_index = i->get_end ();
1515 if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1516 start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1517 end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1518 if (i->get_type () == SCIM_ATTR_DECORATE) {
1519 attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof (Ecore_IMF_Preedit_Attr));
1522 attr->start_index = start_index;
1523 attr->end_index = end_index;
1525 if (i->get_value () == SCIM_ATTR_DECORATE_UNDERLINE) {
1526 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1527 *attrs = eina_list_append (*attrs, (void *)attr);
1528 } else if (i->get_value () == SCIM_ATTR_DECORATE_REVERSE) {
1529 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1530 *attrs = eina_list_append (*attrs, (void *)attr);
1531 } else if (i->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
1532 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
1533 *attrs = eina_list_append (*attrs, (void *)attr);
1534 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR1) {
1535 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB4;
1536 *attrs = eina_list_append (*attrs, (void *)attr);
1537 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR2) {
1538 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB5;
1539 *attrs = eina_list_append (*attrs, (void *)attr);
1540 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR3) {
1541 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB6;
1542 *attrs = eina_list_append (*attrs, (void *)attr);
1543 } else if (i->get_value () == SCIM_ATTR_DECORATE_BGCOLOR4) {
1544 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB7;
1545 *attrs = eina_list_append (*attrs, (void *)attr);
1549 switch(i->get_value())
1551 case SCIM_ATTR_DECORATE_UNDERLINE:
1552 case SCIM_ATTR_DECORATE_REVERSE:
1553 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1554 case SCIM_ATTR_DECORATE_BGCOLOR1:
1555 case SCIM_ATTR_DECORATE_BGCOLOR2:
1556 case SCIM_ATTR_DECORATE_BGCOLOR3:
1557 case SCIM_ATTR_DECORATE_BGCOLOR4:
1558 // Record which character has attribute.
1559 for (int pos = start_index; pos < end_index; ++pos)
1560 attrs_flag [pos] = 1;
1565 } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1566 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1567 } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1568 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1572 // Add underline for all characters which don't have attribute.
1573 for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1574 if (!attrs_flag [pos]) {
1575 int begin_pos = pos;
1576 while (pos < mbs.length () && !attrs_flag [pos])
1578 // use REVERSE style as default
1579 attr = (Ecore_IMF_Preedit_Attr *)calloc (1, sizeof (Ecore_IMF_Preedit_Attr));
1582 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1583 attr->start_index = begin_pos;
1584 attr->end_index = pos;
1585 *attrs = eina_list_append(*attrs, (void *)attr);
1588 delete [] attrs_flag;
1604 * isf_imf_context_use_preedit_set
1605 * @ctx: a #Ecore_IMF_Context
1606 * @use_preedit: Whether the IM context should use the preedit string.
1608 * This function will be called by Ecore IMF.
1610 * Set whether the IM context should use the preedit string to display feedback.
1611 * If is 0 (default is 1), then the IM context may use some other method to
1612 * display feedback, such as displaying it in a child of the root window.
1615 isf_imf_context_use_preedit_set (Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
1617 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (use_preedit == EINA_TRUE ? "true" : "false") << "...\n";
1619 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1621 if (!_on_the_spot) return;
1623 if (context_scim && context_scim->impl) {
1624 bool old = context_scim->impl->use_preedit;
1625 context_scim->impl->use_preedit = use_preedit;
1626 if (context_scim == _focused_ic) {
1627 _panel_client.prepare (context_scim->id);
1629 if (old != use_preedit)
1630 set_ic_capabilities (context_scim);
1632 if (context_scim->impl->preedit_string.length ())
1633 slot_show_preedit_string (context_scim->impl->si);
1635 _panel_client.send ();
1641 * isf_imf_context_prediction_allow_set
1642 * @ctx: a #Ecore_IMF_Context
1643 * @prediction: Whether the IM context should use the prediction.
1645 * This function will be called by Ecore IMF.
1647 * Set whether the IM context should use the prediction.
1650 isf_imf_context_prediction_allow_set (Ecore_IMF_Context* ctx, Eina_Bool prediction)
1652 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction == EINA_TRUE ? "true" : "false") << "...\n";
1654 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1656 if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction) {
1657 context_scim->impl->prediction_allow = prediction;
1658 set_prediction_allow (context_scim->impl->si, prediction);
1663 * isf_imf_context_prediction_allow_get
1664 * @ctx: a #Ecore_IMF_Context
1666 * This function will be called by Ecore IMF.
1668 * To get prediction allow flag for the IM context.
1670 * Return value: the prediction allow flag for the IM context
1673 isf_imf_context_prediction_allow_get (Ecore_IMF_Context* ctx)
1675 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1677 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1679 Eina_Bool ret = EINA_FALSE;
1680 if (context_scim && context_scim->impl) {
1681 ret = context_scim->impl->prediction_allow;
1683 std::cerr << __FUNCTION__ << " failed!!!\n";
1689 * isf_imf_context_autocapital_type_set
1690 * @ctx: a #Ecore_IMF_Context
1691 * @autocapital_type: the autocapital type for the IM context.
1693 * This function will be called by Ecore IMF.
1695 * Set autocapital type for the IM context.
1698 isf_imf_context_autocapital_type_set (Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1700 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1702 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1704 if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1705 context_scim->impl->autocapital_type = autocapital_type;
1710 * isf_imf_context_filter_event
1711 * @ctx: a #Ecore_IMF_Context
1712 * @type: The type of event defined by Ecore_IMF_Event_Type.
1713 * @event: The event itself.
1714 * Return value: %TRUE if the input method handled the key event.
1716 * This function will be called by Ecore IMF.
1718 * Allow an Ecore Input Context to internally handle an event. If this function
1719 * returns 1, then no further processing should be done for this event. Input
1720 * methods must be able to accept all types of events (simply returning 0 if
1721 * the event was not handled), but there is no obligation of any events to be
1722 * submitted to this function.
1725 isf_imf_context_filter_event (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
1727 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1729 EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
1730 Eina_Bool ret = EINA_FALSE;
1732 if (ic == NULL || ic->impl == NULL)
1736 unsigned int timestamp;
1738 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1739 Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
1740 timestamp = ev->timestamp;
1741 scim_string_to_key (key, ev->key);
1742 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1743 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1744 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1745 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1746 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1747 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1748 } else if (type == ECORE_IMF_EVENT_KEY_UP) {
1749 Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
1750 timestamp = ev->timestamp;
1751 scim_string_to_key (key, ev->key);
1752 key.mask = SCIM_KEY_ReleaseMask;
1753 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
1754 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
1755 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
1756 if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR) key.mask |=SCIM_KEY_Mod5Mask;
1757 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
1758 if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
1759 } else if (type == ECORE_IMF_EVENT_MOUSE_UP) {
1760 if (ecore_imf_context_input_panel_enabled_get (ctx)) {
1761 LOGD ("[Mouse-up event] ctx : %p\n", ctx);
1762 if (ic == _focused_ic)
1763 ecore_imf_context_input_panel_show (ctx);
1765 LOGW ("Can't show IME because there is no focus. ctx : %p\n", ctx);
1772 key.mask &= _valid_key_mask;
1774 _panel_client.prepare (ic->id);
1777 if (!filter_hotkeys (ic, key)) {
1778 if (timestamp == 0) {
1780 // in case of generated event
1781 if (type == ECORE_IMF_EVENT_KEY_DOWN) {
1782 char code = key.get_ascii_code ();
1783 if (isgraph (code)) {
1784 char string[2] = {0};
1785 snprintf (string, sizeof (string), "%c", code);
1787 if (strlen (string) != 0) {
1788 ecore_imf_context_commit_event_add (ic->ctx, string);
1789 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)string);
1790 caps_mode_check (ctx, EINA_FALSE, EINA_TRUE);
1795 _panel_client.send ();
1799 if (!_focused_ic || !_focused_ic->impl->is_on ||
1800 !_focused_ic->impl->si->process_key_event (key)) {
1805 _panel_client.send ();
1811 * Set up an ISE specific data
1813 * @param[in] ctx a #Ecore_IMF_Context
1814 * @param[in] data pointer of data to sets up to ISE
1815 * @param[in] length length of data
1817 EAPI void isf_imf_context_imdata_set (Ecore_IMF_Context *ctx, const void* data, int length)
1819 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " data length ( " << length << ") ...\n";
1820 EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
1822 if (context_scim == NULL || data == NULL || length <= 0)
1825 if (context_scim && context_scim->impl) {
1826 if (context_scim->impl->imdata)
1827 free (context_scim->impl->imdata);
1829 context_scim->impl->imdata = calloc (1, length);
1830 memcpy (context_scim->impl->imdata, data, length);
1831 context_scim->impl->imdata_size = length;
1833 if (context_scim->impl->si && _focused_ic == context_scim) {
1834 _panel_client.prepare (context_scim->id);
1835 context_scim->impl->si->set_imdata ((const char *)data, length);
1836 _panel_client.send ();
1840 isf_imf_context_input_panel_imdata_set (ctx, data, length);
1844 * Get the ISE specific data from ISE
1846 * @param[in] ctx a #Ecore_IMF_Context
1847 * @param[out] data pointer of data to return
1848 * @param[out] length length of data
1850 EAPI void isf_imf_context_imdata_get (Ecore_IMF_Context *ctx, void* data, int* length)
1852 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1854 isf_imf_context_input_panel_imdata_get (ctx, data, length);
1857 /* Panel Slot functions */
1859 panel_slot_reload_config (int context)
1861 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1867 panel_slot_exit (int /* context */)
1869 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1875 panel_slot_update_candidate_item_layout (int context, const std::vector<uint32> &row_items)
1877 EcoreIMFContextISF *ic = find_ic (context);
1878 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " row size=" << row_items.size () << " ic=" << ic << "\n";
1879 if (ic && ic->impl) {
1880 _panel_client.prepare (ic->id);
1881 ic->impl->si->update_candidate_item_layout (row_items);
1882 _panel_client.send ();
1887 panel_slot_update_lookup_table_page_size (int context, int page_size)
1889 EcoreIMFContextISF *ic = find_ic (context);
1890 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
1891 if (ic && ic->impl) {
1892 _panel_client.prepare (ic->id);
1893 ic->impl->si->update_lookup_table_page_size (page_size);
1894 _panel_client.send ();
1899 panel_slot_lookup_table_page_up (int context)
1901 EcoreIMFContextISF *ic = find_ic (context);
1902 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1903 if (ic && ic->impl) {
1904 _panel_client.prepare (ic->id);
1905 ic->impl->si->lookup_table_page_up ();
1906 _panel_client.send ();
1911 panel_slot_lookup_table_page_down (int context)
1913 EcoreIMFContextISF *ic = find_ic (context);
1914 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
1915 if (ic && ic->impl) {
1916 _panel_client.prepare (ic->id);
1917 ic->impl->si->lookup_table_page_down ();
1918 _panel_client.send ();
1923 panel_slot_trigger_property (int context, const String &property)
1925 EcoreIMFContextISF *ic = find_ic (context);
1926 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
1927 if (ic && ic->impl) {
1928 _panel_client.prepare (ic->id);
1929 ic->impl->si->trigger_property (property);
1930 _panel_client.send ();
1935 panel_slot_process_helper_event (int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
1937 EcoreIMFContextISF *ic = find_ic (context);
1938 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
1939 << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic != NULL ? ic->impl : 0) << " ic-uuid="
1940 << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "" ) << "\n";
1941 if (ic && ic->impl && ic->impl->si->get_factory_uuid () == target_uuid) {
1942 _panel_client.prepare (ic->id);
1943 SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
1944 ic->impl->si->process_helper_event (helper_uuid, trans);
1945 _panel_client.send ();
1950 panel_slot_move_preedit_caret (int context, int caret_pos)
1952 EcoreIMFContextISF *ic = find_ic (context);
1953 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
1954 if (ic && ic->impl) {
1955 _panel_client.prepare (ic->id);
1956 ic->impl->si->move_preedit_caret (caret_pos);
1957 _panel_client.send ();
1962 panel_slot_update_preedit_caret (int context, int caret)
1964 EcoreIMFContextISF *ic = find_ic (context);
1965 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
1967 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
1968 ic->impl->preedit_caret = caret;
1969 if (ic->impl->use_preedit) {
1970 if (!ic->impl->preedit_started) {
1971 ecore_imf_context_preedit_start_event_add (ic->ctx);
1972 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
1973 ic->impl->preedit_started = true;
1975 ecore_imf_context_preedit_changed_event_add (ic->ctx);
1976 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1978 _panel_client.prepare (ic->id);
1979 _panel_client.update_preedit_caret (ic->id, caret);
1980 _panel_client.send ();
1986 panel_slot_select_aux (int context, int aux_index)
1988 EcoreIMFContextISF *ic = find_ic (context);
1989 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " aux=" << aux_index << " ic=" << ic << "\n";
1990 if (ic && ic->impl) {
1991 _panel_client.prepare (ic->id);
1992 ic->impl->si->select_aux (aux_index);
1993 _panel_client.send ();
1998 panel_slot_select_candidate (int context, int cand_index)
2000 EcoreIMFContextISF *ic = find_ic (context);
2001 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
2002 if (ic && ic->impl) {
2003 _panel_client.prepare (ic->id);
2004 ic->impl->si->select_candidate (cand_index);
2005 _panel_client.send ();
2010 _keyname_to_keycode (const char *keyname)
2014 Display *display = (Display *)ecore_x_display_get ();
2016 keysym = XStringToKeysym (keyname);
2018 if (!strncmp (keyname, "Keycode-", 8)) {
2019 keycode = atoi (keyname + 8);
2021 keycode = XKeysymToKeycode (display, keysym);
2028 feed_key_event (EcoreIMFContextISF *ic, const KeyEvent &key, bool fake)
2030 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2032 if (key.code <= 0x7F ||
2033 (key.code >= SCIM_KEY_BackSpace && key.code <= SCIM_KEY_Delete) ||
2034 (key.code >= SCIM_KEY_Home && key.code <= SCIM_KEY_Hyper_R)) {
2035 // ascii code and function keys
2036 send_x_key_event (key, fake);
2044 panel_slot_process_key_event (int context, const KeyEvent &key)
2046 EcoreIMFContextISF *ic = find_ic (context);
2047 Eina_Bool process_key = EINA_TRUE;
2048 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2049 if (!(ic && ic->impl))
2051 KeyEvent _key = key;
2052 if (key.is_key_press () &&
2053 ecore_imf_context_input_panel_layout_get (ic->ctx) == ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL) {
2054 if (key.code == SHIFT_MODE_OFF ||
2055 key.code == SHIFT_MODE_ON ||
2056 key.code == SHIFT_MODE_LOCK) {
2057 ic->impl->next_shift_status = _key.code;
2058 } else if (key.code == SHIFT_MODE_ENABLE ) {
2059 ic->impl->shift_mode_enabled = true;
2060 } else if (key.code == SHIFT_MODE_DISABLE ) {
2061 ic->impl->shift_mode_enabled = false;
2062 } else if ((key.code >= 'a' && key.code <= 'z') ||
2063 (key.code >= 'A' && key.code <= 'Z')) {
2064 Eina_Bool uppercase;
2065 switch (ic->impl->next_shift_status) {
2067 uppercase = caps_mode_check (ic->ctx, EINA_FALSE, EINA_FALSE);
2069 case SHIFT_MODE_OFF:
2070 uppercase = EINA_FALSE;
2071 ic->impl->next_shift_status = 0;
2074 uppercase = EINA_TRUE;
2075 ic->impl->next_shift_status = 0;
2077 case SHIFT_MODE_LOCK:
2078 uppercase = EINA_TRUE;
2081 uppercase = EINA_FALSE;
2084 if (ic->impl->shift_mode_enabled) {
2086 if(key.code >= 'a' && key.code <= 'z')
2089 if(key.code >= 'A' && key.code <= 'Z')
2096 if (key.code != SHIFT_MODE_OFF &&
2097 key.code != SHIFT_MODE_ON &&
2098 key.code != SHIFT_MODE_LOCK &&
2099 key.code != SHIFT_MODE_ENABLE &&
2100 key.code != SHIFT_MODE_DISABLE) {
2101 if (feed_key_event (ic, _key, false)) return;
2104 if (key.code == SHIFT_MODE_ENABLE ||
2105 key.code == SHIFT_MODE_DISABLE) {
2106 process_key = EINA_FALSE;
2109 _panel_client.prepare (ic->id);
2111 if (!filter_hotkeys (ic, _key)) {
2113 if (!_focused_ic || !_focused_ic->impl->is_on ||
2114 !_focused_ic->impl->si->process_key_event (_key)) {
2115 _fallback_instance->process_key_event (_key);
2120 _panel_client.send ();
2124 panel_slot_commit_string (int context, const WideString &wstr)
2126 EcoreIMFContextISF *ic = find_ic (context);
2127 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2129 if (ic && ic->impl) {
2130 if (_focused_ic != ic)
2133 if (ic->impl->need_commit_preedit)
2134 panel_slot_hide_preedit_string (ic->id);
2135 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2136 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2141 panel_slot_forward_key_event (int context, const KeyEvent &key)
2143 EcoreIMFContextISF *ic = find_ic (context);
2144 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2146 if (strlen (key.get_key_string ().c_str ()) >= 116)
2149 feed_key_event (ic, key, true);
2153 panel_slot_request_help (int context)
2155 EcoreIMFContextISF *ic = find_ic (context);
2156 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2157 if (ic && ic->impl) {
2158 _panel_client.prepare (ic->id);
2159 panel_req_show_help (ic);
2160 _panel_client.send ();
2165 panel_slot_request_factory_menu (int context)
2167 EcoreIMFContextISF *ic = find_ic (context);
2168 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2169 if (ic && ic->impl) {
2170 _panel_client.prepare (ic->id);
2171 panel_req_show_factory_menu (ic);
2172 _panel_client.send ();
2177 panel_slot_change_factory (int context, const String &uuid)
2179 EcoreIMFContextISF *ic = find_ic (context);
2180 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
2181 if (ic && ic->impl) {
2182 _panel_client.prepare (ic->id);
2183 ic->impl->si->reset ();
2184 open_specific_factory (ic, uuid);
2185 _panel_client.send ();
2190 panel_slot_reset_keyboard_ise (int context)
2192 EcoreIMFContextISF *ic = find_ic (context);
2193 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2194 if (ic && ic->impl) {
2195 WideString wstr = ic->impl->preedit_string;
2196 if (ic->impl->need_commit_preedit) {
2197 panel_slot_hide_preedit_string (ic->id);
2199 if (wstr.length ()) {
2200 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
2201 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (wstr).c_str ());
2204 _panel_client.prepare (ic->id);
2205 ic->impl->si->reset ();
2206 _panel_client.send ();
2211 panel_slot_update_keyboard_ise (int context)
2213 EcoreIMFContextISF *ic = find_ic (context);
2214 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2216 _backend->add_module (_config, "socket", false);
2220 panel_slot_show_preedit_string (int context)
2222 EcoreIMFContextISF *ic = find_ic (context);
2223 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << "\n";
2225 if (ic && ic->impl && _focused_ic == ic) {
2226 if (!ic->impl->is_on)
2227 ic->impl->is_on = true;
2229 if (ic->impl->use_preedit) {
2230 if (!ic->impl->preedit_started) {
2231 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
2232 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2233 ic->impl->preedit_started = true;
2234 ic->impl->need_commit_preedit = true;
2237 _panel_client.prepare (ic->id);
2238 _panel_client.show_preedit_string (ic->id);
2239 _panel_client.send ();
2245 panel_slot_hide_preedit_string (int context)
2247 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2249 EcoreIMFContextISF *ic = find_ic (context);
2251 if (ic && ic->impl && _focused_ic == ic) {
2252 if (!ic->impl->is_on)
2253 ic->impl->is_on = true;
2256 if (ic->impl->preedit_string.length ()) {
2257 ic->impl->preedit_string = WideString ();
2258 ic->impl->preedit_caret = 0;
2259 ic->impl->preedit_attrlist.clear ();
2262 if (ic->impl->use_preedit) {
2264 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2265 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2267 if (ic->impl->preedit_started) {
2268 ecore_imf_context_preedit_end_event_add (ic->ctx);
2269 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2270 ic->impl->preedit_started = false;
2271 ic->impl->need_commit_preedit = false;
2274 _panel_client.prepare (ic->id);
2275 _panel_client.hide_preedit_string (ic->id);
2276 _panel_client.send ();
2282 panel_slot_update_preedit_string (int context,
2283 const WideString &str,
2284 const AttributeList &attrs)
2286 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2288 EcoreIMFContextISF *ic = find_ic (context);
2290 if (ic && ic->impl && _focused_ic == ic) {
2291 if (!ic->impl->is_on)
2292 ic->impl->is_on = true;
2294 if (ic->impl->preedit_string != str || str.length ()) {
2295 ic->impl->preedit_string = str;
2296 ic->impl->preedit_attrlist = attrs;
2298 if (ic->impl->use_preedit) {
2299 if (!ic->impl->preedit_started) {
2300 ecore_imf_context_preedit_start_event_add (ic->ctx);
2301 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2302 ic->impl->preedit_started = true;
2303 ic->impl->need_commit_preedit = true;
2305 ic->impl->preedit_caret = str.length ();
2306 ic->impl->preedit_updating = true;
2307 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2308 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2309 ic->impl->preedit_updating = false;
2311 _panel_client.prepare (ic->id);
2312 _panel_client.update_preedit_string (ic->id, str, attrs);
2313 _panel_client.send ();
2320 panel_slot_get_surrounding_text (int context, int maxlen_before, int maxlen_after)
2322 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2324 EcoreIMFContextISF *ic = find_ic (context);
2326 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2328 WideString text = WideString ();
2329 slot_get_surrounding_text (ic->impl->si, text, cursor, maxlen_before, maxlen_after);
2330 _panel_client.prepare (ic->id);
2331 _panel_client.update_surrounding_text (ic->id, text, cursor);
2332 _panel_client.send ();
2337 panel_slot_delete_surrounding_text (int context, int offset, int len)
2339 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2341 EcoreIMFContextISF *ic = find_ic (context);
2343 if (ic && ic->impl && _focused_ic == ic && ic->impl->si)
2344 slot_delete_surrounding_text (ic->impl->si, offset, len);
2348 panel_slot_update_displayed_candidate_number (int context, int number)
2350 EcoreIMFContextISF *ic = find_ic (context);
2351 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " number=" << number << " ic=" << ic << "\n";
2352 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2353 _panel_client.prepare (ic->id);
2354 ic->impl->si->update_displayed_candidate_number (number);
2355 _panel_client.send ();
2360 panel_slot_candidate_more_window_show (int context)
2362 EcoreIMFContextISF *ic = find_ic (context);
2363 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2364 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2365 _panel_client.prepare (ic->id);
2366 ic->impl->si->candidate_more_window_show ();
2367 _panel_client.send ();
2372 panel_slot_candidate_more_window_hide (int context)
2374 EcoreIMFContextISF *ic = find_ic (context);
2375 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
2376 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2377 _panel_client.prepare (ic->id);
2378 ic->impl->si->candidate_more_window_hide ();
2379 _panel_client.send ();
2384 panel_slot_longpress_candidate (int context, int index)
2386 EcoreIMFContextISF *ic = find_ic (context);
2387 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " index=" << index << " ic=" << ic << "\n";
2388 if (ic && ic->impl && _focused_ic == ic && ic->impl->si) {
2389 _panel_client.prepare (ic->id);
2390 ic->impl->si->longpress_candidate (index);
2391 _panel_client.send ();
2396 panel_slot_update_client_id (int context, int client_id)
2398 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " client_id=" << client_id << "\n";
2400 _panel_client_id = client_id;
2403 /* Panel Requestion functions. */
2405 panel_req_show_help (EcoreIMFContextISF *ic)
2407 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2411 help = String (_("Smart Common Input Method platform ")) +
2412 String (SCIM_VERSION) +
2413 String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2415 if (ic && ic->impl) {
2416 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2418 help += utf8_wcstombs (sf->get_name ());
2419 help += String (_(":\n\n"));
2421 help += utf8_wcstombs (sf->get_help ());
2422 help += String (_("\n\n"));
2424 help += utf8_wcstombs (sf->get_credits ());
2426 _panel_client.show_help (ic->id, help);
2431 panel_req_show_factory_menu (EcoreIMFContextISF *ic)
2433 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2435 std::vector<IMEngineFactoryPointer> factories;
2436 std::vector <PanelFactoryInfo> menu;
2438 _backend->get_factories_for_encoding (factories, "UTF-8");
2440 for (size_t i = 0; i < factories.size (); ++ i) {
2441 menu.push_back (PanelFactoryInfo (
2442 factories [i]->get_uuid (),
2443 utf8_wcstombs (factories [i]->get_name ()),
2444 factories [i]->get_language (),
2445 factories [i]->get_icon_file ()));
2449 _panel_client.show_factory_menu (ic->id, menu);
2453 panel_req_update_factory_info (EcoreIMFContextISF *ic)
2455 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2457 if (ic && ic->impl && ic == _focused_ic) {
2458 PanelFactoryInfo info;
2459 if (ic->impl->is_on) {
2460 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2462 info = PanelFactoryInfo (sf->get_uuid (), utf8_wcstombs (sf->get_name ()), sf->get_language (), sf->get_icon_file ());
2464 info = PanelFactoryInfo (String (""), String (_("English/Keyboard")), String ("C"), String (SCIM_KEYBOARD_ICON_FILE));
2466 _panel_client.update_factory_info (ic->id, info);
2471 panel_req_focus_in (EcoreIMFContextISF *ic)
2473 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2475 _panel_client.focus_in (ic->id, ic->impl->si->get_factory_uuid ());
2479 panel_req_update_spot_location (EcoreIMFContextISF *ic)
2481 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2483 _panel_client.update_spot_location (ic->id, ic->impl->cursor_x, ic->impl->cursor_y, ic->impl->cursor_top_y);
2487 panel_req_update_cursor_position (EcoreIMFContextISF *ic, int cursor_pos)
2489 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2491 _panel_client.update_cursor_position (ic->id, cursor_pos);
2495 filter_hotkeys (EcoreIMFContextISF *ic, const KeyEvent &key)
2497 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2501 _frontend_hotkey_matcher.push_key_event (key);
2502 _imengine_hotkey_matcher.push_key_event (key);
2504 FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result ();
2506 if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER) {
2507 if (!ic->impl->is_on)
2512 _display_input_language (ic);
2514 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON) {
2515 if (!ic->impl->is_on) {
2517 _display_input_language (ic);
2520 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF) {
2521 if (ic->impl->is_on) {
2523 _display_input_language (ic);
2526 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY) {
2527 open_next_factory (ic);
2529 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY) {
2530 open_previous_factory (ic);
2532 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU) {
2533 panel_req_show_factory_menu (ic);
2535 } else if (_imengine_hotkey_matcher.is_matched ()) {
2536 ISEInfo info = _imengine_hotkey_matcher.get_match_result ();
2537 ISE_TYPE type = info.type;
2538 if (type == IMENGINE_T)
2539 open_specific_factory (ic, info.uuid);
2540 else if (type == HELPER_T)
2541 _panel_client.start_helper (ic->id, info.uuid);
2548 panel_initialize (void)
2550 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2552 String display_name;
2554 const char *p = getenv ("DISPLAY");
2555 if (p) display_name = String (p);
2558 if (_panel_client.open_connection (_config->get_name (), display_name) >= 0) {
2559 int fd = _panel_client.get_connection_number ();
2561 _panel_iochannel_read_handler = ecore_main_fd_handler_add (fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
2562 // _panel_iochannel_err_handler = ecore_main_fd_handler_add (fd, ECORE_FD_ERROR, panel_iochannel_handler, NULL, NULL, NULL);
2564 SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
2566 EcoreIMFContextISF *context_scim = _ic_list;
2567 while (context_scim != NULL) {
2568 _panel_client.prepare (context_scim->id);
2569 _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
2570 _panel_client.send ();
2571 context_scim = context_scim->next;
2575 _panel_client.prepare (_focused_ic->id);
2576 panel_req_focus_in (_focused_ic);
2577 _panel_client.send ();
2582 std::cerr << "panel_initialize () failed!!!\n";
2587 panel_finalize (void)
2589 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2591 _panel_client.close_connection ();
2593 if (_panel_iochannel_read_handler) {
2594 ecore_main_fd_handler_del (_panel_iochannel_read_handler);
2595 _panel_iochannel_read_handler = 0;
2597 if (_panel_iochannel_err_handler) {
2598 ecore_main_fd_handler_del (_panel_iochannel_err_handler);
2599 _panel_iochannel_err_handler = 0;
2604 panel_iochannel_handler (void *data, Ecore_Fd_Handler *fd_handler)
2606 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2608 if (fd_handler == _panel_iochannel_read_handler) {
2609 if (_panel_client.has_pending_event () && !_panel_client.filter_event ()) {
2611 panel_initialize ();
2612 return ECORE_CALLBACK_CANCEL;
2614 } else if (fd_handler == _panel_iochannel_err_handler) {
2616 panel_initialize ();
2617 return ECORE_CALLBACK_CANCEL;
2619 return ECORE_CALLBACK_RENEW;
2623 turn_on_ic (EcoreIMFContextISF *ic)
2625 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2627 if (ic && ic->impl && !ic->impl->is_on) {
2628 ic->impl->is_on = true;
2630 if (ic == _focused_ic) {
2631 panel_req_focus_in (ic);
2632 // panel_req_update_spot_location (ic);
2633 panel_req_update_factory_info (ic);
2634 _panel_client.turn_on (ic->id);
2635 // _panel_client.hide_preedit_string (ic->id);
2636 // _panel_client.hide_aux_string (ic->id);
2637 // _panel_client.hide_lookup_table (ic->id);
2638 ic->impl->si->focus_in ();
2639 ic->impl->si->set_layout (ecore_imf_context_input_panel_layout_get (ic->ctx));
2640 set_prediction_allow (ic->impl->si, ic->impl->prediction_allow);
2643 //Record the IC on/off status
2644 if (_shared_input_method) {
2645 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
2649 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2650 ecore_imf_context_preedit_start_event_add (ic->ctx);
2651 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2652 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2653 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2654 ic->impl->preedit_started = true;
2660 turn_off_ic (EcoreIMFContextISF *ic)
2662 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2664 if (ic && ic->impl && ic->impl->is_on) {
2665 ic->impl->is_on = false;
2667 if (ic == _focused_ic) {
2668 ic->impl->si->focus_out ();
2670 // panel_req_update_factory_info (ic);
2671 _panel_client.turn_off (ic->id);
2674 //Record the IC on/off status
2675 if (_shared_input_method) {
2676 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2680 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2681 ecore_imf_context_preedit_changed_event_add (ic->ctx);
2682 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2683 ecore_imf_context_preedit_end_event_add (ic->ctx);
2684 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2685 ic->impl->preedit_started = false;
2691 set_ic_capabilities (EcoreIMFContextISF *ic)
2693 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2695 if (ic && ic->impl) {
2696 unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2698 if (!_on_the_spot || !ic->impl->use_preedit)
2699 cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2701 ic->impl->si->update_client_capabilities (cap);
2706 check_socket_frontend (void)
2708 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2710 SocketAddress address;
2711 SocketClient client;
2715 address.set_address (scim_get_default_socket_frontend_address ());
2717 if (!client.connect (address))
2720 if (!scim_socket_open_connection (magic,
2721 String ("ConnectionTester"),
2722 String ("SocketFrontEnd"),
2734 std::vector<String> config_list;
2735 std::vector<String> engine_list;
2736 std::vector<String> helper_list;
2737 std::vector<String> load_engine_list;
2739 std::vector<String>::iterator it;
2741 bool manual = false;
2743 String config_module_name = "simple";
2745 SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore ISF IMModule...\n";
2747 // Get system language.
2748 _language = scim_get_locale_language (scim_get_current_locale ());
2751 // If no Socket FrontEnd is running, then launch one.
2752 // And set manual to false.
2753 bool check_result = check_socket_frontend ();
2754 if (!check_result) {
2755 std::cerr << "Launching a ISF daemon with Socket FrontEnd...\n";
2757 scim_get_imengine_module_list (engine_list);
2758 scim_get_helper_module_list (helper_list);
2760 for (it = engine_list.begin (); it != engine_list.end (); it++) {
2761 if (*it != "socket")
2762 load_engine_list.push_back (*it);
2764 for (it = helper_list.begin (); it != helper_list.end (); it++)
2765 load_engine_list.push_back (*it);
2766 const char *new_argv [] = { "--no-stay", 0 };
2769 (load_engine_list.size () > 0 ? scim_combine_string_list (load_engine_list, ',') : "none"),
2775 // If there is one Socket FrontEnd running and it's not manual mode,
2776 // then just use this Socket Frontend.
2778 for (int i = 0; i < 200; ++i) {
2780 config_module_name = "socket";
2781 load_engine_list.clear ();
2782 load_engine_list.push_back ("socket");
2785 scim_usleep (50000);
2786 check_result = check_socket_frontend ();
2791 if (config_module_name != "dummy") {
2792 //load config module
2793 SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
2794 _config_module = new ConfigModule (config_module_name);
2796 //create config instance
2797 if (_config_module != NULL && _config_module->valid ())
2798 _config = _config_module->create_config ();
2801 if (_config.null ()) {
2802 SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
2804 if (_config_module) delete _config_module;
2805 _config_module = NULL;
2807 _config = new DummyConfig ();
2808 config_module_name = "dummy";
2811 reload_config_callback (_config);
2812 _config->signal_connect_reload (slot (reload_config_callback));
2815 _backend = new CommonBackEnd (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list);
2817 if (_backend.null ()) {
2818 std::cerr << "Cannot create BackEnd Object!\n";
2820 _backend->initialize (_config, load_engine_list.size () > 0 ? load_engine_list : engine_list, false, false);
2821 _fallback_factory = _backend->get_factory (SCIM_COMPOSE_KEY_FACTORY_UUID);
2824 if (_fallback_factory.null ())
2825 _fallback_factory = new DummyIMEngineFactory ();
2827 _fallback_instance = _fallback_factory->create_instance (String ("UTF-8"), 0);
2828 _fallback_instance->signal_connect_commit_string (slot (fallback_commit_string_cb));
2830 // Attach Panel Client signal.
2831 _panel_client.signal_connect_reload_config (slot (panel_slot_reload_config));
2832 _panel_client.signal_connect_exit (slot (panel_slot_exit));
2833 _panel_client.signal_connect_update_candidate_item_layout (slot (panel_slot_update_candidate_item_layout));
2834 _panel_client.signal_connect_update_lookup_table_page_size (slot (panel_slot_update_lookup_table_page_size));
2835 _panel_client.signal_connect_lookup_table_page_up (slot (panel_slot_lookup_table_page_up));
2836 _panel_client.signal_connect_lookup_table_page_down (slot (panel_slot_lookup_table_page_down));
2837 _panel_client.signal_connect_trigger_property (slot (panel_slot_trigger_property));
2838 _panel_client.signal_connect_process_helper_event (slot (panel_slot_process_helper_event));
2839 _panel_client.signal_connect_move_preedit_caret (slot (panel_slot_move_preedit_caret));
2840 _panel_client.signal_connect_update_preedit_caret (slot (panel_slot_update_preedit_caret));
2841 _panel_client.signal_connect_select_aux (slot (panel_slot_select_aux));
2842 _panel_client.signal_connect_select_candidate (slot (panel_slot_select_candidate));
2843 _panel_client.signal_connect_process_key_event (slot (panel_slot_process_key_event));
2844 _panel_client.signal_connect_commit_string (slot (panel_slot_commit_string));
2845 _panel_client.signal_connect_forward_key_event (slot (panel_slot_forward_key_event));
2846 _panel_client.signal_connect_request_help (slot (panel_slot_request_help));
2847 _panel_client.signal_connect_request_factory_menu (slot (panel_slot_request_factory_menu));
2848 _panel_client.signal_connect_change_factory (slot (panel_slot_change_factory));
2849 _panel_client.signal_connect_reset_keyboard_ise (slot (panel_slot_reset_keyboard_ise));
2850 _panel_client.signal_connect_update_keyboard_ise (slot (panel_slot_update_keyboard_ise));
2851 _panel_client.signal_connect_show_preedit_string (slot (panel_slot_show_preedit_string));
2852 _panel_client.signal_connect_hide_preedit_string (slot (panel_slot_hide_preedit_string));
2853 _panel_client.signal_connect_update_preedit_string (slot (panel_slot_update_preedit_string));
2854 _panel_client.signal_connect_get_surrounding_text (slot (panel_slot_get_surrounding_text));
2855 _panel_client.signal_connect_delete_surrounding_text (slot (panel_slot_delete_surrounding_text));
2856 _panel_client.signal_connect_update_displayed_candidate_number (slot (panel_slot_update_displayed_candidate_number));
2857 _panel_client.signal_connect_candidate_more_window_show (slot (panel_slot_candidate_more_window_show));
2858 _panel_client.signal_connect_candidate_more_window_hide (slot (panel_slot_candidate_more_window_hide));
2859 _panel_client.signal_connect_longpress_candidate (slot (panel_slot_longpress_candidate));
2860 _panel_client.signal_connect_update_client_id (slot (panel_slot_update_client_id));
2862 if (!panel_initialize ()) {
2863 std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
2870 SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
2872 // Reset this first so that the shared instance could be released correctly afterwards.
2873 _default_instance.reset ();
2875 SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2876 while (_used_ic_impl_list) {
2877 // In case in "shared input method" mode,
2878 // all contexts share only one instance,
2879 // so we need point the reference pointer correctly before finalizing.
2880 _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2881 isf_imf_context_del (_used_ic_impl_list->parent->ctx);
2884 delete_all_ic_impl ();
2886 _fallback_instance.reset ();
2887 _fallback_factory.reset ();
2889 SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
2892 SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2895 if (_config_module) {
2896 SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
2897 delete _config_module;
2904 _scim_initialized = false;
2906 _panel_client.reset_signal_handler ();
2911 _popup_message (const char *_ptext)
2916 notification_status_message_post(_ptext);
2920 _display_input_language (EcoreIMFContextISF *ic)
2922 IMEngineFactoryPointer sf;
2924 if (ic && ic->impl) {
2925 if (ic->impl->is_on) {
2926 sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2927 _popup_message (scim_get_language_name (sf->get_language ()).c_str ());
2930 _popup_message (scim_get_language_name ("en").c_str());
2936 open_next_factory (EcoreIMFContextISF *ic)
2938 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2939 IMEngineFactoryPointer sf = _backend->get_next_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2943 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2944 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2945 ic->impl->preedit_string = WideString ();
2946 ic->impl->preedit_caret = 0;
2947 attach_instance (ic->impl->si);
2948 _backend->set_default_factory (_language, sf->get_uuid ());
2949 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2950 _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2951 set_ic_capabilities (ic);
2954 if (_shared_input_method) {
2955 _default_instance = ic->impl->si;
2956 ic->impl->shared_si = true;
2958 _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2963 open_previous_factory (EcoreIMFContextISF *ic)
2968 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
2969 IMEngineFactoryPointer sf = _backend->get_previous_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2973 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2974 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2975 ic->impl->preedit_string = WideString ();
2976 ic->impl->preedit_caret = 0;
2977 attach_instance (ic->impl->si);
2978 _backend->set_default_factory (_language, sf->get_uuid ());
2979 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2980 _panel_client.set_candidate_style (ic->id, ONE_LINE_CANDIDATE, FIXED_CANDIDATE_WINDOW);
2981 set_ic_capabilities (ic);
2984 if (_shared_input_method) {
2985 _default_instance = ic->impl->si;
2986 ic->impl->shared_si = true;
2988 _popup_message (utf8_wcstombs (sf->get_name ()).c_str ());
2993 open_specific_factory (EcoreIMFContextISF *ic,
2999 SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
3001 // The same input method is selected, just turn on the IC.
3002 if (ic->impl->si->get_factory_uuid () == uuid) {
3007 IMEngineFactoryPointer sf = _backend->get_factory (uuid);
3009 if (uuid.length () && !sf.null ()) {
3011 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
3012 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
3013 ic->impl->preedit_string = WideString ();
3014 ic->impl->preedit_caret = 0;
3015 attach_instance (ic->impl->si);
3016 _backend->set_default_factory (_language, sf->get_uuid ());
3017 _panel_client.register_input_context (ic->id, sf->get_uuid ());
3018 set_ic_capabilities (ic);
3021 if (_shared_input_method) {
3022 _default_instance = ic->impl->si;
3023 ic->impl->shared_si = true;
3026 std::cerr << "open_specific_factory () is failed!!!!!!\n";
3027 LOGE ("open_specific_factory () is failed. ic : %x uuid : %s", ic->id, uuid.c_str());
3029 // turn_off_ic comment out panel_req_update_factory_info ()
3031 if (ic && ic->impl->is_on) {
3032 ic->impl->is_on = false;
3034 if (ic == _focused_ic) {
3035 ic->impl->si->focus_out ();
3037 panel_req_update_factory_info (ic);
3038 _panel_client.turn_off (ic->id);
3041 //Record the IC on/off status
3042 if (_shared_input_method) {
3043 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
3047 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
3048 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3049 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3050 ecore_imf_context_preedit_end_event_add (ic->ctx);
3051 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
3052 ic->impl->preedit_started = false;
3058 static void initialize_modifier_bits (Display *display)
3060 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3062 if (__current_display == display)
3065 __current_display = display;
3068 __current_alt_mask = Mod1Mask;
3069 __current_meta_mask = ShiftMask | Mod1Mask;
3070 __current_super_mask = 0;
3071 __current_hyper_mask = 0;
3072 __current_numlock_mask = Mod2Mask;
3076 XModifierKeymap *mods = NULL;
3078 ::KeyCode ctrl_l = XKeysymToKeycode (display, XK_Control_L);
3079 ::KeyCode ctrl_r = XKeysymToKeycode (display, XK_Control_R);
3080 ::KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
3081 ::KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
3082 ::KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
3083 ::KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
3084 ::KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
3085 ::KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
3086 ::KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
3087 ::KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
3088 ::KeyCode numlock = XKeysymToKeycode (display, XK_Num_Lock);
3092 mods = XGetModifierMapping (display);
3096 __current_alt_mask = 0;
3097 __current_meta_mask = 0;
3098 __current_super_mask = 0;
3099 __current_hyper_mask = 0;
3100 __current_numlock_mask = 0;
3102 /* We skip the first three sets for Shift, Lock, and Control. The
3103 remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
3104 for (i = 3; i < 8; i++) {
3105 for (j = 0; j < mods->max_keypermod; j++) {
3106 ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
3107 if (! code) continue;
3108 if (code == alt_l || code == alt_r)
3109 __current_alt_mask |= (1 << i);
3110 else if (code == meta_l || code == meta_r)
3111 __current_meta_mask |= (1 << i);
3112 else if (code == super_l || code == super_r)
3113 __current_super_mask |= (1 << i);
3114 else if (code == hyper_l || code == hyper_r)
3115 __current_hyper_mask |= (1 << i);
3116 else if (code == numlock)
3117 __current_numlock_mask |= (1 << i);
3121 /* Check whether there is a combine keys mapped to Meta */
3122 if (__current_meta_mask == 0) {
3125 KeySym keysym_l, keysym_r;
3127 xkey.type = KeyPress;
3128 xkey.display = display;
3130 xkey.send_event = False;
3131 xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
3133 xkey.same_screen = False;
3134 xkey.subwindow = None;
3136 xkey.root = DefaultRootWindow (display);
3137 xkey.state = ShiftMask;
3139 xkey.keycode = meta_l;
3140 XLookupString (&xkey, buf, 32, &keysym_l, 0);
3141 xkey.keycode = meta_r;
3142 XLookupString (&xkey, buf, 32, &keysym_r, 0);
3144 if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
3145 __current_meta_mask = ShiftMask + __current_alt_mask;
3146 else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
3147 __current_meta_mask = ShiftMask + ControlMask;
3150 XFreeModifiermap (mods);
3153 static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask)
3155 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3157 unsigned int state = 0;
3159 initialize_modifier_bits (display);
3161 if (scimkeymask & SCIM_KEY_ShiftMask) state |= ShiftMask;
3162 if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
3163 if (scimkeymask & SCIM_KEY_ControlMask) state |= ControlMask;
3164 if (scimkeymask & SCIM_KEY_AltMask) state |= __current_alt_mask;
3165 if (scimkeymask & SCIM_KEY_MetaMask) state |= __current_meta_mask;
3166 if (scimkeymask & SCIM_KEY_SuperMask) state |= __current_super_mask;
3167 if (scimkeymask & SCIM_KEY_HyperMask) state |= __current_hyper_mask;
3168 if (scimkeymask & SCIM_KEY_NumLockMask) state |= __current_numlock_mask;
3173 static XKeyEvent createKeyEvent (bool press, int keycode, int modifiers, bool fake)
3175 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3179 Display *display = (Display *)ecore_x_display_get ();
3180 int revert = RevertToParent;
3182 XGetInputFocus (display, &focus_win, &revert);
3184 event.display = display;
3185 event.window = focus_win;
3186 event.root = DefaultRootWindow (display);
3187 event.subwindow = None;
3191 event.time = get_time ();
3197 event.same_screen = True;
3198 event.state = modifiers;
3199 event.keycode = keycode;
3201 event.type = KeyPress;
3203 event.type = KeyRelease;
3204 event.send_event = False;
3210 static void send_x_key_event (const KeyEvent &key, bool fake)
3212 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3214 ::KeyCode keycode = 0;
3215 ::KeySym keysym = 0;
3217 char key_string[256] = {0};
3218 char keysym_str[256] = {0};
3220 // Obtain the X11 display.
3221 Display *display = (Display *)ecore_x_display_get ();
3222 if (display == NULL) {
3223 std::cerr << "ecore_x_display_get () failed\n";
3227 if (strncmp (key.get_key_string ().c_str (), "KeyRelease+", 11) == 0) {
3228 snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str () + 11);
3230 snprintf (key_string, sizeof (key_string), "%s", key.get_key_string ().c_str ());
3233 if (strncmp (key_string, "Shift+", 6) == 0) {
3234 snprintf (keysym_str, sizeof (keysym_str), "%s", key_string + 6);
3236 snprintf (keysym_str, sizeof (keysym_str), "%s", key_string);
3239 // get x keysym, keycode, keyname, and key
3240 keysym = XStringToKeysym (keysym_str);
3241 if (keysym == NoSymbol)
3244 keycode = _keyname_to_keycode (keysym_str);
3245 if (XkbKeycodeToKeysym (display, keycode, 0, 0) != keysym) {
3246 if (XkbKeycodeToKeysym (display, keycode, 0, 1) == keysym)
3257 int keycode_min, keycode_max, keycode_num;
3260 XDisplayKeycodes (display, &keycode_min, &keycode_max);
3261 keysyms = XGetKeyboardMapping (display, keycode_min,
3262 keycode_max - keycode_min + 1,
3264 mod = (mod + 1) & 0x7;
3265 i = (keycode_max - keycode_min - mod - 1) * keycode_num;
3267 keysyms[i] = keysym;
3268 XChangeKeyboardMapping (display, keycode_min, keycode_num,
3269 keysyms, (keycode_max - keycode_min));
3271 XSync (display, False);
3272 keycode = keycode_max - mod - 1;
3275 unsigned int modifier = scim_x11_keymask_scim_to_x11 (display, key.mask);
3278 modifier |= ShiftMask;
3281 if (key.is_key_press ()) {
3283 event = createKeyEvent (true, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3284 XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3287 event = createKeyEvent (true, keycode, modifier, fake);
3288 XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
3290 event = createKeyEvent (false, keycode, modifier, fake);
3291 XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3294 event = createKeyEvent (false, XKeysymToKeycode (display, XK_Shift_L), modifier, fake);
3295 XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
3301 attach_instance (const IMEngineInstancePointer &si)
3303 si->signal_connect_show_preedit_string (
3304 slot (slot_show_preedit_string));
3305 si->signal_connect_show_aux_string (
3306 slot (slot_show_aux_string));
3307 si->signal_connect_show_lookup_table (
3308 slot (slot_show_lookup_table));
3310 si->signal_connect_hide_preedit_string (
3311 slot (slot_hide_preedit_string));
3312 si->signal_connect_hide_aux_string (
3313 slot (slot_hide_aux_string));
3314 si->signal_connect_hide_lookup_table (
3315 slot (slot_hide_lookup_table));
3317 si->signal_connect_update_preedit_caret (
3318 slot (slot_update_preedit_caret));
3319 si->signal_connect_update_preedit_string (
3320 slot (slot_update_preedit_string));
3321 si->signal_connect_update_aux_string (
3322 slot (slot_update_aux_string));
3323 si->signal_connect_update_lookup_table (
3324 slot (slot_update_lookup_table));
3326 si->signal_connect_commit_string (
3327 slot (slot_commit_string));
3329 si->signal_connect_forward_key_event (
3330 slot (slot_forward_key_event));
3332 si->signal_connect_register_properties (
3333 slot (slot_register_properties));
3335 si->signal_connect_update_property (
3336 slot (slot_update_property));
3338 si->signal_connect_beep (
3341 si->signal_connect_start_helper (
3342 slot (slot_start_helper));
3344 si->signal_connect_stop_helper (
3345 slot (slot_stop_helper));
3347 si->signal_connect_send_helper_event (
3348 slot (slot_send_helper_event));
3350 si->signal_connect_get_surrounding_text (
3351 slot (slot_get_surrounding_text));
3353 si->signal_connect_delete_surrounding_text (
3354 slot (slot_delete_surrounding_text));
3356 si->signal_connect_expand_candidate (
3357 slot (slot_expand_candidate));
3358 si->signal_connect_contract_candidate (
3359 slot (slot_contract_candidate));
3361 si->signal_connect_set_candidate_style (
3362 slot (slot_set_candidate_style));
3365 // Implementation of slot functions
3367 slot_show_preedit_string (IMEngineInstanceBase *si)
3369 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3371 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3373 if (ic && ic->impl && _focused_ic == ic) {
3374 if (ic->impl->use_preedit) {
3375 if (!ic->impl->preedit_started) {
3376 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3377 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3378 ic->impl->preedit_started = true;
3380 //if (ic->impl->preedit_string.length ())
3381 // ecore_imf_context_preedit_changed_event_add (_focused_ic->ctx);
3383 _panel_client.show_preedit_string (ic->id);
3389 slot_show_aux_string (IMEngineInstanceBase *si)
3391 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3393 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3395 if (ic && ic->impl && _focused_ic == ic)
3396 _panel_client.show_aux_string (ic->id);
3400 slot_show_lookup_table (IMEngineInstanceBase *si)
3402 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3404 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3406 if (ic && ic->impl && _focused_ic == ic)
3407 _panel_client.show_lookup_table (ic->id);
3411 slot_hide_preedit_string (IMEngineInstanceBase *si)
3413 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3415 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3417 if (ic && ic->impl && _focused_ic == ic) {
3419 if (ic->impl->preedit_string.length ()) {
3420 ic->impl->preedit_string = WideString ();
3421 ic->impl->preedit_caret = 0;
3422 ic->impl->preedit_attrlist.clear ();
3425 if (ic->impl->use_preedit) {
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);
3430 if (ic->impl->preedit_started) {
3431 ecore_imf_context_preedit_end_event_add (ic->ctx);
3432 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
3433 ic->impl->preedit_started = false;
3436 _panel_client.hide_preedit_string (ic->id);
3442 slot_hide_aux_string (IMEngineInstanceBase *si)
3444 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3446 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3448 if (ic && ic->impl && _focused_ic == ic)
3449 _panel_client.hide_aux_string (ic->id);
3453 slot_hide_lookup_table (IMEngineInstanceBase *si)
3455 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3457 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3459 if (ic && ic->impl && _focused_ic == ic)
3460 _panel_client.hide_lookup_table (ic->id);
3464 slot_update_preedit_caret (IMEngineInstanceBase *si, int caret)
3466 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3468 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3470 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
3471 ic->impl->preedit_caret = caret;
3472 if (ic->impl->use_preedit) {
3473 if (!ic->impl->preedit_started) {
3474 ecore_imf_context_preedit_start_event_add (ic->ctx);
3475 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3476 ic->impl->preedit_started = true;
3478 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3479 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3481 _panel_client.update_preedit_caret (ic->id, caret);
3487 slot_update_preedit_string (IMEngineInstanceBase *si,
3488 const WideString & str,
3489 const AttributeList & attrs)
3491 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3493 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3495 if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length ())) {
3496 ic->impl->preedit_string = str;
3497 ic->impl->preedit_attrlist = attrs;
3498 if (ic->impl->use_preedit) {
3499 if (!ic->impl->preedit_started) {
3500 ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
3501 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
3502 ic->impl->preedit_started = true;
3504 ic->impl->preedit_caret = str.length ();
3505 ic->impl->preedit_updating = true;
3506 ecore_imf_context_preedit_changed_event_add (ic->ctx);
3507 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
3508 ic->impl->preedit_updating = false;
3510 _panel_client.update_preedit_string (ic->id, str, attrs);
3516 slot_update_aux_string (IMEngineInstanceBase *si,
3517 const WideString & str,
3518 const AttributeList & attrs)
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)
3525 _panel_client.update_aux_string (ic->id, str, attrs);
3529 slot_commit_string (IMEngineInstanceBase *si,
3530 const WideString & str)
3532 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3534 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3536 if (ic && ic->ctx) {
3537 if (strcmp (utf8_wcstombs (str).c_str (), " ") == 0)
3538 autoperiod_insert (ic->ctx);
3540 ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (str).c_str ());
3541 ecore_imf_context_event_callback_call (ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3546 slot_forward_key_event (IMEngineInstanceBase *si,
3547 const KeyEvent & key)
3549 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3551 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3553 if (ic && _focused_ic == ic) {
3554 if (!_fallback_instance->process_key_event (key)) {
3555 feed_key_event (ic, key, true);
3561 slot_update_lookup_table (IMEngineInstanceBase *si,
3562 const LookupTable & table)
3564 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3566 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3568 if (ic && ic->impl && _focused_ic == ic)
3569 _panel_client.update_lookup_table (ic->id, table);
3573 slot_register_properties (IMEngineInstanceBase *si,
3574 const PropertyList & properties)
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 _panel_client.register_properties (ic->id, properties);
3585 slot_update_property (IMEngineInstanceBase *si,
3586 const Property & property)
3588 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3590 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3592 if (ic && ic->impl && _focused_ic == ic)
3593 _panel_client.update_property (ic->id, property);
3597 slot_beep (IMEngineInstanceBase *si)
3599 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3601 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3603 if (ic && ic->impl && _focused_ic == ic)
3608 slot_start_helper (IMEngineInstanceBase *si,
3609 const String &helper_uuid)
3611 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3613 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3614 << (ic != NULL ? ic->id : -1) << " ic=" << ic
3615 << " ic-uuid=" << ((ic != NULL ) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3618 _panel_client.start_helper (ic->id, helper_uuid);
3622 slot_stop_helper (IMEngineInstanceBase *si,
3623 const String &helper_uuid)
3625 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3627 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic != NULL ? ic->id : -1) << " ic=" << ic << "...\n";
3630 _panel_client.stop_helper (ic->id, helper_uuid);
3634 slot_send_helper_event (IMEngineInstanceBase *si,
3635 const String &helper_uuid,
3636 const Transaction &trans)
3638 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3640 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
3641 << (ic != NULL ? ic->id : -1) << " ic=" << ic
3642 << " ic-uuid=" << ((ic != NULL) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
3645 _panel_client.send_helper_event (ic->id, helper_uuid, trans);
3649 slot_get_surrounding_text (IMEngineInstanceBase *si,
3655 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3657 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3659 if (ic && ic->impl && _focused_ic == ic) {
3660 char *surrounding = NULL;
3662 if (ecore_imf_context_surrounding_get (_focused_ic->ctx, &surrounding, &cursor_index)) {
3663 SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
3664 SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
3665 WideString before = utf8_mbstowcs (String (surrounding));
3666 if (cursor_index > (int)before.length())
3668 WideString after = before;
3669 before = before.substr (0, cursor_index);
3670 after = after.substr (cursor_index, after.length () - cursor_index);
3671 if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length ())
3672 before = WideString (before.begin () + (before.length () - maxlen_before), before.end ());
3673 else if (maxlen_before == 0)
3674 before = WideString ();
3675 if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length ())
3676 after = WideString (after.begin (), after.begin () + maxlen_after);
3677 else if (maxlen_after == 0)
3678 after = WideString ();
3679 text = before + after;
3680 cursor = before.length ();
3688 slot_delete_surrounding_text (IMEngineInstanceBase *si,
3692 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3694 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3696 if (ic && ic->impl && _focused_ic == ic) {
3697 Ecore_IMF_Event_Delete_Surrounding ev;
3698 ev.ctx = _focused_ic->ctx;
3701 ecore_imf_context_delete_surrounding_event_add (_focused_ic->ctx, offset, len);
3702 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
3709 slot_expand_candidate (IMEngineInstanceBase *si)
3711 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3713 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3715 if (ic && ic->impl && _focused_ic == ic)
3716 _panel_client.expand_candidate (ic->id);
3720 slot_contract_candidate (IMEngineInstanceBase *si)
3722 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3724 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3726 if (ic && ic->impl && _focused_ic == ic)
3727 _panel_client.contract_candidate (ic->id);
3731 slot_set_candidate_style (IMEngineInstanceBase *si, ISF_CANDIDATE_PORTRAIT_LINE_T portrait_line, ISF_CANDIDATE_MODE_T mode)
3733 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3735 EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
3737 if (ic && ic->impl && _focused_ic == ic)
3738 _panel_client.set_candidate_style (ic->id, portrait_line, mode);
3742 reload_config_callback (const ConfigPointer &config)
3744 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3746 _frontend_hotkey_matcher.load_hotkeys (config);
3747 _imengine_hotkey_matcher.load_hotkeys (config);
3750 scim_string_to_key (key,
3751 config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
3752 String ("Shift+Control+Alt+Lock")));
3754 _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
3755 _valid_key_mask |= SCIM_KEY_ReleaseMask;
3756 // Special treatment for two backslash keys on jp106 keyboard.
3757 _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
3759 _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
3760 _shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
3762 // Get keyboard layout setting
3763 // Flush the global config first, in order to load the new configs from disk.
3764 scim_global_config_flush ();
3766 _keyboard_layout = scim_get_default_keyboard_layout ();
3770 fallback_commit_string_cb (IMEngineInstanceBase *si,
3771 const WideString &str)
3773 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
3775 if (_focused_ic && _focused_ic->impl) {
3776 ecore_imf_context_commit_event_add (_focused_ic->ctx, utf8_wcstombs (str).c_str ());
3777 ecore_imf_context_event_callback_call (_focused_ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs (str).c_str ());
3782 vi:ts=4:expandtab:nowrap