--- /dev/null
+#define Uses_SCIM_DEBUG
+#define Uses_SCIM_BACKEND
+#define Uses_SCIM_IMENGINE_MODULE
+#define Uses_SCIM_HOTKEY
+#define Uses_SCIM_PANEL_CLIENT
+
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <unistd.h>
+#include <pthread.h>
+#include <Ecore_Evas.h>
+#include <Ecore_X.h>
+#include <Ecore.h>
+#include <Evas.h>
+
+#include <X11/Xlib.h>
+#include <X11/keysym.h>
+#include <X11/Xutil.h>
+
+#include <scim.h>
+#include "scim_imcontext.h"
+
+using namespace scim;
+
+struct _EcoreIMFContextISFImpl
+{
+ EcoreIMFContextISF *parent;
+ IMEngineInstancePointer si;
+ Ecore_X_Window client_window;
+ Evas *client_canvas;
+ Ecore_IMF_Input_Mode input_mode;
+ WideString preedit_string;
+ AttributeList preedit_attrlist;
+ Ecore_IMF_Autocapital_Type autocapital_type;
+ int preedit_caret;
+ int cursor_x;
+ int cursor_y;
+ int cursor_pos;
+ bool use_preedit;
+ bool is_on;
+ bool shared_si;
+ bool preedit_started;
+ bool preedit_updating;
+ bool need_commit_preedit;
+ bool uppercase;
+ bool prediction_allow;
+
+ EcoreIMFContextISFImpl *next;
+};
+
+/* Input Context handling functions. */
+static EcoreIMFContextISFImpl *new_ic_impl (EcoreIMFContextISF *parent);
+static void delete_ic_impl (EcoreIMFContextISFImpl *impl);
+static void delete_all_ic_impl (void);
+
+static EcoreIMFContextISF *find_ic (int id);
+
+
+/* private functions */
+static void panel_slot_reload_config (int context);
+static void panel_slot_exit (int context);
+static void panel_slot_update_lookup_table_page_size(int context,
+ int page_size);
+static void panel_slot_lookup_table_page_up (int context);
+static void panel_slot_lookup_table_page_down (int context);
+static void panel_slot_trigger_property (int context,
+ const String &property);
+static void panel_slot_process_helper_event (int context,
+ const String &target_uuid,
+ const String &helper_uuid,
+ const Transaction &trans);
+static void panel_slot_move_preedit_caret (int context,
+ int caret_pos);
+static void panel_slot_select_candidate (int context,
+ int cand_index);
+static void panel_slot_process_key_event (int context,
+ const KeyEvent &key);
+static void panel_slot_commit_string (int context,
+ const WideString &wstr);
+static void panel_slot_forward_key_event (int context,
+ const KeyEvent &key);
+static void panel_slot_request_help (int context);
+static void panel_slot_request_factory_menu (int context);
+static void panel_slot_change_factory (int context,
+ const String &uuid);
+
+static void panel_req_focus_in (EcoreIMFContextISF *ic);
+static void panel_req_update_factory_info (EcoreIMFContextISF *ic);
+static void panel_req_update_spot_location (EcoreIMFContextISF *ic);
+static void panel_req_show_help (EcoreIMFContextISF *ic);
+static void panel_req_show_factory_menu (EcoreIMFContextISF *ic);
+
+/* Panel iochannel handler*/
+static bool panel_initialize (void);
+static void panel_finalize (void);
+static Eina_Bool panel_iochannel_handler (void *data,
+ Ecore_Fd_Handler *fd_handler);
+
+/* utility functions */
+static bool filter_hotkeys (EcoreIMFContextISF *ic,
+ const KeyEvent &key);
+static void turn_on_ic (EcoreIMFContextISF *ic);
+static void turn_off_ic (EcoreIMFContextISF *ic);
+static void set_ic_capabilities (EcoreIMFContextISF *ic);
+
+static void initialize (void);
+static void finalize (void);
+
+static void open_next_factory (EcoreIMFContextISF *ic);
+static void open_previous_factory (EcoreIMFContextISF *ic);
+static void open_specific_factory (EcoreIMFContextISF *ic,
+ const String &uuid);
+static void initialize_modifier_bits (Display *display);
+static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask);
+static XKeyEvent createKeyEvent (Display *display, Window &win,
+ Window &winRoot, bool press,
+ int keycode, int modifiers);
+static void _x_send_key_event (const KeyEvent &key);
+
+static void attach_instance (const IMEngineInstancePointer &si);
+
+/* slot functions */
+static void slot_show_preedit_string (IMEngineInstanceBase *si);
+static void slot_show_aux_string (IMEngineInstanceBase *si);
+static void slot_show_lookup_table (IMEngineInstanceBase *si);
+
+static void slot_hide_preedit_string (IMEngineInstanceBase *si);
+static void slot_hide_aux_string (IMEngineInstanceBase *si);
+static void slot_hide_lookup_table (IMEngineInstanceBase *si);
+
+static void slot_update_preedit_caret (IMEngineInstanceBase *si,
+ int caret);
+static void slot_update_preedit_string (IMEngineInstanceBase *si,
+ const WideString &str,
+ const AttributeList &attrs);
+static void slot_update_aux_string (IMEngineInstanceBase *si,
+ const WideString &str,
+ const AttributeList &attrs);
+static void slot_commit_string (IMEngineInstanceBase *si,
+ const WideString &str);
+static void slot_forward_key_event (IMEngineInstanceBase *si,
+ const KeyEvent &key);
+static void slot_update_lookup_table (IMEngineInstanceBase *si,
+ const LookupTable &table);
+
+static void slot_register_properties (IMEngineInstanceBase *si,
+ const PropertyList &properties);
+static void slot_update_property (IMEngineInstanceBase *si,
+ const Property &property);
+static void slot_beep (IMEngineInstanceBase *si);
+static void slot_start_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid);
+static void slot_stop_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid);
+static void slot_send_helper_event (IMEngineInstanceBase *si,
+ const String &helper_uuid,
+ const Transaction &trans);
+static bool slot_get_surrounding_text (IMEngineInstanceBase *si,
+ WideString &text,
+ int &cursor,
+ int maxlen_before,
+ int maxlen_after);
+static bool slot_delete_surrounding_text (IMEngineInstanceBase *si,
+ int offset,
+ int len);
+
+static void reload_config_callback (const ConfigPointer &config);
+
+static void fallback_commit_string_cb (IMEngineInstanceBase *si,
+ const WideString &str);
+
+static void caps_mode_check (Ecore_IMF_Context *ctx, Eina_Bool force);
+
+/* Local variables declaration */
+static String _language;
+static EcoreIMFContextISFImpl *_used_ic_impl_list = 0;
+static EcoreIMFContextISFImpl *_free_ic_impl_list = 0;
+static EcoreIMFContextISF *_ic_list = 0;
+
+static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
+static int _valid_key_mask = SCIM_KEY_AllMasks;
+
+static FrontEndHotkeyMatcher _frontend_hotkey_matcher;
+static IMEngineHotkeyMatcher _imengine_hotkey_matcher;
+
+static IMEngineInstancePointer _default_instance;
+
+static ConfigModule *_config_module = 0;
+static ConfigPointer _config;
+static BackEndPointer _backend;
+
+static EcoreIMFContextISF *_focused_ic = 0;
+
+static bool _scim_initialized = false;
+
+static int _instance_count = 0;
+static int _context_count = 0;
+
+static IMEngineFactoryPointer _fallback_factory;
+static IMEngineInstancePointer _fallback_instance;
+static PanelClient _panel_client;
+
+static Ecore_Fd_Handler *_panel_iochannel_read_handler = 0;
+static Ecore_Fd_Handler *_panel_iochannel_err_handler = 0;
+
+static Ecore_X_Window _client_window = 0;
+
+static bool _on_the_spot = true;
+static bool _shared_input_method = false;
+
+static Eina_Bool autocap_allow = EINA_FALSE;
+
+static Display *__current_display = 0;
+static int __current_alt_mask = Mod1Mask;
+static int __current_meta_mask = 0;
+static int __current_super_mask = 0;
+static int __current_hyper_mask = 0;
+static int __current_numlock_mask = Mod2Mask;
+
+// A hack to shutdown the immodule cleanly even if im_module_exit () is not called when exiting.
+class FinalizeHandler
+{
+public:
+ FinalizeHandler ()
+ {
+ SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::FinalizeHandler ()\n";
+ }
+ ~FinalizeHandler ()
+ {
+ SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::~FinalizeHandler ()\n";
+ isf_imf_context_shutdown ();
+ }
+};
+
+static FinalizeHandler _finalize_handler;
+
+static unsigned int
+utf8_offset_to_index(const char *str, int offset)
+{
+ int index = 0;
+ int i;
+ for (i = 0; i < offset; i++)
+ {
+ eina_unicode_utf8_get_next(str, &index);
+ }
+
+ return index;
+}
+
+static unsigned int
+get_time (void)
+{
+ unsigned int tint;
+ struct timeval tv;
+ struct timezone tz; /* is not used since ages */
+ gettimeofday (&tv, &tz);
+ tint = tv.tv_sec * 1000;
+ tint = tint / 1000 * 1000;
+ tint = tint + tv.tv_usec / 1000;
+ return tint;
+}
+
+/* Function Implementations */
+static EcoreIMFContextISFImpl *
+new_ic_impl (EcoreIMFContextISF *parent)
+{
+ EcoreIMFContextISFImpl *impl = NULL;
+
+ if (_free_ic_impl_list != NULL)
+ {
+ impl = _free_ic_impl_list;
+ _free_ic_impl_list = _free_ic_impl_list->next;
+ }
+ else
+ {
+ impl = new EcoreIMFContextISFImpl;
+ if (impl == NULL)
+ return NULL;
+ }
+
+ impl->uppercase = false;
+ impl->autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
+ impl->next = _used_ic_impl_list;
+ _used_ic_impl_list = impl;
+
+ impl->parent = parent;
+
+ return impl;
+}
+
+static void
+delete_ic_impl (EcoreIMFContextISFImpl *impl)
+{
+ EcoreIMFContextISFImpl *rec = _used_ic_impl_list, *last = 0;
+
+ for (; rec != 0; last = rec, rec = rec->next)
+ {
+ if (rec == impl)
+ {
+ if (last != 0)
+ last->next = rec->next;
+ else
+ _used_ic_impl_list = rec->next;
+
+ rec->next = _free_ic_impl_list;
+ _free_ic_impl_list = rec;
+
+ rec->parent = 0;
+ rec->si.reset ();
+ rec->client_window = 0;
+ rec->preedit_string = WideString ();
+ rec->preedit_attrlist.clear ();
+
+ return;
+ }
+ }
+}
+
+static void
+delete_all_ic_impl (void)
+{
+ EcoreIMFContextISFImpl *it = _used_ic_impl_list;
+
+ while (it != 0)
+ {
+ _used_ic_impl_list = it->next;
+ delete it;
+ it = _used_ic_impl_list;
+ }
+
+ it = _free_ic_impl_list;
+ while (it != 0)
+ {
+ _free_ic_impl_list = it->next;
+ delete it;
+ it = _free_ic_impl_list;
+ }
+}
+
+static EcoreIMFContextISF *
+find_ic (int id)
+{
+ EcoreIMFContextISFImpl *rec = _used_ic_impl_list;
+
+ while (rec != 0)
+ {
+ if (rec->parent && rec->parent->id == id)
+ return rec->parent;
+ rec = rec->next;
+ }
+
+ return 0;
+}
+
+static Eina_Bool
+analyze_surrounding_text(Ecore_IMF_Context *ctx)
+{
+ char *plain_str = NULL;
+ char *markup_str = NULL;
+ const char *puncs[3] = {". ", "! ", "? "};
+ Eina_Bool ret = EINA_FALSE;
+ int cursor_pos = 0;
+ int i = 0;
+ Eina_Unicode *tail = NULL;
+ Eina_Unicode *ustr = NULL;
+ Eina_Unicode *uni_puncs[3];
+ EcoreIMFContextISF *context_scim;
+
+ if (!ctx) return EINA_FALSE;
+ context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+ if (!context_scim || !context_scim->impl) return EINA_FALSE;
+
+ switch (context_scim->impl->autocapital_type)
+ {
+ case ECORE_IMF_AUTOCAPITAL_TYPE_NONE:
+ return EINA_FALSE;
+ case ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER:
+ return EINA_TRUE;
+ default:
+ break;
+ }
+
+ for (i=0; i<3; i++)
+ uni_puncs[i] = eina_unicode_utf8_to_unicode(puncs[i], NULL);
+
+ ecore_imf_context_surrounding_get(ctx, &markup_str, &cursor_pos);
+ if (!markup_str) goto done;
+
+ if (cursor_pos == 0)
+ {
+ ret = EINA_TRUE;
+ goto done;
+ }
+
+ // Convert into plain string
+ plain_str = evas_textblock_text_markup_to_utf8(NULL, markup_str);
+ if (!plain_str) goto done;
+
+ // Convert string from utf8 to unicode
+ ustr = eina_unicode_utf8_to_unicode(plain_str, NULL);
+ if (!ustr) goto done;
+
+ if (cursor_pos >= 1)
+ {
+ if (context_scim->impl->autocapital_type == ECORE_IMF_AUTOCAPITAL_TYPE_WORD)
+ {
+ if (ustr[cursor_pos-1] == ' ')
+ {
+ ret = EINA_TRUE;
+ goto done;
+ }
+ }
+
+ // Check paragraph separator <PS> and carrage return <br>
+ if ((ustr[cursor_pos-1] == 0x2029) || (ustr[cursor_pos-1] == '\n'))
+ {
+ ret = EINA_TRUE;
+ goto done;
+ }
+ }
+
+ // check punctuation
+ if (cursor_pos >= 2)
+ {
+ tail = eina_unicode_strndup(ustr+cursor_pos-2, 2);
+
+ if (tail)
+ {
+ for (i=0; i<3; i++)
+ {
+ if (!eina_unicode_strcmp(tail, uni_puncs[i]))
+ {
+ ret = EINA_TRUE;
+ break;
+ }
+ }
+ free(tail);
+ tail = NULL;
+ }
+ }
+
+done:
+ if (ustr) free(ustr);
+ if (markup_str) free(markup_str);
+ if (plain_str) free(plain_str);
+
+ for (i=0; i<3; i++)
+ if (uni_puncs[i]) free(uni_puncs[i]);
+
+ return ret;
+}
+
+static void
+caps_mode_check(Ecore_IMF_Context *ctx, Eina_Bool force)
+{
+ Eina_Bool uppercase;
+ EcoreIMFContextISF *context_scim;
+
+ if (!ctx) return;
+ context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (autocap_allow == EINA_FALSE)
+ return;
+
+ // Check autocapital type
+ if (!context_scim || !context_scim->impl)
+ return;
+
+ if (analyze_surrounding_text(ctx))
+ uppercase = EINA_TRUE;
+ else
+ uppercase = EINA_FALSE;
+
+ if (force)
+ context_scim->impl->uppercase = uppercase;
+ else
+ if (context_scim->impl->uppercase != uppercase)
+ context_scim->impl->uppercase = uppercase;
+}
+
+static void
+feed_key_event (Evas *evas, const char *str, Eina_Bool fake)
+{
+ char key_string[128] = {0};
+ unsigned int timestamp = 0;
+
+ if (!fake)
+ timestamp = get_time ();
+
+ if (strncmp (str, "KeyRelease+", 11) == 0)
+ {
+ strncpy(key_string, str + 11, strlen(str)-11);
+ evas_event_feed_key_up (evas, key_string, key_string, NULL, NULL, timestamp, NULL);
+ SCIM_DEBUG_FRONTEND(1) << " evas_event_feed_key_up ()...\n";
+ }
+ else
+ {
+ strncpy(key_string, str, strlen(str));
+ evas_event_feed_key_down (evas, key_string, key_string, NULL, NULL, timestamp, NULL);
+ SCIM_DEBUG_FRONTEND(1) << " evas_event_feed_key_down ()...\n";
+ }
+}
+
+/* Public functions */
+/**
+ * isf_imf_context_new
+ *
+ * This function will be called by Ecore IMF.
+ * Create a instance of type EcoreIMFContextISF.
+ *
+ * Return value: A pointer to the newly created EcoreIMFContextISF instance
+ */
+EAPI EcoreIMFContextISF *
+isf_imf_context_new (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+ char *env;
+
+ Ecore_X_Display *display = ecore_x_display_get ();
+ if (!display)
+ {
+ std::cerr << "ecore_x_display_get () failed !!!";
+ return NULL;
+ }
+
+ EcoreIMFContextISF *context_scim = new EcoreIMFContextISF;
+ if (context_scim == NULL)
+ {
+ std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
+ return NULL;
+ }
+
+ context_scim->id = _context_count++;
+
+ if (!_scim_initialized)
+ {
+ initialize ();
+ _scim_initialized = true;
+ }
+
+ env = getenv("ECORE_IMF_AUTOCAPITAL_ALLOW");
+ if (env)
+ autocap_allow = !!atoi(env);
+
+ return context_scim;
+}
+
+/**
+ * isf_imf_shutdown
+ *
+ * It will be called when the scim im module is unloaded by ecore. It will do some
+ * cleanup job.
+ */
+EAPI void
+isf_imf_context_shutdown (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (_scim_initialized)
+ {
+ _scim_initialized = false;
+ finalize ();
+ }
+}
+
+EAPI void
+isf_imf_context_add (Ecore_IMF_Context *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
+
+ if (!context_scim) return;
+
+ context_scim->impl = NULL;
+
+ if (_backend.null ())
+ return;
+
+ IMEngineInstancePointer si;
+
+ // Use the default instance if "shared input method" mode is enabled.
+ if (_shared_input_method && !_default_instance.null ())
+ {
+ si = _default_instance;
+ SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
+ }
+
+ // Not in "shared input method" mode, or no default instance, create an instance.
+ if (si.null ())
+ {
+ IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
+ if (factory.null ()) return;
+ si = factory->create_instance ("UTF-8", _instance_count++);
+ if (si.null ()) return;
+ attach_instance (si);
+ SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
+ }
+
+ // If "shared input method" mode is enabled, and there is no default instance,
+ // then store this instance as default one.
+ if (_shared_input_method && _default_instance.null ())
+ {
+ SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
+ _default_instance = si;
+ }
+
+ context_scim->ctx = ctx;
+ context_scim->impl = new_ic_impl (context_scim);
+ if (context_scim->impl == NULL)
+ {
+ std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
+ return;
+ }
+
+ context_scim->impl->si = si;
+ context_scim->impl->client_window = 0;
+ context_scim->impl->client_canvas = NULL;
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->cursor_x = 0;
+ context_scim->impl->cursor_y = 0;
+ context_scim->impl->cursor_pos = -1;
+ context_scim->impl->is_on = false;
+ context_scim->impl->shared_si = _shared_input_method;
+ context_scim->impl->use_preedit = _on_the_spot;
+ context_scim->impl->preedit_started = false;
+ context_scim->impl->preedit_updating = false;
+ context_scim->impl->need_commit_preedit = false;
+
+ if (!_ic_list)
+ context_scim->next = NULL;
+ else
+ context_scim->next = _ic_list;
+ _ic_list = context_scim;
+
+ if (_shared_input_method)
+ context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
+
+ _panel_client.prepare (context_scim->id);
+ _panel_client.register_input_context (context_scim->id, si->get_factory_uuid ());
+ set_ic_capabilities (context_scim);
+ _panel_client.send ();
+
+ SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
+}
+
+EAPI void
+isf_imf_context_del (Ecore_IMF_Context *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (!_ic_list) return;
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
+
+ if (context_scim)
+ {
+ if (context_scim->id != _ic_list->id)
+ {
+ EcoreIMFContextISF * pre = _ic_list;
+ EcoreIMFContextISF * cur = _ic_list->next;
+ while (cur != NULL)
+ {
+ if (cur->id == context_scim->id)
+ {
+ pre->next = cur->next;
+ break;
+ }
+ pre = cur;
+ cur = cur->next;
+ }
+ }
+ else
+ _ic_list = _ic_list->next;
+ }
+
+ if (context_scim && context_scim->impl)
+ {
+ _panel_client.prepare (context_scim->id);
+
+ if (context_scim == _focused_ic)
+ context_scim->impl->si->focus_out ();
+
+ // Delete the instance.
+ EcoreIMFContextISF *old_focused = _focused_ic;
+ _focused_ic = context_scim;
+ context_scim->impl->si.reset ();
+ _focused_ic = old_focused;
+
+ if (context_scim == _focused_ic)
+ {
+ _panel_client.turn_off (context_scim->id);
+ _panel_client.focus_out (context_scim->id);
+ }
+
+ _panel_client.remove_input_context (context_scim->id);
+ _panel_client.send ();
+
+ if (context_scim->impl->client_window)
+ isf_imf_context_client_window_set (ctx, NULL);
+
+ if (context_scim->impl)
+ {
+ delete_ic_impl (context_scim->impl);
+ context_scim->impl = 0;
+ }
+ }
+
+ if (context_scim == _focused_ic)
+ _focused_ic = 0;
+
+ if (context_scim)
+ {
+ delete context_scim;
+ context_scim = 0;
+ }
+}
+
+/**
+ * isf_imf_context_client_canvas_set
+ * @ctx: a #Ecore_IMF_Context
+ * @canvas: the client canvas
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Set the client canvas for the Input Method Context; this is the canvas
+ * in which the input appears.
+ *
+ * The canvas type can be determined by using the context canvas type.
+ * Actually only canvas with type "evas" (Evas *) is supported. This canvas
+ * may be used in order to correctly position status windows, and may also
+ * be used for purposes internal to the Input Method Context.
+ */
+EAPI void
+isf_imf_context_client_canvas_set (Ecore_IMF_Context *ctx, void *canvas)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->client_canvas != (Evas*) canvas)
+ context_scim->impl->client_canvas = (Evas*)canvas;
+}
+
+/**
+ * isf_imf_context_client_window_set
+ * @ctx: a #Ecore_IMF_Context
+ * @window: the client window
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Set the client window for the Input Method Context; this is the Ecore_X_Window
+ * when using X11, Ecore_Win32_Window when using Win32, etc.
+ *
+ * This window is used in order to correctly position status windows,
+ * and may also be used for purposes internal to the Input Method Context.
+ */
+EAPI void
+isf_imf_context_client_window_set (Ecore_IMF_Context *ctx, void *window)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->client_window != (Ecore_X_Window) window)
+ {
+ context_scim->impl->client_window = (Ecore_X_Window) window;
+
+ if ((context_scim->impl->client_window != 0) &&
+ (context_scim->impl->client_window != _client_window))
+ _client_window = context_scim->impl->client_window;
+ }
+}
+
+/**
+ * isf_imf_context_reset
+ * @ctx: a #Ecore_IMF_Context
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that a change such as a change in cursor
+ * position has been made. This will typically cause the Input Method Context
+ * to clear the preedit state.
+ */
+EAPI void
+isf_imf_context_reset (Ecore_IMF_Context *ctx)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic)
+ {
+ WideString wstr = context_scim->impl->preedit_string;
+
+ _panel_client.prepare (context_scim->id);
+ context_scim->impl->si->reset ();
+ _panel_client.send ();
+
+ if (context_scim->impl->need_commit_preedit)
+ {
+ if (wstr.length ())
+ ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
+
+ _panel_client.prepare (context_scim->id);
+ _panel_client.send ();
+ }
+ }
+}
+
+/**
+ * isf_imf_context_focus_in
+ * @ctx: a #Ecore_IMF_Context
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that the widget to which its correspond has gained focus.
+ */
+EAPI void
+isf_imf_context_focus_in (Ecore_IMF_Context *ctx)
+{
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (!context_scim)
+ return;
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
+
+ if (_focused_ic)
+ {
+ if (_focused_ic == context_scim)
+ {
+ SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
+ //isf_imf_context_cursor_position_set (ctx, 0);
+ return;
+ }
+ SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
+ if (_focused_ic->ctx)
+ isf_imf_context_focus_out (_focused_ic->ctx);
+ }
+
+ bool need_cap = false;
+ bool need_reset = false;
+ bool need_reg = false;
+
+ if (context_scim && context_scim->impl)
+ {
+ _focused_ic = context_scim;
+ _panel_client.prepare (context_scim->id);
+
+ // Handle the "Shared Input Method" mode.
+ if (_shared_input_method)
+ {
+ SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
+ IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
+ if (!factory.null ())
+ {
+ if (_default_instance.null () || _default_instance->get_factory_uuid () != factory->get_uuid ())
+ {
+ _default_instance = factory->create_instance ("UTF-8", _default_instance.null () ? _instance_count++ : _default_instance->get_id ());
+ attach_instance (_default_instance);
+ SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id () << " " << _default_instance->get_factory_uuid () << "\n";
+ }
+
+ context_scim->impl->shared_si = true;
+ context_scim->impl->si = _default_instance;
+
+ context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
+ context_scim->impl->preedit_string.clear ();
+ context_scim->impl->preedit_attrlist.clear ();
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->preedit_started = false;
+ need_cap = true;
+ need_reset = true;
+ need_reg = true;
+ }
+ }
+ else if (context_scim->impl->shared_si)
+ {
+ SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
+ IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
+ if (!factory.null ())
+ {
+ context_scim->impl->si = factory->create_instance ("UTF-8", _instance_count++);
+ context_scim->impl->preedit_string.clear ();
+ context_scim->impl->preedit_attrlist.clear ();
+ context_scim->impl->preedit_caret = 0;
+ context_scim->impl->preedit_started = false;
+ attach_instance (context_scim->impl->si);
+ need_cap = true;
+ need_reg = true;
+ context_scim->impl->shared_si = false;
+ SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id () << " " << context_scim->impl->si->get_factory_uuid () << "\n";
+ }
+ }
+
+ context_scim->impl->si->set_frontend_data (static_cast <void*> (context_scim));
+
+ if (need_reg) _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
+ if (need_cap) set_ic_capabilities (context_scim);
+ if (need_reset) context_scim->impl->si->reset ();
+
+ panel_req_focus_in (context_scim);
+ panel_req_update_spot_location (context_scim);
+ panel_req_update_factory_info (context_scim);
+
+ if (context_scim->impl->is_on)
+ {
+ _panel_client.turn_on (context_scim->id);
+ _panel_client.hide_preedit_string (context_scim->id);
+ _panel_client.hide_aux_string (context_scim->id);
+ _panel_client.hide_lookup_table (context_scim->id);
+ context_scim->impl->si->focus_in ();
+ }
+ else
+ {
+ _panel_client.turn_off (context_scim->id);
+ }
+
+ _panel_client.send ();
+ }
+}
+
+/**
+ * isf_imf_context_focus_out
+ * @ctx: a #Ecore_IMF_Context
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that the widget to which its correspond has lost focus.
+ */
+EAPI void
+isf_imf_context_focus_out (Ecore_IMF_Context *ctx)
+{
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (!context_scim) return;
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic)
+ {
+ WideString wstr = context_scim->impl->preedit_string;
+
+ if (context_scim->impl->need_commit_preedit)
+ {
+ if (wstr.length ())
+ ecore_imf_context_commit_event_add (context_scim->ctx, utf8_wcstombs (wstr).c_str ());
+
+ _panel_client.prepare (context_scim->id);
+ _panel_client.send ();
+ }
+
+ _panel_client.prepare (context_scim->id);
+ context_scim->impl->si->focus_out ();
+ context_scim->impl->si->reset ();
+ _panel_client.turn_off (context_scim->id);
+ _panel_client.focus_out (context_scim->id);
+ _panel_client.send ();
+ _focused_ic = 0;
+ }
+}
+
+/**
+ * isf_imf_context_cursor_location_set
+ * @ctx: a #Ecore_IMF_Context
+ * @x: x position of New cursor.
+ * @y: y position of New cursor.
+ * @w: the width of New cursor.
+ * @h: the height of New cursor.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that a change in the cursor location has been made.
+ */
+EAPI void
+isf_imf_context_cursor_location_set (Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+ Ecore_Evas *ee;
+ int canvas_x, canvas_y;
+
+ if (cw == 0 && ch == 0)
+ return;
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic)
+ {
+ // Don't update spot location while updating preedit string.
+ if (context_scim->impl->preedit_updating)
+ return;
+
+ if (!context_scim->impl->client_canvas)
+ return;
+
+ ee = ecore_evas_ecore_evas_get(context_scim->impl->client_canvas);
+ if (!ee) return;
+
+ ecore_evas_geometry_get (ee, &canvas_x, &canvas_y, NULL, NULL);
+
+ if (context_scim->impl->cursor_x != canvas_x + cx || context_scim->impl->cursor_y != canvas_y + cy + ch)
+ {
+ context_scim->impl->cursor_x = canvas_x + cx;
+ context_scim->impl->cursor_y = canvas_y + cy + ch;
+ _panel_client.prepare (context_scim->id);
+ panel_req_update_spot_location (context_scim);
+ _panel_client.send ();
+ SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
+ }
+ }
+}
+
+/**
+ * isf_imf_context_use_preedit_set
+ * @ctx: a #Ecore_IMF_Context
+ * @use_preedit: Whether the IM context should use the preedit string.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Set whether the IM context should use the preedit string to display feedback.
+ * If is 0 (default is 1), then the IM context may use some other method to
+ * display feedback, such as displaying it in a child of the root window.
+ */
+EAPI void
+isf_imf_context_use_preedit_set (Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (use_preedit ? "true" : "false") << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
+
+ if (!_on_the_spot) return;
+
+ if (context_scim && context_scim->impl)
+ {
+ bool old = context_scim->impl->use_preedit;
+ context_scim->impl->use_preedit = use_preedit;
+ if (context_scim == _focused_ic)
+ {
+ _panel_client.prepare (context_scim->id);
+
+ if (old != use_preedit)
+ set_ic_capabilities (context_scim);
+
+ if (context_scim->impl->preedit_string.length ())
+ slot_show_preedit_string (context_scim->impl->si);
+
+ _panel_client.send ();
+ }
+ }
+}
+
+EAPI void
+isf_imf_context_preedit_string_with_attributes_get (Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->is_on)
+ {
+ String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
+
+ if (str)
+ {
+ if (mbs.length ())
+ *str = strdup (mbs.c_str ());
+ else
+ *str = strdup ("");
+ }
+
+ if (cursor_pos)
+ {
+ *cursor_pos = context_scim->impl->preedit_caret;
+ }
+
+ if (attrs)
+ {
+ if (mbs.length ())
+ {
+ int start_index, end_index;
+ int wlen = context_scim->impl->preedit_string.length ();
+
+ Ecore_IMF_Preedit_Attr *attr = NULL;
+ AttributeList::const_iterator i;
+ bool *attrs_flag = new bool [mbs.length ()];
+ memset (attrs_flag, 0, mbs.length () *sizeof (bool));
+
+ for (i = context_scim->impl->preedit_attrlist.begin ();
+ i != context_scim->impl->preedit_attrlist.end (); ++i)
+ {
+ start_index = i->get_start ();
+ end_index = i->get_end ();
+
+ if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE)
+ {
+ start_index = utf8_offset_to_index (mbs.c_str (), i->get_start ());
+ end_index = utf8_offset_to_index (mbs.c_str (), i->get_end ());
+
+ if (i->get_type () == SCIM_ATTR_DECORATE)
+ {
+ attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
+ if (attr == NULL)
+ continue;
+ attr->start_index = start_index;
+ attr->end_index = end_index;
+
+ if (i->get_value () == SCIM_ATTR_DECORATE_UNDERLINE)
+ {
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
+ *attrs = eina_list_append(*attrs, (void *)attr);
+ }
+ else if (i->get_value () == SCIM_ATTR_DECORATE_REVERSE)
+ {
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
+ *attrs = eina_list_append(*attrs, (void *)attr);
+ }
+ else if (i->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT)
+ {
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
+ *attrs = eina_list_append(*attrs, (void *)attr);
+ }
+ else
+ {
+ free (attr);
+ }
+
+ switch(i->get_value())
+ {
+ case SCIM_ATTR_DECORATE_UNDERLINE:
+ case SCIM_ATTR_DECORATE_REVERSE:
+ case SCIM_ATTR_DECORATE_HIGHLIGHT:
+ // Record which character has attribute.
+ for (int pos = start_index; pos < end_index; ++pos)
+ attrs_flag [pos] = 1;
+ break;
+ default:
+ break;
+ }
+ }
+ else if (i->get_type () == SCIM_ATTR_FOREGROUND)
+ {
+ SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
+ }
+ else if (i->get_type () == SCIM_ATTR_BACKGROUND)
+ {
+ SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
+ }
+ }
+ }
+
+ // Add underline for all characters which don't have attribute.
+ for (unsigned int pos = 0; pos < mbs.length (); ++pos)
+ {
+ if (!attrs_flag [pos])
+ {
+ int begin_pos = pos;
+
+ while (pos < mbs.length () && !attrs_flag [pos])
+ ++pos;
+
+ // use REVERSE style as default
+ attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
+ if (attr == NULL)
+ continue;
+ attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
+ attr->start_index = begin_pos;
+ attr->end_index = pos;
+ *attrs = eina_list_append(*attrs, (void *)attr);
+ }
+ }
+
+ delete [] attrs_flag;
+ }
+ }
+ }
+ else
+ {
+ if (str)
+ *str = strdup ("");
+
+ if (cursor_pos)
+ *cursor_pos = 0;
+
+ if (attrs)
+ *attrs = NULL;
+ }
+}
+
+/**
+ * isf_imf_context_preedit_string_get
+ * @ctx: a #Ecore_IMF_Context
+ * @str: the preedit string
+ * @cursor_pos: the cursor position
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * To get the preedit string of the input method.
+ */
+EAPI void
+isf_imf_context_preedit_string_get (Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->is_on)
+ {
+ String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
+
+ if (str)
+ {
+ if (mbs.length ())
+ *str = strdup (mbs.c_str ());
+ else
+ *str = strdup ("");
+ }
+
+ if (cursor_pos)
+ *cursor_pos = context_scim->impl->preedit_caret;
+ }
+ else
+ {
+ if (str)
+ *str = strdup ("");
+
+ if (cursor_pos)
+ *cursor_pos = 0;
+ }
+}
+
+/**
+ * isf_imf_context_cursor_position_set
+ * @ctx: a #Ecore_IMF_Context
+ * @cursor_pos: New cursor position in characters.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Notify the Input Method Context that a change in the cursor position has been made.
+ */
+EAPI void
+isf_imf_context_cursor_position_set (Ecore_IMF_Context *ctx, int cursor_pos)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (context_scim && context_scim->impl && context_scim == _focused_ic)
+ {
+ // Don't update spot location while updating preedit string.
+ if (context_scim->impl->preedit_updating)
+ return;
+
+ if (context_scim->impl->cursor_pos != cursor_pos)
+ {
+ context_scim->impl->cursor_pos = cursor_pos;
+ caps_mode_check(ctx, EINA_FALSE);
+ }
+ }
+}
+
+/**
+ * isf_imf_context_input_mode_set
+ * @ctx: a #Ecore_IMF_Context
+ * @input_mode: the input mode
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
+ * is in Ecore_IMF.h.
+ */
+EAPI void
+isf_imf_context_input_mode_set (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
+ if (context_scim && context_scim->impl)
+ context_scim->impl->input_mode = input_mode;
+}
+
+/**
+ * isf_imf_context_prediction_allow_set
+ * @ctx: a #Ecore_IMF_Context
+ * @use_prediction: Whether the IM context should use the prediction.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Set whether the IM context should use the prediction.
+ */
+EAPI void
+isf_imf_context_prediction_allow_set (Ecore_IMF_Context* ctx, Eina_Bool prediction)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << (prediction ? "true" : "false") << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->prediction_allow != prediction)
+ context_scim->impl->prediction_allow = prediction;
+}
+
+EAPI void
+isf_imf_context_autocapital_type_set (Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
+
+ EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get (ctx);
+
+ if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type)
+ context_scim->impl->autocapital_type = autocapital_type;
+}
+
+/**
+ * isf_imf_context_filter_event
+ * @ctx: a #Ecore_IMF_Context
+ * @type: The type of event defined by Ecore_IMF_Event_Type.
+ * @event: The event itself.
+ * Return value: %TRUE if the input method handled the key event.
+ *
+ * This function will be called by Ecore IMF.
+ *
+ * Allow an Ecore Input Context to internally handle an event. If this function
+ * returns 1, then no further processing should be done for this event. Input
+ * methods must be able to accept all types of events (simply returning 0 if
+ * the event was not handled), but there is no obligation of any events to be
+ * submitted to this function.
+ */
+
+EAPI Eina_Bool
+isf_imf_context_filter_event (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get (ctx);
+ Eina_Bool ret = EINA_FALSE;
+
+ if (ic == NULL || ic->impl == NULL)
+ return ret;
+
+ KeyEvent key;
+
+ if (type == ECORE_IMF_EVENT_KEY_DOWN)
+ {
+ Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
+ scim_string_to_key (key, ev->key);
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
+ if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
+ if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
+ }
+ else if (type == ECORE_IMF_EVENT_KEY_UP)
+ {
+ Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
+ scim_string_to_key (key, ev->key);
+ key.mask = SCIM_KEY_ReleaseMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT) key.mask |=SCIM_KEY_ShiftMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL) key.mask |=SCIM_KEY_ControlMask;
+ if (ev->modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT) key.mask |=SCIM_KEY_AltMask;
+ if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_CAPS) key.mask |=SCIM_KEY_CapsLockMask;
+ if (ev->locks & ECORE_IMF_KEYBOARD_LOCK_NUM) key.mask |=SCIM_KEY_NumLockMask;
+ }
+ else
+ {
+ return ret;
+ }
+
+ key.mask &= _valid_key_mask;
+
+ _panel_client.prepare (ic->id);
+
+ ret = EINA_TRUE;
+ if (!filter_hotkeys (ic, key))
+ {
+ if (!_focused_ic || !_focused_ic->impl->is_on ||
+ !_focused_ic->impl->si->process_key_event (key))
+ ret = EINA_FALSE;
+ }
+
+ _panel_client.send ();
+
+ return ret;
+}
+
+/* Panel Slot functions */
+static void
+panel_slot_reload_config (int context)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+ _config->reload ();
+}
+
+static void
+panel_slot_exit (int /* context */)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ finalize ();
+}
+
+static void
+panel_slot_update_lookup_table_page_size (int context, int page_size)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->update_lookup_table_page_size (page_size);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_lookup_table_page_up (int context)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->lookup_table_page_up ();
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_lookup_table_page_down (int context)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->lookup_table_page_down ();
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_trigger_property (int context, const String &property)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->trigger_property (property);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_process_helper_event (int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " target=" << target_uuid
+ << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic ? ic->impl : 0) << " ic-uuid="
+ << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "" ) << "\n";
+ if (ic && ic->impl && ic->impl->si->get_factory_uuid () == target_uuid)
+ {
+ _panel_client.prepare (ic->id);
+ SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
+ ic->impl->si->process_helper_event (helper_uuid, trans);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_move_preedit_caret (int context, int caret_pos)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->move_preedit_caret (caret_pos);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_select_candidate (int context, int cand_index)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare (ic->id);
+ ic->impl->si->select_candidate (cand_index);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_process_key_event (int context, const KeyEvent &key)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
+
+ if (ic && ic->impl && ic->impl->client_canvas)
+ feed_key_event(ic->impl->client_canvas, key.get_key_string().c_str(), EINA_FALSE);
+}
+
+static void
+panel_slot_commit_string (int context, const WideString &wstr)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
+
+ if (ic && ic->impl)
+ {
+ if (_focused_ic != ic)
+ return;
+
+ ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (wstr).c_str ());
+ }
+}
+
+static void
+panel_slot_forward_key_event (int context, const KeyEvent &key)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
+
+ if (ic && ic->impl && ic->impl->client_canvas)
+ feed_key_event (ic->impl->client_canvas, key.get_key_string ().c_str (), EINA_TRUE);
+}
+
+static void
+panel_slot_request_help (int context)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare (ic->id);
+ panel_req_show_help (ic);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_request_factory_menu (int context)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " ic=" << ic << "\n";
+
+ if (ic && ic->impl)
+ {
+ _panel_client.prepare (ic->id);
+ panel_req_show_factory_menu (ic);
+ _panel_client.send ();
+ }
+}
+
+static void
+panel_slot_change_factory (int context, const String &uuid)
+{
+ EcoreIMFContextISF *ic = find_ic (context);
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
+
+ if (ic && ic->impl)
+ {
+ ic->impl->si->reset ();
+ _panel_client.prepare (ic->id);
+ open_specific_factory (ic, uuid);
+ _panel_client.send ();
+ }
+}
+
+/* Panel Requestion functions. */
+static void
+panel_req_show_help (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ String help;
+
+ help = String ("Smart Common Input Method platform ") +
+ //String (SCIM_VERSION) +
+ String ("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n");
+
+ if (ic && ic->impl)
+ {
+ IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
+ if (sf)
+ {
+ help += utf8_wcstombs (sf->get_name ());
+ help += String (":\n\n");
+
+ help += utf8_wcstombs (sf->get_help ());
+ help += String ("\n\n");
+
+ help += utf8_wcstombs (sf->get_credits ());
+ }
+ _panel_client.show_help (ic->id, help);
+ }
+}
+
+static void
+panel_req_show_factory_menu (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ std::vector<IMEngineFactoryPointer> factories;
+ std::vector <PanelFactoryInfo> menu;
+
+ _backend->get_factories_for_encoding (factories, "UTF-8");
+
+ for (size_t i = 0; i < factories.size (); ++ i)
+ {
+ menu.push_back (PanelFactoryInfo (
+ factories [i]->get_uuid (),
+ utf8_wcstombs (factories [i]->get_name ()),
+ factories [i]->get_language (),
+ factories [i]->get_icon_file ()));
+ }
+
+ if (menu.size ())
+ _panel_client.show_factory_menu (ic->id, menu);
+}
+
+static void
+panel_req_update_factory_info (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && ic == _focused_ic)
+ {
+ PanelFactoryInfo info;
+ if (ic->impl->is_on)
+ {
+ IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
+ if (sf)
+ info = PanelFactoryInfo (sf->get_uuid (), utf8_wcstombs (sf->get_name ()), sf->get_language (), sf->get_icon_file ());
+ }
+ else
+ {
+ info = PanelFactoryInfo (String (""), String ("English/Keyboard"), String ("C"), "");
+ }
+ _panel_client.update_factory_info (ic->id, info);
+ }
+}
+
+static void
+panel_req_focus_in (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _panel_client.focus_in (ic->id, ic->impl->si->get_factory_uuid ());
+}
+
+static void
+panel_req_update_spot_location (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _panel_client.update_spot_location (ic->id, ic->impl->cursor_x, ic->impl->cursor_y);
+}
+
+static bool
+filter_hotkeys (EcoreIMFContextISF *ic, const KeyEvent &key)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ bool ret = false;
+
+ _frontend_hotkey_matcher.push_key_event (key);
+ _imengine_hotkey_matcher.push_key_event (key);
+
+ FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result ();
+
+ if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER)
+ {
+ if (!ic->impl->is_on)
+ turn_on_ic (ic);
+ else
+ turn_off_ic (ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON)
+ {
+ if (!ic->impl->is_on)
+ turn_on_ic (ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF)
+ {
+ if (ic->impl->is_on)
+ turn_off_ic (ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY)
+ {
+ open_next_factory (ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY)
+ {
+ open_previous_factory (ic);
+ ret = true;
+ }
+ else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU)
+ {
+ panel_req_show_factory_menu (ic);
+ ret = true;
+ }
+ else if (_imengine_hotkey_matcher.is_matched ())
+ {
+ String sfid = _imengine_hotkey_matcher.get_match_result ();
+ open_specific_factory (ic, sfid);
+ ret = true;
+ }
+ return ret;
+}
+
+static bool
+panel_initialize (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ String display_name;
+ {
+ const char *p = getenv ("DISPLAY");
+ if (p) display_name = String (p);
+ }
+
+ if (_panel_client.open_connection (_config->get_name (), display_name) >= 0)
+ {
+ int fd = _panel_client.get_connection_number ();
+
+ _panel_iochannel_read_handler = ecore_main_fd_handler_add (fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
+
+ SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
+
+ return true;
+ }
+ std::cerr << "panel_initialize () failed!!!\n";
+ return false;
+}
+
+static void
+panel_finalize (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _panel_client.close_connection ();
+
+ if (_panel_iochannel_read_handler)
+ {
+ ecore_main_fd_handler_del (_panel_iochannel_read_handler);
+ _panel_iochannel_read_handler = 0;
+ }
+
+ if (_panel_iochannel_err_handler)
+ {
+ ecore_main_fd_handler_del (_panel_iochannel_err_handler);
+ _panel_iochannel_err_handler = 0;
+ }
+}
+
+static Eina_Bool
+panel_iochannel_handler (void *data, Ecore_Fd_Handler *fd_handler)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (fd_handler == _panel_iochannel_read_handler)
+ {
+ if (!_panel_client.filter_event ())
+ {
+ panel_finalize ();
+ panel_initialize ();
+ return ECORE_CALLBACK_CANCEL;
+ }
+ }
+ else if (fd_handler == _panel_iochannel_err_handler)
+ {
+ panel_finalize ();
+ panel_initialize ();
+ return ECORE_CALLBACK_CANCEL;
+ }
+ return ECORE_CALLBACK_RENEW;
+}
+
+static void
+turn_on_ic (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && !ic->impl->is_on)
+ {
+ ic->impl->is_on = true;
+
+ if (ic == _focused_ic)
+ {
+ panel_req_focus_in (ic);
+ panel_req_update_spot_location (ic);
+ panel_req_update_factory_info (ic);
+ _panel_client.turn_on (ic->id);
+ _panel_client.hide_preedit_string (ic->id);
+ _panel_client.hide_aux_string (ic->id);
+ _panel_client.hide_lookup_table (ic->id);
+ ic->impl->si->focus_in ();
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method)
+ _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length ())
+ {
+ ecore_imf_context_preedit_start_event_add (ic->ctx);
+ ecore_imf_context_preedit_changed_event_add (ic->ctx);
+ ic->impl->preedit_started = true;
+ }
+ }
+}
+
+static void
+turn_off_ic (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl && ic->impl->is_on)
+ {
+ ic->impl->is_on = false;
+
+ if (ic == _focused_ic)
+ {
+ ic->impl->si->focus_out ();
+
+ panel_req_update_factory_info (ic);
+ _panel_client.turn_off (ic->id);
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method)
+ _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length ())
+ {
+ ecore_imf_context_preedit_changed_event_add (ic->ctx);
+ ecore_imf_context_preedit_end_event_add (ic->ctx);
+ ic->impl->preedit_started = false;
+ }
+ }
+}
+
+static void
+set_ic_capabilities (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (ic && ic->impl)
+ {
+ unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
+
+ if (!_on_the_spot || !ic->impl->use_preedit)
+ cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
+
+ ic->impl->si->update_client_capabilities (cap);
+ }
+}
+
+static bool
+check_socket_frontend (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ SocketAddress address;
+ SocketClient client;
+
+ uint32 magic;
+
+ address.set_address (scim_get_default_socket_frontend_address ());
+
+ if (!client.connect (address))
+ return false;
+
+ if (!scim_socket_open_connection (magic,
+ String ("ConnectionTester"),
+ String ("SocketFrontEnd"),
+ client,
+ 1000))
+ return false;
+
+ return true;
+}
+
+void
+initialize (void)
+{
+ std::vector<String> config_list;
+ std::vector<String> engine_list;
+ std::vector<String> load_engine_list;
+
+ std::vector<String>::iterator it;
+
+ bool manual = false;
+
+ bool socket = true;
+
+ String config_module_name = "simple";
+
+ printf("Initializing Ecore SCIM IMModule...\n");
+
+ SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore SCIM IMModule...\n";
+
+ // Get system language.
+ _language = scim_get_locale_language (scim_get_current_locale ());
+
+ if (socket)
+ {
+ // If no Socket FrontEnd is running, then launch one.
+ // And set manual to false.
+ bool check_result = check_socket_frontend ();
+ if (!check_result)
+ {
+ std::cerr << "Launching a SCIM daemon with Socket FrontEnd...\n";
+ //get modules list
+ scim_get_imengine_module_list (engine_list);
+
+ for (it = engine_list.begin (); it != engine_list.end (); it++)
+ {
+ if (*it != "socket")
+ load_engine_list.push_back (*it);
+ }
+
+ const char *new_argv [] = { "--no-stay", 0 };
+ scim_launch (true,
+ config_module_name,
+ (load_engine_list.size () ? scim_combine_string_list (load_engine_list, ',') : "none"),
+ "socket",
+ (char **)new_argv);
+ manual = false;
+ }
+
+ // If there is one Socket FrontEnd running and it's not manual mode,
+ // then just use this Socket Frontend.
+ if (!manual)
+ {
+ for (int i = 0; i < 200; ++i)
+ {
+ if (check_result)
+ {
+ config_module_name = "socket";
+ load_engine_list.clear ();
+ load_engine_list.push_back ("socket");
+ break;
+ }
+ scim_usleep (50000);
+ check_result = check_socket_frontend ();
+ }
+ }
+ }
+
+ if (config_module_name != "dummy")
+ {
+ //load config module
+ SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
+ _config_module = new ConfigModule (config_module_name);
+
+ //create config instance
+ if (_config_module != NULL && _config_module->valid ())
+ _config = _config_module->create_config ();
+ }
+
+ if (_config.null ())
+ {
+ SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
+
+ if (_config_module) delete _config_module;
+ _config_module = NULL;
+
+ _config = new DummyConfig ();
+ config_module_name = "dummy";
+ }
+
+ reload_config_callback (_config);
+ _config->signal_connect_reload (slot (reload_config_callback));
+
+ // create backend
+ _backend = new CommonBackEnd (_config, load_engine_list.size () ? load_engine_list : engine_list);
+
+ if (_backend.null ())
+ std::cerr << "Cannot create BackEnd Object!\n";
+ else
+ _fallback_factory = _backend->get_factory (SCIM_COMPOSE_KEY_FACTORY_UUID);
+
+ if (_fallback_factory.null ())
+ _fallback_factory = new DummyIMEngineFactory ();
+
+ _fallback_instance = _fallback_factory->create_instance (String ("UTF-8"), 0);
+ _fallback_instance->signal_connect_commit_string (slot (fallback_commit_string_cb));
+
+ // Attach Panel Client signal.
+ _panel_client.signal_connect_reload_config (slot (panel_slot_reload_config));
+ _panel_client.signal_connect_exit (slot (panel_slot_exit));
+ _panel_client.signal_connect_update_lookup_table_page_size (slot (panel_slot_update_lookup_table_page_size));
+ _panel_client.signal_connect_lookup_table_page_up (slot (panel_slot_lookup_table_page_up));
+ _panel_client.signal_connect_lookup_table_page_down (slot (panel_slot_lookup_table_page_down));
+ _panel_client.signal_connect_trigger_property (slot (panel_slot_trigger_property));
+ _panel_client.signal_connect_process_helper_event (slot (panel_slot_process_helper_event));
+ _panel_client.signal_connect_move_preedit_caret (slot (panel_slot_move_preedit_caret));
+ _panel_client.signal_connect_select_candidate (slot (panel_slot_select_candidate));
+ _panel_client.signal_connect_process_key_event (slot (panel_slot_process_key_event));
+ _panel_client.signal_connect_commit_string (slot (panel_slot_commit_string));
+ _panel_client.signal_connect_forward_key_event (slot (panel_slot_forward_key_event));
+ _panel_client.signal_connect_request_help (slot (panel_slot_request_help));
+ _panel_client.signal_connect_request_factory_menu (slot (panel_slot_request_factory_menu));
+ _panel_client.signal_connect_change_factory (slot (panel_slot_change_factory));
+
+ if (!panel_initialize ())
+ std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
+}
+
+static void
+finalize (void)
+{
+ SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
+
+ // Reset this first so that the shared instance could be released correctly afterwards.
+ _default_instance.reset ();
+
+ SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
+ while (_used_ic_impl_list)
+ {
+ // In case in "shared input method" mode,
+ // all contexts share only one instance,
+ // so we need point the reference pointer correctly before finalizing.
+ _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
+ isf_imf_context_del (_used_ic_impl_list->parent->ctx);
+ }
+
+ delete_all_ic_impl ();
+
+ _fallback_instance.reset ();
+ _fallback_factory.reset ();
+
+ SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
+ _backend.reset ();
+
+ SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
+ _config.reset ();
+
+ if (_config_module)
+ {
+ SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
+ delete _config_module;
+ _config_module = 0;
+ }
+
+ _focused_ic = NULL;
+ _ic_list = NULL;
+
+ _scim_initialized = false;
+
+ panel_finalize ();
+}
+
+static void
+open_next_factory (EcoreIMFContextISF *ic)
+{
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+ IMEngineFactoryPointer sf = _backend->get_next_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
+
+ if (!sf.null ())
+ {
+ turn_off_ic (ic);
+ ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
+ ic->impl->si->set_frontend_data (static_cast <void*> (ic));
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ attach_instance (ic->impl->si);
+ _backend->set_default_factory (_language, sf->get_uuid ());
+ _panel_client.register_input_context (ic->id, sf->get_uuid ());
+ set_ic_capabilities (ic);
+ turn_on_ic (ic);
+
+ if (_shared_input_method)
+ {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ }
+}
+
+static void
+open_previous_factory (EcoreIMFContextISF *ic)
+{
+ if (ic == NULL)
+ return;
+
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+ IMEngineFactoryPointer sf = _backend->get_previous_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
+
+ if (!sf.null ())
+ {
+ turn_off_ic (ic);
+ ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
+ ic->impl->si->set_frontend_data (static_cast <void*> (ic));
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ attach_instance (ic->impl->si);
+ _backend->set_default_factory (_language, sf->get_uuid ());
+ _panel_client.register_input_context (ic->id, sf->get_uuid ());
+ set_ic_capabilities (ic);
+ turn_on_ic (ic);
+
+ if (_shared_input_method)
+ {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ }
+}
+
+static void
+open_specific_factory (EcoreIMFContextISF *ic,
+ const String &uuid)
+{
+ if (ic == NULL)
+ return;
+
+ SCIM_DEBUG_FRONTEND(2) << __FUNCTION__ << " context=" << ic->id << "\n";
+
+ // The same input method is selected, just turn on the IC.
+ if (ic->impl->si->get_factory_uuid () == uuid)
+ {
+ turn_on_ic (ic);
+ return;
+ }
+
+ IMEngineFactoryPointer sf = _backend->get_factory (uuid);
+
+ if (uuid.length () && !sf.null ())
+ {
+ turn_off_ic (ic);
+ ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
+ ic->impl->si->set_frontend_data (static_cast <void*> (ic));
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ attach_instance (ic->impl->si);
+ _backend->set_default_factory (_language, sf->get_uuid ());
+ _panel_client.register_input_context (ic->id, sf->get_uuid ());
+ set_ic_capabilities (ic);
+ turn_on_ic (ic);
+
+ if (_shared_input_method)
+ {
+ _default_instance = ic->impl->si;
+ ic->impl->shared_si = true;
+ }
+ }
+ else
+ {
+ // turn_off_ic comment out panel_req_update_factory_info ()
+ turn_off_ic (ic);
+ if (ic && ic->impl->is_on)
+ {
+ ic->impl->is_on = false;
+
+ if (ic == _focused_ic)
+ {
+ ic->impl->si->focus_out ();
+
+ panel_req_update_factory_info (ic);
+ _panel_client.turn_off (ic->id);
+ }
+
+ //Record the IC on/off status
+ if (_shared_input_method)
+ _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
+
+ if (ic->impl->use_preedit && ic->impl->preedit_string.length ())
+ {
+ ecore_imf_context_preedit_changed_event_add (ic->ctx);
+ ecore_imf_context_preedit_end_event_add (ic->ctx);
+ ic->impl->preedit_started = false;
+ }
+ }
+ }
+}
+
+static void initialize_modifier_bits (Display *display)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (__current_display == display)
+ return;
+
+ __current_display = display;
+
+ if (display == 0)
+ {
+ __current_alt_mask = Mod1Mask;
+ __current_meta_mask = ShiftMask | Mod1Mask;
+ __current_super_mask = 0;
+ __current_hyper_mask = 0;
+ __current_numlock_mask = Mod2Mask;
+ return;
+ }
+
+ XModifierKeymap *mods = NULL;
+
+ ::KeyCode ctrl_l = XKeysymToKeycode (display, XK_Control_L);
+ ::KeyCode ctrl_r = XKeysymToKeycode (display, XK_Control_R);
+ ::KeyCode meta_l = XKeysymToKeycode (display, XK_Meta_L);
+ ::KeyCode meta_r = XKeysymToKeycode (display, XK_Meta_R);
+ ::KeyCode alt_l = XKeysymToKeycode (display, XK_Alt_L);
+ ::KeyCode alt_r = XKeysymToKeycode (display, XK_Alt_R);
+ ::KeyCode super_l = XKeysymToKeycode (display, XK_Super_L);
+ ::KeyCode super_r = XKeysymToKeycode (display, XK_Super_R);
+ ::KeyCode hyper_l = XKeysymToKeycode (display, XK_Hyper_L);
+ ::KeyCode hyper_r = XKeysymToKeycode (display, XK_Hyper_R);
+ ::KeyCode numlock = XKeysymToKeycode (display, XK_Num_Lock);
+
+ int i, j;
+
+ mods = XGetModifierMapping (display);
+ if (mods == NULL)
+ return;
+
+ __current_alt_mask = 0;
+ __current_meta_mask = 0;
+ __current_super_mask = 0;
+ __current_hyper_mask = 0;
+ __current_numlock_mask = 0;
+
+ /* We skip the first three sets for Shift, Lock, and Control. The
+ remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
+ for (i = 3; i < 8; i++)
+ {
+ for (j = 0; j < mods->max_keypermod; j++)
+ {
+ ::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
+ if (! code) continue;
+ if (code == alt_l || code == alt_r)
+ __current_alt_mask |= (1 << i);
+ else if (code == meta_l || code == meta_r)
+ __current_meta_mask |= (1 << i);
+ else if (code == super_l || code == super_r)
+ __current_super_mask |= (1 << i);
+ else if (code == hyper_l || code == hyper_r)
+ __current_hyper_mask |= (1 << i);
+ else if (code == numlock)
+ __current_numlock_mask |= (1 << i);
+ }
+ }
+
+ /* Check whether there is a combine keys mapped to Meta */
+ if (__current_meta_mask == 0)
+ {
+ char buf [32];
+ XKeyEvent xkey;
+ KeySym keysym_l, keysym_r;
+
+ xkey.type = KeyPress;
+ xkey.display = display;
+ xkey.serial = 0L;
+ xkey.send_event = False;
+ xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
+ xkey.time = 0;
+ xkey.same_screen = False;
+ xkey.subwindow = None;
+ xkey.window = None;
+ xkey.root = DefaultRootWindow (display);
+ xkey.state = ShiftMask;
+
+ xkey.keycode = meta_l;
+ XLookupString (&xkey, buf, 32, &keysym_l, 0);
+ xkey.keycode = meta_r;
+ XLookupString (&xkey, buf, 32, &keysym_r, 0);
+
+ if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
+ __current_meta_mask = ShiftMask + __current_alt_mask;
+ else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
+ __current_meta_mask = ShiftMask + ControlMask;
+ }
+
+ XFreeModifiermap (mods);
+}
+
+static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ unsigned int state = 0;
+
+ initialize_modifier_bits (display);
+
+ if (scimkeymask & SCIM_KEY_ShiftMask) state |= ShiftMask;
+ if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
+ if (scimkeymask & SCIM_KEY_ControlMask) state |= ControlMask;
+ if (scimkeymask & SCIM_KEY_AltMask) state |= __current_alt_mask;
+ if (scimkeymask & SCIM_KEY_MetaMask) state |= __current_meta_mask;
+ if (scimkeymask & SCIM_KEY_SuperMask) state |= __current_super_mask;
+ if (scimkeymask & SCIM_KEY_HyperMask) state |= __current_hyper_mask;
+ if (scimkeymask & SCIM_KEY_NumLockMask) state |= __current_numlock_mask;
+
+ return state;
+}
+
+static XKeyEvent createKeyEvent (Display *display, Window &win,
+ Window &winRoot, bool press,
+ int keycode, int modifiers)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ XKeyEvent event;
+
+ event.display = display;
+ event.window = win;
+ event.root = winRoot;
+ event.subwindow = None;
+ event.time = CurrentTime;
+ event.x = 1;
+ event.y = 1;
+ event.x_root = 1;
+ event.y_root = 1;
+ event.same_screen = EINA_TRUE;
+ event.state = modifiers;
+ event.keycode = XKeysymToKeycode (display, keycode);
+ if (press)
+ event.type = KeyPress;
+ else
+ event.type = KeyRelease;
+ event.send_event = EINA_FALSE;
+ event.serial = 0;
+
+ return event;
+}
+
+static void _x_send_key_event (const KeyEvent &key)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ // Obtain the X11 display.
+ Display *display = XOpenDisplay (NULL);
+ if (display == NULL)
+ {
+ std::cerr << "XOpenDisplay failed\n";
+ return;
+ }
+
+ // Get the root window for the current display.
+ Window winRoot = 0;// = XRootWindow (display, 1);
+
+ // Find the window which has the current keyboard focus.
+ Window winFocus = 0;
+ int revert = RevertToParent;
+
+ XGetInputFocus (display, &winFocus, &revert);
+
+ // Send a fake key press event to the window.
+ XSelectInput (display, winFocus, FocusChangeMask|KeyPressMask|KeyReleaseMask);
+ XMapWindow (display, winFocus);
+
+ unsigned int modifier = scim_x11_keymask_scim_to_x11 (display, key.mask);
+ XKeyEvent event;
+ if (key.is_key_press ())
+ {
+ event = createKeyEvent (display, winFocus, winRoot, true, key.code, modifier);
+ XSendEvent (event.display, event.window, True, KeyPressMask, (XEvent *)&event);
+ }
+ else
+ {
+ event = createKeyEvent (display, winFocus, winRoot, false, key.code, modifier);
+ XSendEvent (event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
+ }
+
+ XCloseDisplay (display);
+}
+
+static void
+attach_instance (const IMEngineInstancePointer &si)
+{
+ si->signal_connect_show_preedit_string (
+ slot (slot_show_preedit_string));
+ si->signal_connect_show_aux_string (
+ slot (slot_show_aux_string));
+ si->signal_connect_show_lookup_table (
+ slot (slot_show_lookup_table));
+
+ si->signal_connect_hide_preedit_string (
+ slot (slot_hide_preedit_string));
+ si->signal_connect_hide_aux_string (
+ slot (slot_hide_aux_string));
+ si->signal_connect_hide_lookup_table (
+ slot (slot_hide_lookup_table));
+
+ si->signal_connect_update_preedit_caret (
+ slot (slot_update_preedit_caret));
+ si->signal_connect_update_preedit_string (
+ slot (slot_update_preedit_string));
+ si->signal_connect_update_aux_string (
+ slot (slot_update_aux_string));
+ si->signal_connect_update_lookup_table (
+ slot (slot_update_lookup_table));
+
+ si->signal_connect_commit_string (
+ slot (slot_commit_string));
+
+ si->signal_connect_forward_key_event (
+ slot (slot_forward_key_event));
+
+ si->signal_connect_register_properties (
+ slot (slot_register_properties));
+
+ si->signal_connect_update_property (
+ slot (slot_update_property));
+
+ si->signal_connect_beep (
+ slot (slot_beep));
+
+ si->signal_connect_start_helper (
+ slot (slot_start_helper));
+
+ si->signal_connect_stop_helper (
+ slot (slot_stop_helper));
+
+ si->signal_connect_send_helper_event (
+ slot (slot_send_helper_event));
+
+ si->signal_connect_get_surrounding_text (
+ slot (slot_get_surrounding_text));
+
+ si->signal_connect_delete_surrounding_text (
+ slot (slot_delete_surrounding_text));
+}
+
+// Implementation of slot functions
+static void
+slot_show_preedit_string (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ {
+ if (ic->impl->use_preedit)
+ {
+ if (!ic->impl->preedit_started)
+ {
+ ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
+ ic->impl->preedit_started = true;
+ }
+ }
+ else
+ _panel_client.show_preedit_string (ic->id);
+ }
+}
+
+static void
+slot_show_aux_string (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.show_aux_string (ic->id);
+}
+
+static void
+slot_show_lookup_table (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.show_lookup_table (ic->id);
+}
+
+static void
+slot_hide_preedit_string (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ {
+ bool emit = false;
+ if (ic->impl->preedit_string.length ())
+ {
+ ic->impl->preedit_string = WideString ();
+ ic->impl->preedit_caret = 0;
+ ic->impl->preedit_attrlist.clear ();
+ emit = true;
+ }
+ if (ic->impl->use_preedit)
+ {
+ if (emit)
+ ecore_imf_context_preedit_changed_event_add (ic->ctx);
+ if (ic->impl->preedit_started)
+ {
+ ecore_imf_context_preedit_end_event_add (ic->ctx);
+ ic->impl->preedit_started = false;
+ }
+ }
+ else
+ _panel_client.hide_preedit_string (ic->id);
+ }
+}
+
+static void
+slot_hide_aux_string (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.hide_aux_string (ic->id);
+}
+
+static void
+slot_hide_lookup_table (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.hide_lookup_table (ic->id);
+}
+
+static void
+slot_update_preedit_caret (IMEngineInstanceBase *si, int caret)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret)
+ {
+ ic->impl->preedit_caret = caret;
+ if (ic->impl->use_preedit)
+ {
+ if (!ic->impl->preedit_started)
+ {
+ ecore_imf_context_preedit_start_event_add (ic->ctx);
+ ic->impl->preedit_started = true;
+ }
+ ecore_imf_context_preedit_changed_event_add (ic->ctx);
+ }
+ else
+ _panel_client.update_preedit_caret (ic->id, caret);
+ }
+}
+
+static void
+slot_update_preedit_string (IMEngineInstanceBase *si,
+ const WideString & str,
+ const AttributeList & attrs)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length ()))
+ {
+ ic->impl->preedit_string = str;
+ ic->impl->preedit_attrlist = attrs;
+ if (ic->impl->use_preedit)
+ {
+ if (!ic->impl->preedit_started)
+ {
+ ecore_imf_context_preedit_start_event_add (_focused_ic->ctx);
+ ic->impl->preedit_started = true;
+ }
+ ic->impl->preedit_caret = str.length ();
+ ic->impl->preedit_updating = true;
+ ecore_imf_context_preedit_changed_event_add (ic->ctx);
+ ic->impl->preedit_updating = false;
+ }
+ else
+ {
+ _panel_client.update_preedit_string (ic->id, str, attrs);
+ }
+ }
+}
+
+static void
+slot_update_aux_string (IMEngineInstanceBase *si,
+ const WideString & str,
+ const AttributeList & attrs)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_aux_string (ic->id, str, attrs);
+}
+
+static void
+slot_commit_string (IMEngineInstanceBase *si,
+ const WideString & str)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->ctx)
+ ecore_imf_context_commit_event_add (ic->ctx, utf8_wcstombs (str).c_str ());
+}
+
+static void
+slot_forward_key_event (IMEngineInstanceBase *si,
+ const KeyEvent & key)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && _focused_ic == ic)
+ {
+ if (!_fallback_instance->process_key_event (key))
+ _x_send_key_event(key);
+ }
+}
+
+static void
+slot_update_lookup_table (IMEngineInstanceBase *si,
+ const LookupTable & table)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_lookup_table (ic->id, table);
+}
+
+static void
+slot_register_properties (IMEngineInstanceBase *si,
+ const PropertyList & properties)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.register_properties (ic->id, properties);
+}
+
+static void
+slot_update_property (IMEngineInstanceBase *si,
+ const Property & property)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ _panel_client.update_property (ic->id, property);
+}
+
+static void
+slot_beep (IMEngineInstanceBase *si)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ ;//gdk_beep ();
+}
+
+static void
+slot_start_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid)
+{
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
+ << (ic ? ic->id : -1) << " ic=" << ic
+ << " ic-uuid=" << ((ic ) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.start_helper (ic->id, helper_uuid);
+}
+
+static void
+slot_stop_helper (IMEngineInstanceBase *si,
+ const String &helper_uuid)
+{
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context=" << (ic ? ic->id : -1) << " ic=" << ic << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.stop_helper (ic->id, helper_uuid);
+}
+
+static void
+slot_send_helper_event (IMEngineInstanceBase *si,
+ const String &helper_uuid,
+ const Transaction &trans)
+{
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " helper= " << helper_uuid << " context="
+ << (ic ? ic->id : -1) << " ic=" << ic
+ << " ic-uuid=" << ((ic) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
+
+ if (ic && ic->impl)
+ _panel_client.send_helper_event (ic->id, helper_uuid, trans);
+}
+
+static bool
+slot_get_surrounding_text (IMEngineInstanceBase *si,
+ WideString &text,
+ int &cursor,
+ int maxlen_before,
+ int maxlen_after)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ {
+ char *surrounding = NULL;
+ int cursor_index;
+ if (ecore_imf_context_surrounding_get (_focused_ic->ctx, &surrounding, &cursor_index))
+ {
+ SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
+ SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
+ WideString before (utf8_mbstowcs (String (surrounding, surrounding + cursor_index)));
+ WideString after (utf8_mbstowcs (String (surrounding + cursor_index)));
+ if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length ())
+ before = WideString (before.begin () + (before.length () - maxlen_before), before.end ());
+ else if (maxlen_before == 0) before = WideString ();
+ if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length ())
+ after = WideString (after.begin (), after.begin () + maxlen_after);
+ else if (maxlen_after == 0) after = WideString ();
+ text = before + after;
+ cursor = before.length ();
+ return true;
+ }
+ }
+ return false;
+}
+
+static bool
+slot_delete_surrounding_text (IMEngineInstanceBase *si,
+ int offset,
+ int len)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *> (si->get_frontend_data ());
+
+ if (ic && ic->impl && _focused_ic == ic)
+ {
+ ecore_imf_context_delete_surrounding_event_add (_focused_ic->ctx, offset, len);
+ return true;
+ }
+ return false;
+}
+
+static void
+reload_config_callback (const ConfigPointer &config)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ _frontend_hotkey_matcher.load_hotkeys (config);
+ _imengine_hotkey_matcher.load_hotkeys (config);
+
+ KeyEvent key;
+
+ scim_string_to_key (key,
+ config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
+ String ("Shift+Control+Alt+Lock")));
+
+ _valid_key_mask = (key.mask > 0)?(key.mask):0xFFFF;
+ _valid_key_mask |= SCIM_KEY_ReleaseMask;
+ // Special treatment for two backslash keys on jp106 keyboard.
+ _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
+
+ _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
+ _shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
+
+ // Get keyboard layout setting
+ // Flush the global config first, in order to load the new configs from disk.
+ scim_global_config_flush ();
+
+ _keyboard_layout = scim_get_default_keyboard_layout ();
+}
+
+static void
+fallback_commit_string_cb (IMEngineInstanceBase *si,
+ const WideString &str)
+{
+ SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
+
+ if (_focused_ic && _focused_ic->impl)
+ ecore_imf_context_commit_event_add (_focused_ic->ctx, utf8_wcstombs (str).c_str ());
+}
+