2012-01-13 15:51:31 -08:00
|
|
|
#ifdef HAVE_CONFIG_H
|
|
|
|
# include <config.h>
|
|
|
|
#endif
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
#include <Eina.h>
|
|
|
|
#include <Ecore.h>
|
|
|
|
#include <Ecore_Input.h>
|
|
|
|
#include <Ecore_IMF.h>
|
|
|
|
#include <Ecore_X.h>
|
|
|
|
#include <X11/Xlib.h>
|
|
|
|
#include <X11/Xlocale.h>
|
|
|
|
#include <X11/Xutil.h>
|
|
|
|
#include <X11/keysym.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <langinfo.h>
|
|
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
#define CLAMP(x, low, high) (x > high) ? high : (x < low) ? low : x
|
|
|
|
#define _(x) x
|
|
|
|
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
static Eina_List *open_ims = NULL;
|
|
|
|
#endif
|
|
|
|
|
2011-12-20 01:49:55 -08:00
|
|
|
#define FEEDBACK_MASK (XIMReverse | XIMUnderline | XIMHighlight)
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
typedef struct _XIM_Im_Info XIM_Im_Info;
|
|
|
|
struct _XIM_Im_Info
|
|
|
|
{
|
|
|
|
Ecore_X_Window win;
|
|
|
|
char *locale;
|
|
|
|
XIM im;
|
|
|
|
Eina_List *ics;
|
|
|
|
Eina_Bool reconnecting;
|
|
|
|
XIMStyles *xim_styles;
|
2011-07-29 03:50:59 -07:00
|
|
|
Eina_Bool supports_string_conversion : 1;
|
|
|
|
Eina_Bool supports_cursor : 1;
|
2011-07-11 19:26:39 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
typedef struct _Ecore_IMF_Context_Data Ecore_IMF_Context_Data;
|
|
|
|
struct _Ecore_IMF_Context_Data
|
|
|
|
{
|
|
|
|
Ecore_X_Window win;
|
|
|
|
long mask;
|
|
|
|
XIC ic; /* Input context for composed characters */
|
|
|
|
char *locale;
|
|
|
|
XIM_Im_Info *im_info;
|
|
|
|
int preedit_length;
|
|
|
|
int preedit_cursor;
|
|
|
|
Eina_Unicode *preedit_chars;
|
|
|
|
Eina_Bool use_preedit;
|
|
|
|
Eina_Bool finalizing;
|
|
|
|
Eina_Bool has_focus;
|
|
|
|
Eina_Bool in_toplevel;
|
2011-12-20 01:49:55 -08:00
|
|
|
XIMFeedback *feedbacks;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
XIMCallback preedit_start_cb;
|
|
|
|
XIMCallback preedit_done_cb;
|
|
|
|
XIMCallback preedit_draw_cb;
|
|
|
|
XIMCallback preedit_caret_cb;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* prototype */
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data_new();
|
|
|
|
void imf_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data);
|
|
|
|
|
|
|
|
#ifdef ENABLE_XIM
|
2012-05-25 17:10:56 -07:00
|
|
|
static void add_feedback_attr(Eina_List **attrs,
|
|
|
|
const char *str,
|
|
|
|
XIMFeedback feedback,
|
|
|
|
int start_pos,
|
|
|
|
int end_pos);
|
2012-01-13 16:04:16 -08:00
|
|
|
|
|
|
|
static void reinitialize_ic(Ecore_IMF_Context *ctx);
|
|
|
|
static void reinitialize_all_ics(XIM_Im_Info *info);
|
|
|
|
static void set_ic_client_window(Ecore_IMF_Context *ctx,
|
|
|
|
Ecore_X_Window window);
|
|
|
|
static int preedit_start_callback(XIC xic,
|
|
|
|
XPointer client_data,
|
|
|
|
XPointer call_data);
|
|
|
|
static void preedit_done_callback(XIC xic,
|
|
|
|
XPointer client_data,
|
|
|
|
XPointer call_data);
|
|
|
|
static int xim_text_to_utf8(Ecore_IMF_Context *ctx,
|
|
|
|
XIMText *xim_text,
|
|
|
|
char **text);
|
|
|
|
static void preedit_draw_callback(XIC xic,
|
|
|
|
XPointer client_data,
|
|
|
|
XIMPreeditDrawCallbackStruct *call_data);
|
|
|
|
static void preedit_caret_callback(XIC xic,
|
|
|
|
XPointer client_data,
|
|
|
|
XIMPreeditCaretCallbackStruct *call_data);
|
2011-07-11 19:26:39 -07:00
|
|
|
static XVaNestedList preedit_callback_set(Ecore_IMF_Context *ctx);
|
|
|
|
static XIC get_ic(Ecore_IMF_Context *ctx);
|
|
|
|
static XIM_Im_Info *get_im(Ecore_X_Window window,
|
2012-01-13 16:04:16 -08:00
|
|
|
char *locale);
|
2011-07-11 19:26:39 -07:00
|
|
|
static void xim_info_try_im(XIM_Im_Info *info);
|
|
|
|
static void xim_info_display_closed(Ecore_X_Display *display,
|
2012-01-13 16:04:16 -08:00
|
|
|
int is_error,
|
|
|
|
XIM_Im_Info *info);
|
|
|
|
static void xim_instantiate_callback(Display *display,
|
|
|
|
XPointer client_data,
|
|
|
|
XPointer call_data);
|
|
|
|
static void setup_im(XIM_Im_Info *info);
|
|
|
|
static void xim_destroy_callback(XIM xim,
|
|
|
|
XPointer client_data,
|
|
|
|
XPointer call_data);
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
|
2012-01-13 15:50:01 -08:00
|
|
|
#ifdef ENABLE_XIM
|
2011-12-20 01:49:55 -08:00
|
|
|
static unsigned int
|
|
|
|
utf8_offset_to_index(const char *str, int offset)
|
|
|
|
{
|
2012-05-26 15:01:53 -07:00
|
|
|
int idx = 0;
|
2011-12-20 01:49:55 -08:00
|
|
|
int i;
|
|
|
|
for (i = 0; i < offset; i++)
|
|
|
|
{
|
2012-05-26 15:01:53 -07:00
|
|
|
eina_unicode_utf8_get_next(str, &idx);
|
2011-12-20 01:49:55 -08:00
|
|
|
}
|
|
|
|
|
2012-05-26 15:01:53 -07:00
|
|
|
return idx;
|
2011-12-20 01:49:55 -08:00
|
|
|
}
|
2012-01-13 16:04:16 -08:00
|
|
|
|
2012-01-13 15:50:01 -08:00
|
|
|
#endif
|
2011-12-20 01:49:55 -08:00
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_add(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data = NULL;
|
|
|
|
|
|
|
|
imf_context_data = imf_context_data_new();
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!imf_context_data) return;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
imf_context_data->use_preedit = EINA_TRUE;
|
|
|
|
imf_context_data->finalizing = EINA_FALSE;
|
|
|
|
imf_context_data->has_focus = EINA_FALSE;
|
|
|
|
imf_context_data->in_toplevel = EINA_FALSE;
|
|
|
|
|
|
|
|
ecore_imf_context_data_set(ctx, imf_context_data);
|
2012-01-13 15:57:25 -08:00
|
|
|
#else
|
|
|
|
(void)ctx;
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_del(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
imf_context_data->finalizing = EINA_TRUE;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->im_info && !imf_context_data->im_info->ics->next)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->im_info->reconnecting == EINA_TRUE)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
Ecore_X_Display *dsp;
|
|
|
|
dsp = ecore_x_display_get();
|
2012-01-13 16:04:16 -08:00
|
|
|
XUnregisterIMInstantiateCallback(dsp,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
xim_instantiate_callback,
|
|
|
|
(XPointer)imf_context_data->im_info);
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
2012-01-13 16:04:16 -08:00
|
|
|
else if (imf_context_data->im_info->im)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XIMCallback im_destroy_callback;
|
|
|
|
im_destroy_callback.client_data = NULL;
|
|
|
|
im_destroy_callback.callback = NULL;
|
2012-01-13 16:04:16 -08:00
|
|
|
XSetIMValues(imf_context_data->im_info->im,
|
|
|
|
XNDestroyCallback, &im_destroy_callback,
|
|
|
|
NULL);
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
set_ic_client_window(ctx, 0);
|
|
|
|
|
|
|
|
imf_context_data_destroy(imf_context_data);
|
2012-01-13 15:57:25 -08:00
|
|
|
#else
|
|
|
|
(void)ctx;
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_client_window_set(Ecore_IMF_Context *ctx,
|
2012-01-13 16:04:16 -08:00
|
|
|
void *window)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
set_ic_client_window(ctx, (Ecore_X_Window)((Ecore_Window)window));
|
2012-01-13 15:57:25 -08:00
|
|
|
#else
|
|
|
|
(void)ctx;
|
|
|
|
(void)window;
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_preedit_string_get(Ecore_IMF_Context *ctx,
|
2012-01-13 16:04:16 -08:00
|
|
|
char **str,
|
|
|
|
int *cursor_pos)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
char *utf8;
|
|
|
|
int len;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
|
|
|
|
2011-07-26 04:47:40 -07:00
|
|
|
if (imf_context_data->preedit_chars)
|
|
|
|
{
|
|
|
|
utf8 = eina_unicode_unicode_to_utf8(imf_context_data->preedit_chars,
|
|
|
|
&len);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (str)
|
|
|
|
*str = utf8;
|
2011-07-26 04:47:40 -07:00
|
|
|
else
|
2012-01-13 16:04:16 -08:00
|
|
|
free(utf8);
|
2011-07-26 04:47:40 -07:00
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
else
|
2011-07-26 04:47:40 -07:00
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
if (str)
|
|
|
|
*str = NULL;
|
|
|
|
if (cursor_pos)
|
|
|
|
*cursor_pos = 0;
|
2011-07-26 04:47:40 -07:00
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (cursor_pos)
|
2011-07-11 19:26:39 -07:00
|
|
|
*cursor_pos = imf_context_data->preedit_cursor;
|
|
|
|
#else
|
2012-01-13 15:57:25 -08:00
|
|
|
(void)ctx;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (str)
|
2011-07-11 19:26:39 -07:00
|
|
|
*str = NULL;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (cursor_pos)
|
2011-07-11 19:26:39 -07:00
|
|
|
*cursor_pos = 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-12-20 01:49:55 -08:00
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
|
2012-01-13 16:04:16 -08:00
|
|
|
char **str,
|
|
|
|
Eina_List **attrs,
|
|
|
|
int *cursor_pos)
|
2011-12-20 01:49:55 -08:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
|
2012-01-13 15:50:01 -08:00
|
|
|
#ifdef ENABLE_XIM
|
2011-12-20 01:49:55 -08:00
|
|
|
Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
|
|
|
|
|
|
|
|
_ecore_imf_context_xim_preedit_string_get(ctx, str, cursor_pos);
|
|
|
|
|
|
|
|
if (!attrs) return;
|
|
|
|
if (!imf_context_data || !imf_context_data->feedbacks) return;
|
|
|
|
|
|
|
|
int i = 0;
|
|
|
|
XIMFeedback last_feedback = 0;
|
|
|
|
int start = -1;
|
|
|
|
|
|
|
|
for (i = 0; i < imf_context_data->preedit_length; i++)
|
|
|
|
{
|
|
|
|
XIMFeedback new_feedback = imf_context_data->feedbacks[i] & FEEDBACK_MASK;
|
|
|
|
|
|
|
|
if (new_feedback != last_feedback)
|
|
|
|
{
|
|
|
|
if (start >= 0)
|
2012-01-13 16:04:16 -08:00
|
|
|
add_feedback_attr(attrs, *str, last_feedback, start, i);
|
2011-12-20 01:49:55 -08:00
|
|
|
|
|
|
|
last_feedback = new_feedback;
|
|
|
|
start = i;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (start >= 0)
|
2012-01-13 16:04:16 -08:00
|
|
|
add_feedback_attr(attrs, *str, last_feedback, start, i);
|
2012-01-13 15:50:01 -08:00
|
|
|
#else
|
2012-01-13 15:57:25 -08:00
|
|
|
(void)ctx;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (str)
|
2012-01-13 15:50:01 -08:00
|
|
|
*str = NULL;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (attrs)
|
2012-01-13 15:50:01 -08:00
|
|
|
*attrs = NULL;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (cursor_pos)
|
2012-01-13 15:50:01 -08:00
|
|
|
*cursor_pos = 0;
|
|
|
|
#endif
|
2011-12-20 01:49:55 -08:00
|
|
|
}
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_focus_in(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
XIC ic;
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
ic = imf_context_data->ic;
|
|
|
|
imf_context_data->has_focus = EINA_TRUE;
|
2012-02-07 02:10:23 -08:00
|
|
|
|
|
|
|
if (ecore_imf_context_input_panel_enabled_get(ctx))
|
|
|
|
ecore_imf_context_input_panel_show(ctx);
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (ic)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
char *str;
|
|
|
|
|
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
|
|
if ((str = Xutf8ResetIC(ic)))
|
|
|
|
#else
|
|
|
|
if ((str = XmbResetIC(ic)))
|
|
|
|
#endif
|
|
|
|
XFree(str);
|
|
|
|
|
|
|
|
XSetICFocus(ic);
|
|
|
|
}
|
2012-01-13 15:57:25 -08:00
|
|
|
#else
|
|
|
|
(void)ctx;
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-07-11 23:11:04 -07:00
|
|
|
_ecore_imf_context_xim_focus_out(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
EINA_LOG_DBG("%s in", __FUNCTION__);
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
XIC ic;
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->has_focus == EINA_TRUE)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
imf_context_data->has_focus = EINA_FALSE;
|
|
|
|
ic = imf_context_data->ic;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (ic)
|
2011-07-11 19:26:39 -07:00
|
|
|
XUnsetICFocus(ic);
|
2012-02-07 02:10:23 -08:00
|
|
|
|
|
|
|
if (ecore_imf_context_input_panel_enabled_get(ctx))
|
|
|
|
ecore_imf_context_input_panel_hide(ctx);
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
2012-01-13 15:57:25 -08:00
|
|
|
#else
|
|
|
|
(void)ctx;
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-07-11 23:11:04 -07:00
|
|
|
_ecore_imf_context_xim_reset(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
EINA_LOG_DBG("%s in", __FUNCTION__);
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
XIC ic;
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
char *result;
|
|
|
|
|
|
|
|
/* restore conversion state after resetting ic later */
|
|
|
|
XIMPreeditState preedit_state = XIMPreeditUnKnown;
|
|
|
|
XVaNestedList preedit_attr;
|
|
|
|
Eina_Bool have_preedit_state = EINA_FALSE;
|
|
|
|
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
ic = imf_context_data->ic;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!ic)
|
2011-07-11 19:26:39 -07:00
|
|
|
return;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->preedit_length == 0)
|
2011-07-11 19:26:39 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
preedit_attr = XVaCreateNestedList(0,
|
|
|
|
XNPreeditState, &preedit_state,
|
|
|
|
NULL);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!XGetICValues(ic,
|
|
|
|
XNPreeditAttributes, preedit_attr,
|
|
|
|
NULL))
|
2011-07-11 19:26:39 -07:00
|
|
|
have_preedit_state = EINA_TRUE;
|
|
|
|
|
|
|
|
XFree(preedit_attr);
|
|
|
|
|
|
|
|
result = XmbResetIC(ic);
|
|
|
|
|
|
|
|
preedit_attr = XVaCreateNestedList(0,
|
|
|
|
XNPreeditState, preedit_state,
|
|
|
|
NULL);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (have_preedit_state)
|
2011-07-11 19:26:39 -07:00
|
|
|
XSetICValues(ic,
|
|
|
|
XNPreeditAttributes, preedit_attr,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
XFree(preedit_attr);
|
|
|
|
|
2011-12-20 01:49:55 -08:00
|
|
|
if (imf_context_data->feedbacks)
|
|
|
|
{
|
|
|
|
free(imf_context_data->feedbacks);
|
|
|
|
imf_context_data->feedbacks = NULL;
|
|
|
|
}
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->preedit_length)
|
2011-07-26 04:57:51 -07:00
|
|
|
{
|
|
|
|
imf_context_data->preedit_length = 0;
|
|
|
|
free(imf_context_data->preedit_chars);
|
|
|
|
imf_context_data->preedit_chars = NULL;
|
2011-12-20 01:49:55 -08:00
|
|
|
|
2011-07-26 04:57:51 -07:00
|
|
|
ecore_imf_context_preedit_changed_event_add(ctx);
|
2012-01-17 20:38:04 -08:00
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
2011-07-26 04:57:51 -07:00
|
|
|
}
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (result)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
char *result_utf8 = strdup(result);
|
|
|
|
if (result_utf8)
|
|
|
|
{
|
|
|
|
ecore_imf_context_commit_event_add(ctx, result_utf8);
|
2012-01-17 20:38:04 -08:00
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, result_utf8);
|
2012-01-13 16:04:16 -08:00
|
|
|
free(result_utf8);
|
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
XFree(result);
|
2012-01-13 15:57:25 -08:00
|
|
|
#else
|
|
|
|
(void)ctx;
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_use_preedit_set(Ecore_IMF_Context *ctx,
|
2012-01-13 16:04:16 -08:00
|
|
|
Eina_Bool use_preedit)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
use_preedit = use_preedit != EINA_FALSE;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->use_preedit != use_preedit)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
imf_context_data->use_preedit = use_preedit;
|
|
|
|
reinitialize_ic(ctx);
|
|
|
|
}
|
2012-01-13 15:57:25 -08:00
|
|
|
#else
|
|
|
|
(void)ctx;
|
|
|
|
(void)use_preedit;
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2012-01-13 15:50:01 -08:00
|
|
|
#ifdef ENABLE_XIM
|
2011-12-20 01:49:55 -08:00
|
|
|
static void
|
2012-01-13 16:04:16 -08:00
|
|
|
add_feedback_attr(Eina_List **attrs,
|
|
|
|
const char *str,
|
|
|
|
XIMFeedback feedback,
|
|
|
|
int start_pos,
|
|
|
|
int end_pos)
|
2011-12-20 01:49:55 -08:00
|
|
|
{
|
|
|
|
Ecore_IMF_Preedit_Attr *attr = NULL;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
unsigned int start_index = utf8_offset_to_index(str, start_pos);
|
|
|
|
unsigned int end_index = utf8_offset_to_index(str, end_pos);
|
2011-12-20 01:49:55 -08:00
|
|
|
|
|
|
|
if (feedback & FEEDBACK_MASK)
|
2012-01-13 16:04:16 -08:00
|
|
|
{
|
2011-12-20 01:49:55 -08:00
|
|
|
attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
|
|
|
|
attr->start_index = start_index;
|
|
|
|
attr->end_index = end_index;
|
|
|
|
*attrs = eina_list_append(*attrs, (void *)attr);
|
2012-01-13 16:04:16 -08:00
|
|
|
}
|
2011-12-20 01:49:55 -08:00
|
|
|
|
|
|
|
if (feedback & XIMUnderline)
|
|
|
|
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
|
|
|
|
|
|
|
|
if (feedback & XIMReverse)
|
|
|
|
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
|
|
|
|
|
|
|
|
if (feedback & XIMHighlight)
|
|
|
|
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
|
|
|
|
}
|
2012-01-13 16:04:16 -08:00
|
|
|
|
2012-01-13 15:50:01 -08:00
|
|
|
#endif
|
2011-12-20 01:49:55 -08:00
|
|
|
|
2011-07-29 03:50:59 -07:00
|
|
|
static void
|
2012-01-13 16:04:16 -08:00
|
|
|
_ecore_imf_context_xim_cursor_location_set(Ecore_IMF_Context *ctx,
|
|
|
|
int x, int y, int w, int h)
|
2011-07-29 03:50:59 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("%s in", __FUNCTION__);
|
|
|
|
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
XIC ic;
|
|
|
|
XVaNestedList preedit_attr;
|
2012-01-13 16:04:16 -08:00
|
|
|
XPoint spot;
|
2011-07-29 03:50:59 -07:00
|
|
|
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
2011-07-29 03:50:59 -07:00
|
|
|
ic = imf_context_data->ic;
|
|
|
|
if (!ic)
|
|
|
|
return;
|
|
|
|
|
|
|
|
spot.x = x;
|
|
|
|
spot.y = y + h;
|
2012-01-13 16:04:16 -08:00
|
|
|
|
|
|
|
preedit_attr = XVaCreateNestedList(0,
|
|
|
|
XNSpotLocation, &spot,
|
|
|
|
NULL);
|
|
|
|
XSetICValues(ic,
|
|
|
|
XNPreeditAttributes, preedit_attr,
|
|
|
|
NULL);
|
2011-07-29 03:50:59 -07:00
|
|
|
|
|
|
|
XFree(preedit_attr);
|
2012-01-13 15:57:25 -08:00
|
|
|
#else
|
|
|
|
(void)ctx;
|
|
|
|
(void)x;
|
|
|
|
(void)y;
|
|
|
|
(void)h;
|
2011-07-29 03:50:59 -07:00
|
|
|
#endif
|
2011-08-23 05:04:52 -07:00
|
|
|
(void)(w); // yes w is unused, but only a bi-product of the algorithm
|
2011-07-29 03:50:59 -07:00
|
|
|
}
|
|
|
|
|
2012-02-07 02:10:23 -08:00
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_input_panel_show(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
|
|
|
EINA_LOG_DBG("%s in", __FUNCTION__);
|
|
|
|
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
2012-02-07 02:10:23 -08:00
|
|
|
|
|
|
|
ecore_x_e_virtual_keyboard_state_set
|
|
|
|
(imf_context_data->win, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
|
|
|
|
#else
|
|
|
|
(void)ctx;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
_ecore_imf_context_xim_input_panel_hide(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
|
|
|
EINA_LOG_DBG("%s in", __FUNCTION__);
|
|
|
|
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
2012-02-07 02:10:23 -08:00
|
|
|
|
|
|
|
ecore_x_e_virtual_keyboard_state_set
|
|
|
|
(imf_context_data->win, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
|
|
|
|
#else
|
|
|
|
(void)ctx;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
static unsigned int
|
|
|
|
_ecore_x_event_reverse_modifiers(unsigned int state)
|
|
|
|
{
|
|
|
|
unsigned int modifiers = 0;
|
|
|
|
|
|
|
|
/**< "Control" is pressed */
|
2012-01-13 16:04:16 -08:00
|
|
|
if (state & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
|
2011-07-11 19:26:39 -07:00
|
|
|
modifiers |= ControlMask;
|
|
|
|
|
|
|
|
/**< "Alt" is pressed */
|
2012-01-13 16:04:16 -08:00
|
|
|
if (state & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
|
2011-07-11 19:26:39 -07:00
|
|
|
modifiers |= Mod1Mask;
|
|
|
|
|
|
|
|
/**< "Shift" is pressed */
|
2012-01-13 16:04:16 -08:00
|
|
|
if (state & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
|
2011-07-11 19:26:39 -07:00
|
|
|
modifiers |= ShiftMask;
|
|
|
|
|
|
|
|
/**< "Win" (between "Ctrl" and "A */
|
2012-01-13 16:04:16 -08:00
|
|
|
if (state & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
|
2011-07-11 19:26:39 -07:00
|
|
|
modifiers |= Mod5Mask;
|
|
|
|
|
|
|
|
return modifiers;
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned int
|
2011-07-11 23:11:04 -07:00
|
|
|
_ecore_x_event_reverse_locks(unsigned int state)
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
unsigned int locks = 0;
|
|
|
|
|
|
|
|
/**< "Num" lock is active */
|
2012-01-13 16:04:16 -08:00
|
|
|
if (state & ECORE_IMF_KEYBOARD_LOCK_NUM)
|
2011-07-11 19:26:39 -07:00
|
|
|
locks |= Mod3Mask;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (state & ECORE_IMF_KEYBOARD_LOCK_CAPS)
|
2011-07-11 19:26:39 -07:00
|
|
|
locks |= LockMask;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
#if 0 /* FIXME: add mask. */
|
|
|
|
if (state & ECORE_IMF_KEYBOARD_LOCK_SCROLL)
|
2011-07-25 00:16:54 -07:00
|
|
|
;
|
|
|
|
#endif
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
return locks;
|
|
|
|
}
|
|
|
|
|
|
|
|
static KeyCode
|
|
|
|
_keycode_get(Ecore_X_Display *dsp,
|
2012-01-13 16:04:16 -08:00
|
|
|
const char *keyname)
|
2011-07-11 23:11:04 -07:00
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
KeyCode keycode;
|
|
|
|
|
|
|
|
// EINA_LOG_DBG("keyname:%s keysym:%lu", keyname, XStringToKeysym(keyname));
|
2012-01-13 16:04:16 -08:00
|
|
|
if (strcmp(keyname, "Keycode-0") == 0)
|
2012-05-25 17:10:56 -07:00
|
|
|
keycode = 0;
|
|
|
|
else
|
|
|
|
keycode = XKeysymToKeycode(dsp, XStringToKeysym(keyname));
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
return keycode;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static Eina_Bool
|
2012-01-13 16:04:16 -08:00
|
|
|
_ecore_imf_context_xim_filter_event(Ecore_IMF_Context *ctx,
|
2011-07-11 19:26:39 -07:00
|
|
|
Ecore_IMF_Event_Type type,
|
2012-01-13 16:04:16 -08:00
|
|
|
Ecore_IMF_Event *event)
|
2011-07-11 23:11:04 -07:00
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
EINA_LOG_DBG("%s in", __FUNCTION__);
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
XIC ic;
|
|
|
|
|
|
|
|
Ecore_X_Display *dsp;
|
|
|
|
Ecore_X_Window win;
|
|
|
|
|
|
|
|
int val;
|
|
|
|
char compose_buffer[256];
|
|
|
|
KeySym sym;
|
|
|
|
char *compose = NULL;
|
|
|
|
char *tmp = NULL;
|
|
|
|
Eina_Bool result = EINA_FALSE;
|
|
|
|
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return EINA_FALSE;
|
2011-07-11 19:26:39 -07:00
|
|
|
ic = imf_context_data->ic;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!ic)
|
2012-06-19 08:18:34 -07:00
|
|
|
ic = get_ic(ctx);
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (type == ECORE_IMF_EVENT_KEY_DOWN)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XKeyPressedEvent xev;
|
|
|
|
Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
|
|
|
|
EINA_LOG_DBG("ECORE_IMF_EVENT_KEY_DOWN");
|
|
|
|
|
|
|
|
dsp = ecore_x_display_get();
|
|
|
|
win = imf_context_data->win;
|
|
|
|
|
|
|
|
xev.type = KeyPress;
|
|
|
|
xev.serial = 0; /* hope it doesn't matter */
|
|
|
|
xev.send_event = 0;
|
|
|
|
xev.display = dsp;
|
|
|
|
xev.window = win;
|
|
|
|
xev.root = ecore_x_window_root_get(win);
|
|
|
|
xev.subwindow = win;
|
|
|
|
xev.time = ev->timestamp;
|
|
|
|
xev.x = xev.x_root = 0;
|
|
|
|
xev.y = xev.y_root = 0;
|
|
|
|
xev.state = 0;
|
|
|
|
xev.state |= _ecore_x_event_reverse_modifiers(ev->modifiers);
|
|
|
|
xev.state |= _ecore_x_event_reverse_locks(ev->locks);
|
|
|
|
xev.keycode = _keycode_get(dsp, ev->keyname);
|
|
|
|
xev.same_screen = True;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (ic)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
Status mbstatus;
|
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
|
|
val = Xutf8LookupString(ic,
|
|
|
|
&xev,
|
|
|
|
compose_buffer,
|
|
|
|
sizeof(compose_buffer) - 1,
|
|
|
|
&sym,
|
|
|
|
&mbstatus);
|
|
|
|
#else /* ifdef X_HAVE_UTF8_STRING */
|
|
|
|
val = XmbLookupString(ic,
|
|
|
|
&xev,
|
|
|
|
compose_buffer,
|
|
|
|
sizeof(compose_buffer) - 1,
|
|
|
|
&sym,
|
|
|
|
&mbstatus);
|
|
|
|
#endif /* ifdef X_HAVE_UTF8_STRING */
|
|
|
|
if (mbstatus == XBufferOverflow)
|
|
|
|
{
|
|
|
|
tmp = malloc(sizeof (char) * (val + 1));
|
|
|
|
if (!tmp)
|
2012-05-25 17:10:56 -07:00
|
|
|
return EINA_FALSE;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
compose = tmp;
|
|
|
|
|
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
|
|
val = Xutf8LookupString(ic,
|
|
|
|
(XKeyEvent *)&xev,
|
|
|
|
tmp,
|
|
|
|
val,
|
|
|
|
&sym,
|
|
|
|
&mbstatus);
|
|
|
|
#else /* ifdef X_HAVE_UTF8_STRING */
|
|
|
|
val = XmbLookupString(ic,
|
|
|
|
(XKeyEvent *)&xev,
|
|
|
|
tmp,
|
|
|
|
val,
|
|
|
|
&sym,
|
|
|
|
&mbstatus);
|
|
|
|
#endif /* ifdef X_HAVE_UTF8_STRING */
|
|
|
|
if (val > 0)
|
|
|
|
{
|
|
|
|
tmp[val] = '\0';
|
|
|
|
#ifndef X_HAVE_UTF8_STRING
|
|
|
|
compose = eina_str_convert(nl_langinfo(CODESET),
|
|
|
|
"UTF-8", tmp);
|
|
|
|
free(tmp);
|
|
|
|
tmp = compose;
|
|
|
|
#endif /* ifndef X_HAVE_UTF8_STRING */
|
|
|
|
}
|
|
|
|
else
|
|
|
|
compose = NULL;
|
|
|
|
}
|
|
|
|
else if (val > 0)
|
|
|
|
{
|
|
|
|
compose_buffer[val] = '\0';
|
|
|
|
#ifdef X_HAVE_UTF8_STRING
|
|
|
|
compose = strdup(compose_buffer);
|
|
|
|
#else /* ifdef X_HAVE_UTF8_STRING */
|
|
|
|
compose = eina_str_convert(nl_langinfo(CODESET), "UTF-8",
|
|
|
|
compose_buffer);
|
|
|
|
#endif /* ifdef X_HAVE_UTF8_STRING */
|
|
|
|
}
|
|
|
|
}
|
2012-05-25 17:10:56 -07:00
|
|
|
else
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
XComposeStatus status;
|
|
|
|
val = XLookupString(&xev,
|
|
|
|
compose_buffer,
|
|
|
|
sizeof(compose_buffer),
|
|
|
|
&sym,
|
|
|
|
&status);
|
|
|
|
if (val > 0)
|
|
|
|
{
|
|
|
|
compose_buffer[val] = '\0';
|
|
|
|
compose = eina_str_convert(nl_langinfo(CODESET),
|
|
|
|
"UTF-8", compose_buffer);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (compose)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
Eina_Unicode *unicode;
|
|
|
|
int len;
|
|
|
|
unicode = eina_unicode_utf8_to_unicode(compose, &len);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!unicode) abort();
|
|
|
|
if (unicode[0] >= 0x20 && unicode[0] != 0x7f)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
ecore_imf_context_commit_event_add(ctx, compose);
|
2012-01-17 20:38:04 -08:00
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_COMMIT, compose);
|
2011-07-11 19:26:39 -07:00
|
|
|
result = EINA_TRUE;
|
|
|
|
}
|
|
|
|
free(compose);
|
|
|
|
free(unicode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
#else
|
2012-01-13 15:57:25 -08:00
|
|
|
(void)ctx;
|
|
|
|
(void)type;
|
|
|
|
(void)event;
|
2011-07-11 19:26:39 -07:00
|
|
|
return EINA_FALSE;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
static const Ecore_IMF_Context_Info xim_info = {
|
|
|
|
.id = "xim",
|
|
|
|
.description = _("X input method"),
|
|
|
|
.default_locales = "ko:ja:th:zh",
|
|
|
|
.canvas_type = "evas",
|
|
|
|
.canvas_required = 1,
|
|
|
|
};
|
|
|
|
|
|
|
|
static Ecore_IMF_Context_Class xim_class = {
|
|
|
|
.add = _ecore_imf_context_xim_add,
|
|
|
|
.del = _ecore_imf_context_xim_del,
|
|
|
|
.client_window_set = _ecore_imf_context_xim_client_window_set,
|
|
|
|
.client_canvas_set = NULL,
|
2012-02-07 02:10:23 -08:00
|
|
|
.show = _ecore_imf_context_xim_input_panel_show,
|
|
|
|
.hide = _ecore_imf_context_xim_input_panel_hide,
|
2011-07-11 19:26:39 -07:00
|
|
|
.preedit_string_get = _ecore_imf_context_xim_preedit_string_get,
|
|
|
|
.focus_in = _ecore_imf_context_xim_focus_in,
|
|
|
|
.focus_out = _ecore_imf_context_xim_focus_out,
|
|
|
|
.reset = _ecore_imf_context_xim_reset,
|
|
|
|
.cursor_position_set = NULL,
|
|
|
|
.use_preedit_set = _ecore_imf_context_xim_use_preedit_set,
|
|
|
|
.input_mode_set = NULL,
|
|
|
|
.filter_event = _ecore_imf_context_xim_filter_event,
|
2011-12-20 01:49:55 -08:00
|
|
|
.preedit_string_with_attributes_get = _ecore_imf_context_xim_preedit_string_with_attributes_get,
|
2011-07-11 19:26:39 -07:00
|
|
|
.prediction_allow_set = NULL,
|
|
|
|
.autocapital_type_set = NULL,
|
|
|
|
.control_panel_show = NULL,
|
|
|
|
.control_panel_hide = NULL,
|
|
|
|
.input_panel_layout_set = NULL,
|
|
|
|
.input_panel_layout_get = NULL,
|
|
|
|
.input_panel_language_set = NULL,
|
|
|
|
.input_panel_language_get = NULL,
|
2011-07-29 03:50:59 -07:00
|
|
|
.cursor_location_set = _ecore_imf_context_xim_cursor_location_set,
|
2012-02-06 01:46:38 -08:00
|
|
|
.input_panel_imdata_set = NULL,
|
|
|
|
.input_panel_imdata_get = NULL,
|
2012-02-14 17:22:28 -08:00
|
|
|
.input_panel_return_key_type_set = NULL,
|
2012-02-28 20:37:33 -08:00
|
|
|
.input_panel_return_key_disabled_set = NULL,
|
|
|
|
.input_panel_caps_lock_mode_set = NULL
|
2011-07-11 19:26:39 -07:00
|
|
|
};
|
|
|
|
|
|
|
|
static Ecore_IMF_Context *
|
2011-07-11 23:11:04 -07:00
|
|
|
xim_imf_module_create(void)
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
EINA_LOG_DBG("%s in", __FUNCTION__);
|
|
|
|
Ecore_IMF_Context *ctx = NULL;
|
|
|
|
|
|
|
|
ctx = ecore_imf_context_new(&xim_class);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!ctx)
|
2011-07-11 19:26:39 -07:00
|
|
|
goto error;
|
|
|
|
|
|
|
|
return ctx;
|
|
|
|
|
|
|
|
error:
|
|
|
|
free(ctx);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static Ecore_IMF_Context *
|
2011-07-11 23:11:04 -07:00
|
|
|
xim_imf_module_exit(void)
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
Eina_Bool
|
2011-07-11 23:11:04 -07:00
|
|
|
ecore_imf_xim_init(void)
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
EINA_LOG_DBG("%s in", __FUNCTION__);
|
|
|
|
eina_init();
|
|
|
|
ecore_x_init(NULL);
|
|
|
|
ecore_imf_module_register(&xim_info,
|
|
|
|
xim_imf_module_create,
|
|
|
|
xim_imf_module_exit);
|
|
|
|
|
|
|
|
return EINA_TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-07-11 23:11:04 -07:00
|
|
|
ecore_imf_xim_shutdown(void)
|
|
|
|
{
|
2011-07-11 23:10:54 -07:00
|
|
|
#ifdef ENABLE_XIM
|
2012-05-25 17:10:56 -07:00
|
|
|
while (open_ims)
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
XIM_Im_Info *info = open_ims->data;
|
|
|
|
Ecore_X_Display *display = ecore_x_display_get();
|
|
|
|
|
|
|
|
xim_info_display_closed(display, EINA_FALSE, info);
|
|
|
|
}
|
2011-07-11 23:10:54 -07:00
|
|
|
#endif
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
ecore_x_shutdown();
|
|
|
|
eina_shutdown();
|
|
|
|
}
|
|
|
|
|
|
|
|
EINA_MODULE_INIT(ecore_imf_xim_init);
|
|
|
|
EINA_MODULE_SHUTDOWN(ecore_imf_xim_shutdown);
|
|
|
|
|
|
|
|
#ifdef ENABLE_XIM
|
|
|
|
/*
|
|
|
|
* internal functions
|
|
|
|
*/
|
|
|
|
Ecore_IMF_Context_Data *
|
|
|
|
imf_context_data_new()
|
|
|
|
{
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data = NULL;
|
|
|
|
char *locale;
|
|
|
|
|
|
|
|
locale = setlocale(LC_CTYPE, "");
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!locale) return NULL;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!XSupportsLocale()) return NULL;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
imf_context_data = calloc(1, sizeof(Ecore_IMF_Context_Data));
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!imf_context_data) return NULL;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
imf_context_data->locale = strdup(locale);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!imf_context_data->locale) goto error;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
return imf_context_data;
|
|
|
|
error:
|
|
|
|
imf_context_data_destroy(imf_context_data);
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2011-07-11 23:11:04 -07:00
|
|
|
imf_context_data_destroy(Ecore_IMF_Context_Data *imf_context_data)
|
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!imf_context_data)
|
2011-07-11 19:26:39 -07:00
|
|
|
return;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->ic)
|
2011-07-11 19:26:39 -07:00
|
|
|
XDestroyIC(imf_context_data->ic);
|
|
|
|
|
2011-07-25 00:16:54 -07:00
|
|
|
free(imf_context_data->preedit_chars);
|
2011-12-20 01:49:55 -08:00
|
|
|
|
|
|
|
if (imf_context_data->feedbacks)
|
|
|
|
{
|
|
|
|
free(imf_context_data->feedbacks);
|
|
|
|
imf_context_data->feedbacks = NULL;
|
|
|
|
}
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
free(imf_context_data->locale);
|
|
|
|
free(imf_context_data);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int
|
2012-01-13 16:04:16 -08:00
|
|
|
preedit_start_callback(XIC xic __UNUSED__,
|
2011-07-11 19:26:39 -07:00
|
|
|
XPointer client_data,
|
2011-07-25 00:16:54 -07:00
|
|
|
XPointer call_data __UNUSED__)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return -1;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->finalizing == EINA_FALSE)
|
2012-01-17 20:38:04 -08:00
|
|
|
{
|
|
|
|
ecore_imf_context_preedit_start_event_add(ctx);
|
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
|
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-01-13 16:04:16 -08:00
|
|
|
preedit_done_callback(XIC xic __UNUSED__,
|
2011-07-11 19:26:39 -07:00
|
|
|
XPointer client_data,
|
2011-07-25 00:16:54 -07:00
|
|
|
XPointer call_data __UNUSED__)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->preedit_length)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
imf_context_data->preedit_length = 0;
|
2011-07-26 04:57:51 -07:00
|
|
|
free(imf_context_data->preedit_chars);
|
|
|
|
imf_context_data->preedit_chars = NULL;
|
2011-07-11 19:26:39 -07:00
|
|
|
ecore_imf_context_preedit_changed_event_add(ctx);
|
2012-01-17 20:38:04 -08:00
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->finalizing == EINA_FALSE)
|
2012-01-17 20:38:04 -08:00
|
|
|
{
|
|
|
|
ecore_imf_context_preedit_end_event_add(ctx);
|
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
|
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
/* FIXME */
|
|
|
|
static int
|
2011-07-25 00:16:54 -07:00
|
|
|
xim_text_to_utf8(Ecore_IMF_Context *ctx __UNUSED__,
|
2012-01-13 16:04:16 -08:00
|
|
|
XIMText *xim_text,
|
|
|
|
char **text)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
int text_length = 0;
|
|
|
|
char *result = NULL;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (xim_text && xim_text->string.multi_byte)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
if (xim_text->encoding_is_wchar)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_WARN("Wide character return from Xlib not currently supported");
|
|
|
|
*text = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* XXX Convert to UTF-8 */
|
|
|
|
result = strdup(xim_text->string.multi_byte);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (result)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
text_length = eina_unicode_utf8_get_len(result);
|
|
|
|
if (text_length != xim_text->length)
|
|
|
|
{
|
|
|
|
EINA_LOG_WARN("Size mismatch when converting text from input method: supplied length = %d\n, result length = %d", xim_text->length, text_length);
|
|
|
|
}
|
|
|
|
}
|
2012-05-25 17:10:56 -07:00
|
|
|
else
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
EINA_LOG_WARN("Error converting text from IM to UCS-4");
|
|
|
|
*text = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
*text = result;
|
|
|
|
return text_length;
|
|
|
|
}
|
2012-05-25 17:10:56 -07:00
|
|
|
else
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
*text = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-01-13 16:04:16 -08:00
|
|
|
preedit_draw_callback(XIC xic __UNUSED__,
|
|
|
|
XPointer client_data,
|
2011-07-11 19:26:39 -07:00
|
|
|
XIMPreeditDrawCallbackStruct *call_data)
|
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
2011-07-26 04:57:51 -07:00
|
|
|
Eina_Bool ret = EINA_FALSE;
|
2011-07-11 19:26:39 -07:00
|
|
|
Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
|
|
|
|
XIMText *t = call_data->text;
|
|
|
|
char *tmp;
|
|
|
|
Eina_Unicode *new_text = NULL;
|
2011-07-26 04:57:51 -07:00
|
|
|
Eina_UStrbuf *preedit_bufs = NULL;
|
2011-07-11 19:26:39 -07:00
|
|
|
int new_text_length;
|
2011-12-20 01:49:55 -08:00
|
|
|
int i = 0;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
|
|
|
|
2011-07-26 04:57:51 -07:00
|
|
|
preedit_bufs = eina_ustrbuf_new();
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->preedit_chars)
|
|
|
|
{
|
|
|
|
ret = eina_ustrbuf_append(preedit_bufs, imf_context_data->preedit_chars);
|
|
|
|
if (ret == EINA_FALSE) goto done;
|
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
new_text_length = xim_text_to_utf8(ctx, t, &tmp);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (tmp)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
int tmp_len;
|
|
|
|
new_text = eina_unicode_utf8_to_unicode((const char *)tmp, &tmp_len);
|
|
|
|
free(tmp);
|
|
|
|
}
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (t == NULL)
|
|
|
|
{
|
|
|
|
/* delete string */
|
|
|
|
ret = eina_ustrbuf_remove(preedit_bufs,
|
|
|
|
call_data->chg_first, call_data->chg_length);
|
|
|
|
}
|
|
|
|
else if (call_data->chg_length == 0)
|
|
|
|
{
|
|
|
|
/* insert string */
|
|
|
|
ret = eina_ustrbuf_insert(preedit_bufs, new_text, call_data->chg_first);
|
|
|
|
}
|
|
|
|
else if (call_data->chg_length > 0)
|
|
|
|
{
|
|
|
|
/* replace string */
|
|
|
|
ret = eina_ustrbuf_remove(preedit_bufs,
|
|
|
|
call_data->chg_first, call_data->chg_length);
|
|
|
|
if (ret == EINA_FALSE) goto done;
|
|
|
|
|
|
|
|
ret = eina_ustrbuf_insert_n(preedit_bufs, new_text,
|
|
|
|
new_text_length, call_data->chg_first);
|
|
|
|
if (ret == EINA_FALSE) goto done;
|
|
|
|
}
|
2012-05-25 17:10:56 -07:00
|
|
|
else
|
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
ret = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
done:
|
|
|
|
if (ret == EINA_TRUE)
|
|
|
|
{
|
|
|
|
free(imf_context_data->preedit_chars);
|
|
|
|
imf_context_data->preedit_chars =
|
2011-07-26 04:57:51 -07:00
|
|
|
eina_ustrbuf_string_steal(preedit_bufs);
|
2012-01-13 16:04:16 -08:00
|
|
|
imf_context_data->preedit_length =
|
2011-07-26 04:57:51 -07:00
|
|
|
eina_unicode_strlen(imf_context_data->preedit_chars);
|
2011-07-28 22:37:31 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->feedbacks)
|
|
|
|
{
|
|
|
|
free(imf_context_data->feedbacks);
|
|
|
|
imf_context_data->feedbacks = NULL;
|
|
|
|
}
|
2011-12-20 01:49:55 -08:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->preedit_length > 0)
|
|
|
|
{
|
|
|
|
imf_context_data->feedbacks = calloc(imf_context_data->preedit_length, sizeof(XIMFeedback));
|
2011-12-20 01:49:55 -08:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
for (i = 0; i < imf_context_data->preedit_length; i++)
|
|
|
|
imf_context_data->feedbacks[i] = t->feedback[i];
|
|
|
|
}
|
2011-12-20 01:49:55 -08:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
ecore_imf_context_preedit_changed_event_add(ctx);
|
2012-01-17 20:38:04 -08:00
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
2012-01-13 16:04:16 -08:00
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
free(new_text);
|
2011-07-26 04:57:51 -07:00
|
|
|
eina_ustrbuf_free(preedit_bufs);
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-01-13 16:04:16 -08:00
|
|
|
preedit_caret_callback(XIC xic __UNUSED__,
|
|
|
|
XPointer client_data,
|
2011-07-11 19:26:39 -07:00
|
|
|
XIMPreeditCaretCallbackStruct *call_data)
|
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
Ecore_IMF_Context *ctx = (Ecore_IMF_Context *)client_data;
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (call_data->direction == XIMAbsolutePosition)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
// printf("call_data->position:%d\n", call_data->position);
|
2012-01-13 16:04:16 -08:00
|
|
|
imf_context_data->preedit_cursor = call_data->position;
|
|
|
|
if (imf_context_data->finalizing == EINA_FALSE)
|
2012-01-17 20:38:04 -08:00
|
|
|
{
|
|
|
|
ecore_imf_context_preedit_changed_event_add(ctx);
|
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static XVaNestedList
|
|
|
|
preedit_callback_set(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
|
|
|
|
|
|
|
imf_context_data->preedit_start_cb.client_data = (XPointer)ctx;
|
|
|
|
imf_context_data->preedit_start_cb.callback = (XIMProc)preedit_start_callback;
|
|
|
|
|
|
|
|
imf_context_data->preedit_done_cb.client_data = (XPointer)ctx;
|
|
|
|
imf_context_data->preedit_done_cb.callback = (XIMProc)preedit_done_callback;
|
|
|
|
|
|
|
|
imf_context_data->preedit_draw_cb.client_data = (XPointer)ctx;
|
|
|
|
imf_context_data->preedit_draw_cb.callback = (XIMProc)preedit_draw_callback;
|
|
|
|
|
|
|
|
imf_context_data->preedit_caret_cb.client_data = (XPointer)ctx;
|
|
|
|
imf_context_data->preedit_caret_cb.callback = (XIMProc)preedit_caret_callback;
|
|
|
|
|
|
|
|
return XVaCreateNestedList(0,
|
|
|
|
XNPreeditStartCallback,
|
|
|
|
&imf_context_data->preedit_start_cb,
|
|
|
|
XNPreeditDoneCallback,
|
|
|
|
&imf_context_data->preedit_done_cb,
|
|
|
|
XNPreeditDrawCallback,
|
|
|
|
&imf_context_data->preedit_draw_cb,
|
|
|
|
XNPreeditCaretCallback,
|
|
|
|
&imf_context_data->preedit_caret_cb,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
|
|
|
|
static XIC
|
|
|
|
get_ic(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
XIC ic;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return NULL;
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
ic = imf_context_data->ic;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!ic)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XIM_Im_Info *im_info = imf_context_data->im_info;
|
|
|
|
XVaNestedList preedit_attr = NULL;
|
|
|
|
XIMStyle im_style = 0;
|
2011-07-29 03:50:59 -07:00
|
|
|
XPoint spot = { 0, 0 };
|
2011-07-11 19:26:39 -07:00
|
|
|
char *name = NULL;
|
2011-09-02 21:47:50 -07:00
|
|
|
|
|
|
|
if (!im_info)
|
|
|
|
{
|
|
|
|
EINA_LOG_WARN("Doesn't open XIM.");
|
|
|
|
return NULL;
|
|
|
|
}
|
2012-01-13 16:04:16 -08:00
|
|
|
|
2011-07-29 03:50:59 -07:00
|
|
|
// supported styles
|
|
|
|
#if 0
|
|
|
|
int i;
|
|
|
|
if (im_info->xim_styles)
|
|
|
|
{
|
|
|
|
for (i = 0; i < im_info->xim_styles->count_styles; i++)
|
|
|
|
{
|
|
|
|
printf("%i: ", i);
|
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMPreeditCallbacks)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMPreeditCallbacks | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMPreeditPosition)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMPreeditPosition | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMPreeditArea)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMPreeditArea | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMPreeditNothing)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMPreeditNothing | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMPreeditNone)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMPreeditNone | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMStatusArea)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMStatusArea | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMStatusCallbacks)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMStatusCallbacks | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMStatusNothing)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMStatusNothing | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->xim_styles->supported_styles[i] & XIMStatusNone)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("XIMStatusNone | ");
|
2011-07-29 03:50:59 -07:00
|
|
|
printf("\n");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
// "OverTheSpot" = XIMPreeditPosition | XIMStatusNothing
|
|
|
|
// "OffTheSpot" = XIMPreeditArea | XIMStatusArea
|
|
|
|
// "Root" = XIMPreeditNothing | XIMStatusNothing
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2011-07-29 03:50:59 -07:00
|
|
|
if (imf_context_data->use_preedit == EINA_TRUE)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
2011-07-29 03:50:59 -07:00
|
|
|
if (im_info->supports_cursor)
|
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
// kinput2 DOES do this...
|
2011-07-29 03:50:59 -07:00
|
|
|
XFontSet fs;
|
|
|
|
char **missing_charset_list;
|
|
|
|
int missing_charset_count;
|
|
|
|
char *def_string;
|
2012-01-13 16:04:16 -08:00
|
|
|
|
2011-07-29 03:50:59 -07:00
|
|
|
im_style |= XIMPreeditPosition;
|
|
|
|
im_style |= XIMStatusNothing;
|
|
|
|
fs = XCreateFontSet(ecore_x_display_get(),
|
|
|
|
"fixed",
|
|
|
|
&missing_charset_list,
|
|
|
|
&missing_charset_count,
|
|
|
|
&def_string);
|
|
|
|
preedit_attr = XVaCreateNestedList(0,
|
|
|
|
XNSpotLocation, &spot,
|
|
|
|
XNFontSet, fs,
|
|
|
|
NULL);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
im_style |= XIMPreeditCallbacks;
|
|
|
|
im_style |= XIMStatusNothing;
|
|
|
|
preedit_attr = preedit_callback_set(ctx);
|
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
name = XNPreeditAttributes;
|
|
|
|
}
|
2012-01-13 16:04:16 -08:00
|
|
|
else
|
2011-07-29 03:50:59 -07:00
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
im_style |= XIMPreeditNothing;
|
2011-07-29 03:50:59 -07:00
|
|
|
im_style |= XIMStatusNothing;
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
2012-06-18 16:38:23 -07:00
|
|
|
if (!im_info->xim_styles)
|
|
|
|
{
|
|
|
|
EINA_LOG_WARN("No XIM styles supported! Wanted %#llx",
|
|
|
|
(unsigned long long)im_style);
|
|
|
|
im_style = 0;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
XIMStyle fallback = 0;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < im_info->xim_styles->count_styles; i++)
|
|
|
|
{
|
|
|
|
XIMStyle cur = im_info->xim_styles->supported_styles[i];
|
|
|
|
if (cur == im_style)
|
|
|
|
break;
|
|
|
|
else if (cur == (XIMPreeditNothing | XIMStatusNothing))
|
|
|
|
/* TODO: fallback is just that or the anyone? */
|
|
|
|
fallback = cur;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (i == im_info->xim_styles->count_styles)
|
|
|
|
{
|
|
|
|
if (fallback)
|
|
|
|
{
|
|
|
|
EINA_LOG_WARN("Wanted XIM style %#llx not found, "
|
|
|
|
"using fallback %#llx instead.",
|
|
|
|
(unsigned long long)im_style,
|
|
|
|
(unsigned long long)fallback);
|
|
|
|
im_style = fallback;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
EINA_LOG_WARN("Wanted XIM style %#llx not found, "
|
|
|
|
"no fallback supported.",
|
|
|
|
(unsigned long long)im_style);
|
|
|
|
im_style = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((im_info->im) && (im_style))
|
2011-07-28 05:01:04 -07:00
|
|
|
{
|
|
|
|
ic = XCreateIC(im_info->im,
|
|
|
|
XNInputStyle, im_style,
|
|
|
|
XNClientWindow, imf_context_data->win,
|
|
|
|
name, preedit_attr, NULL);
|
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
XFree(preedit_attr);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (ic)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
unsigned long mask = 0xaaaaaaaa;
|
2012-01-13 16:04:16 -08:00
|
|
|
XGetICValues(ic,
|
|
|
|
XNFilterEvents, &mask,
|
|
|
|
NULL);
|
2011-07-11 19:26:39 -07:00
|
|
|
imf_context_data->mask = mask;
|
|
|
|
ecore_x_event_mask_set(imf_context_data->win, mask);
|
|
|
|
}
|
|
|
|
|
|
|
|
imf_context_data->ic = ic;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (ic && imf_context_data->has_focus == EINA_TRUE)
|
2011-07-11 19:26:39 -07:00
|
|
|
XSetICFocus(ic);
|
|
|
|
}
|
|
|
|
|
|
|
|
return ic;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reinitialize_ic(Ecore_IMF_Context *ctx)
|
|
|
|
{
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
XIC ic = imf_context_data->ic;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (ic)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XDestroyIC(ic);
|
|
|
|
imf_context_data->ic = NULL;
|
2012-01-13 16:04:16 -08:00
|
|
|
if (imf_context_data->preedit_length)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
imf_context_data->preedit_length = 0;
|
2011-07-26 04:57:51 -07:00
|
|
|
free(imf_context_data->preedit_chars);
|
|
|
|
imf_context_data->preedit_chars = NULL;
|
2011-07-11 19:26:39 -07:00
|
|
|
ecore_imf_context_preedit_changed_event_add(ctx);
|
2012-01-17 20:38:04 -08:00
|
|
|
ecore_imf_context_event_callback_call(ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
reinitialize_all_ics(XIM_Im_Info *info)
|
|
|
|
{
|
|
|
|
Eina_List *tmp_list;
|
|
|
|
Ecore_IMF_Context *ctx;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
EINA_LIST_FOREACH (info->ics, tmp_list, ctx)
|
2011-07-11 19:26:39 -07:00
|
|
|
reinitialize_ic(ctx);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
set_ic_client_window(Ecore_IMF_Context *ctx,
|
2012-01-13 16:04:16 -08:00
|
|
|
Ecore_X_Window window)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
Ecore_IMF_Context_Data *imf_context_data = ecore_imf_context_data_get(ctx);
|
|
|
|
Ecore_X_Window old_win;
|
|
|
|
|
2012-06-19 08:18:34 -07:00
|
|
|
if (!imf_context_data) return;
|
|
|
|
|
2011-07-11 19:26:39 -07:00
|
|
|
/* reinitialize IC */
|
|
|
|
reinitialize_ic(ctx);
|
|
|
|
|
|
|
|
old_win = imf_context_data->win;
|
|
|
|
EINA_LOG_DBG("old_win:%d window:%d ", old_win, window);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (old_win != 0 && old_win != window) /* XXX how do check window... */
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XIM_Im_Info *info;
|
|
|
|
info = imf_context_data->im_info;
|
|
|
|
info->ics = eina_list_remove(info->ics, imf_context_data);
|
|
|
|
imf_context_data->im_info = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
imf_context_data->win = window;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (window) /* XXX */
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XIM_Im_Info *info = NULL;
|
|
|
|
info = get_im(window, imf_context_data->locale);
|
|
|
|
imf_context_data->im_info = info;
|
|
|
|
imf_context_data->im_info->ics =
|
|
|
|
eina_list_prepend(imf_context_data->im_info->ics,
|
|
|
|
imf_context_data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static XIM_Im_Info *
|
|
|
|
get_im(Ecore_X_Window window,
|
2012-01-13 16:04:16 -08:00
|
|
|
char *locale)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
EINA_LOG_DBG("in");
|
|
|
|
|
|
|
|
Eina_List *l;
|
|
|
|
XIM_Im_Info *im_info = NULL;
|
|
|
|
XIM_Im_Info *info = NULL;
|
2012-05-25 17:10:56 -07:00
|
|
|
EINA_LIST_FOREACH (open_ims, l, im_info)
|
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
if (strcmp(im_info->locale, locale) == 0)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
if (im_info->im)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
return im_info;
|
|
|
|
}
|
2012-05-25 17:10:56 -07:00
|
|
|
else
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
info = im_info;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!info)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
info = calloc(1, sizeof(XIM_Im_Info));
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!info) return NULL;
|
2011-07-11 19:26:39 -07:00
|
|
|
open_ims = eina_list_prepend(open_ims, info);
|
|
|
|
info->win = window;
|
|
|
|
info->locale = strdup(locale);
|
|
|
|
info->reconnecting = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
xim_info_try_im(info);
|
|
|
|
return info;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* initialize info->im */
|
|
|
|
static void
|
|
|
|
xim_info_try_im(XIM_Im_Info *info)
|
|
|
|
{
|
|
|
|
Ecore_X_Display *dsp;
|
|
|
|
|
|
|
|
assert(info->im == NULL);
|
|
|
|
if (info->reconnecting == EINA_TRUE)
|
|
|
|
return;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (XSupportsLocale())
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!XSetLocaleModifiers(""))
|
2011-07-11 19:26:39 -07:00
|
|
|
EINA_LOG_WARN("Unable to set locale modifiers with XSetLocaleModifiers()");
|
|
|
|
dsp = ecore_x_display_get();
|
|
|
|
info->im = XOpenIM(dsp, NULL, NULL, NULL);
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!info->im)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XRegisterIMInstantiateCallback(dsp,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
xim_instantiate_callback,
|
|
|
|
(XPointer)info);
|
|
|
|
info->reconnecting = EINA_TRUE;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
setup_im(info);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2011-07-25 00:16:54 -07:00
|
|
|
xim_info_display_closed(Ecore_X_Display *display __UNUSED__,
|
2012-01-13 16:04:16 -08:00
|
|
|
int is_error __UNUSED__,
|
|
|
|
XIM_Im_Info *info)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
Eina_List *ics, *tmp_list;
|
|
|
|
Ecore_IMF_Context *ctx;
|
|
|
|
|
|
|
|
open_ims = eina_list_remove(open_ims, info);
|
|
|
|
|
|
|
|
ics = info->ics;
|
|
|
|
info->ics = NULL;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
EINA_LIST_FOREACH (ics, tmp_list, ctx)
|
2011-07-11 19:26:39 -07:00
|
|
|
set_ic_client_window(ctx, 0);
|
|
|
|
|
2012-05-25 17:10:56 -07:00
|
|
|
EINA_LIST_FREE (ics, ctx)
|
|
|
|
{
|
2011-07-11 19:26:39 -07:00
|
|
|
Ecore_IMF_Context_Data *imf_context_data;
|
|
|
|
imf_context_data = ecore_imf_context_data_get(ctx);
|
|
|
|
imf_context_data_destroy(imf_context_data);
|
|
|
|
}
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
free(info->locale);
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
if (info->im)
|
2012-01-13 16:04:16 -08:00
|
|
|
XCloseIM(info->im);
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
free(info);
|
2011-07-11 19:26:39 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
xim_instantiate_callback(Display *display,
|
|
|
|
XPointer client_data,
|
2011-07-25 00:16:54 -07:00
|
|
|
XPointer call_data __UNUSED__)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XIM_Im_Info *info = (XIM_Im_Info *)client_data;
|
|
|
|
XIM im = NULL;
|
|
|
|
|
|
|
|
im = XOpenIM(display, NULL, NULL, NULL);
|
|
|
|
|
2011-07-28 05:01:04 -07:00
|
|
|
if (!im)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "Failed to connect to IM\n");
|
|
|
|
return;
|
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
|
|
|
|
info->im = im;
|
2012-01-13 16:04:16 -08:00
|
|
|
setup_im(info);
|
2011-07-11 19:26:39 -07:00
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
XUnregisterIMInstantiateCallback(display, NULL, NULL, NULL,
|
|
|
|
xim_instantiate_callback,
|
|
|
|
(XPointer)info);
|
2011-07-11 19:26:39 -07:00
|
|
|
info->reconnecting = EINA_FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
setup_im(XIM_Im_Info *info)
|
|
|
|
{
|
|
|
|
XIMValuesList *ic_values = NULL;
|
|
|
|
XIMCallback im_destroy_callback;
|
|
|
|
|
2012-01-13 16:04:16 -08:00
|
|
|
if (!info->im)
|
2011-07-11 19:26:39 -07:00
|
|
|
return;
|
|
|
|
|
|
|
|
im_destroy_callback.client_data = (XPointer)info;
|
|
|
|
im_destroy_callback.callback = (XIMProc)xim_destroy_callback;
|
|
|
|
XSetIMValues(info->im,
|
|
|
|
XNDestroyCallback, &im_destroy_callback,
|
|
|
|
NULL);
|
|
|
|
|
|
|
|
XGetIMValues(info->im,
|
|
|
|
XNQueryInputStyle, &info->xim_styles,
|
|
|
|
XNQueryICValuesList, &ic_values,
|
|
|
|
NULL);
|
|
|
|
|
2011-07-29 03:50:59 -07:00
|
|
|
if (ic_values)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2011-07-29 03:50:59 -07:00
|
|
|
for (i = 0; i < ic_values->count_values; i++)
|
|
|
|
{
|
|
|
|
if (!strcmp(ic_values->supported_values[i],
|
|
|
|
XNStringConversionCallback))
|
2012-01-13 16:04:16 -08:00
|
|
|
info->supports_string_conversion = EINA_TRUE;
|
2011-07-29 03:50:59 -07:00
|
|
|
if (!strcmp(ic_values->supported_values[i],
|
|
|
|
XNCursor))
|
2012-01-13 16:04:16 -08:00
|
|
|
info->supports_cursor = EINA_TRUE;
|
2011-07-29 03:50:59 -07:00
|
|
|
}
|
2011-07-11 19:26:39 -07:00
|
|
|
#if 0
|
2011-07-29 03:50:59 -07:00
|
|
|
printf("values........\n");
|
|
|
|
for (i = 0; i < ic_values->count_values; i++)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("%s\n", ic_values->supported_values[i]);
|
2011-07-29 03:50:59 -07:00
|
|
|
printf("styles........\n");
|
|
|
|
for (i = 0; i < info->xim_styles->count_styles; i++)
|
2012-01-13 16:04:16 -08:00
|
|
|
printf("%lx\n", info->xim_styles->supported_styles[i]);
|
2011-07-11 19:26:39 -07:00
|
|
|
#endif
|
|
|
|
XFree(ic_values);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
2012-01-13 16:04:16 -08:00
|
|
|
xim_destroy_callback(XIM xim __UNUSED__,
|
2011-07-11 19:26:39 -07:00
|
|
|
XPointer client_data,
|
2011-07-25 00:16:54 -07:00
|
|
|
XPointer call_data __UNUSED__)
|
2011-07-11 19:26:39 -07:00
|
|
|
{
|
|
|
|
XIM_Im_Info *info = (XIM_Im_Info *)client_data;
|
|
|
|
info->im = NULL;
|
|
|
|
|
|
|
|
reinitialize_all_ics(info);
|
|
|
|
xim_info_try_im(info);
|
|
|
|
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* ENABLE_XIM */
|