Added Ecore_IMF module.

Added Ecore_IMF module. This module enables different input methods to be
used with Ecore. Input methods modules can be created using the Ecore_IMF
interface.
Added ecore_evas_window_get method to allow input methods to request
the window related to a given Ecore_Evas when available.


SVN revision: 32775
devs/devilhorns/wayland_egl
andrunko 15 years ago committed by andrunko
parent 23d39ab154
commit 502b766d66
  1. 8
      legacy/ecore/Makefile.am
  2. 7
      legacy/ecore/configure.in
  3. 11
      legacy/ecore/ecore-imf.pc.in
  4. 3
      legacy/ecore/src/lib/Makefile.am
  5. 1
      legacy/ecore/src/lib/ecore_evas/Ecore_Evas.h
  6. 14
      legacy/ecore/src/lib/ecore_evas/ecore_evas.c
  7. 1
      legacy/ecore/src/lib/ecore_evas/ecore_evas_buffer.c
  8. 22
      legacy/ecore/src/lib/ecore_evas/ecore_evas_directfb.c
  9. 1
      legacy/ecore/src/lib/ecore_evas/ecore_evas_fb.c
  10. 1
      legacy/ecore/src/lib/ecore_evas/ecore_evas_private.h
  11. 1
      legacy/ecore/src/lib/ecore_evas/ecore_evas_sdl.c
  12. 26
      legacy/ecore/src/lib/ecore_evas/ecore_evas_win32.c
  13. 61
      legacy/ecore/src/lib/ecore_evas/ecore_evas_x.c
  14. 6
      legacy/ecore/src/lib/ecore_imf/.cvsignore
  15. 162
      legacy/ecore/src/lib/ecore_imf/Ecore_IMF.h
  16. 31
      legacy/ecore/src/lib/ecore_imf/Makefile.am
  17. 64
      legacy/ecore/src/lib/ecore_imf/ecore_imf.c
  18. 740
      legacy/ecore/src/lib/ecore_imf/ecore_imf_context.c
  19. 207
      legacy/ecore/src/lib/ecore_imf/ecore_imf_module.c
  20. 36
      legacy/ecore/src/lib/ecore_imf/ecore_imf_private.h

@ -16,6 +16,7 @@ MAINTAINERCLEANFILES = Makefile.in aclocal.m4 config.guess \
ecore-evas.pc \
ecore-fb.pc \
ecore-file.pc \
ecore-imf.pc \
ecore-ipc.pc \
ecore-job.pc \
ecore-txt.pc \
@ -36,6 +37,7 @@ EXTRA_DIST = AUTHORS COPYING COPYING-PLAIN ecore.c.in gendoc ecore.supp \
ecore-evas.pc.in \
ecore-fb.pc.in \
ecore-file.pc.in \
ecore-imf.pc.in \
ecore-ipc.pc.in \
ecore-job.pc.in \
ecore-txt.pc.in \
@ -73,6 +75,10 @@ if BUILD_ECORE_DESKTOP
pdesktop = ecore-desktop.pc
endif
if BUILD_ECORE_IMF
pimf = ecore-imf.pc
endif
if BUILD_ECORE_IPC
pipc = ecore-ipc.pc
endif
@ -105,5 +111,5 @@ endif
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = \
ecore.pc $(pcon) $(pconfig) $(pdfb) $(pevas) \
$(pfb) $(pfile) $(pdesktop) $(pipc) $(pjob) $(ptxt) \
$(pfb) $(pfile) $(pdesktop) $(pimf) $(pipc) $(pjob) $(ptxt) \
$(px) $(pwin32) $(psdl)

@ -704,6 +704,9 @@ dnl ecore_desktop
ECORE_CHECK_MODULE([Desktop], [no], [$have_ecore_file],
[requirements_ecore_desktop="ecore-file"])
dnl ecore_imf
ECORE_CHECK_MODULE([IMF], [yes], [$have_evas])
dnl requirements
AC_SUBST(requirements_ecore_con)
AC_SUBST(requirements_ecore_config)
@ -738,6 +741,7 @@ ecore-directfb.pc
ecore-evas.pc
ecore-fb.pc
ecore-file.pc
ecore-imf.pc
ecore-ipc.pc
ecore-job.pc
ecore-txt.pc
@ -755,6 +759,7 @@ src/lib/ecore_fb/Makefile
src/lib/ecore_sdl/Makefile
src/lib/ecore_evas/Makefile
src/lib/ecore_con/Makefile
src/lib/ecore_imf/Makefile
src/lib/ecore_ipc/Makefile
src/lib/ecore_txt/Makefile
src/lib/ecore_config/Makefile
@ -799,6 +804,8 @@ echo " Ecore_Evas Buffer Support....: $have_ecore_evas_buffer"
echo " Ecore_File...................: $have_ecore_file (Inotify: $have_inotify) (Poll: $have_poll) (CURL: $have_curl)"
echo " Ecore_Desktop................: $have_ecore_desktop"
echo " Ecore_IMF....................: $have_ecore_imf"
echo
echo "Now type 'make' ('gmake' on some systems) to compile $PACKAGE."
echo

@ -0,0 +1,11 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: ecore-imf
Description: E core library, IMF module
Requires: ecore evas
Version: @VERSION@
Libs: -L${libdir} -lecore_imf
Cflags: -I${includedir}

@ -13,4 +13,5 @@ ecore_ipc \
ecore_evas \
ecore_config \
ecore_file \
ecore_desktop
ecore_desktop \
ecore_imf

@ -232,6 +232,7 @@ EAPI void ecore_evas_sticky_set(Ecore_Evas *ee, int sticky);
EAPI int ecore_evas_sticky_get(Ecore_Evas *ee);
EAPI void ecore_evas_ignore_events_set(Ecore_Evas *ee, int ignore);
EAPI int ecore_evas_ignore_events_get(Ecore_Evas *ee);
EAPI void *ecore_evas_window_get(Ecore_Evas *ee);
#ifdef __cplusplus
}

@ -1773,6 +1773,20 @@ ecore_evas_ignore_events_get(Ecore_Evas *ee)
return ee->ignore_events ? 1 : 0;
}
EAPI void *
ecore_evas_window_get(Ecore_Evas *ee)
{
if (!ECORE_MAGIC_CHECK(ee, ECORE_MAGIC_EVAS))
{
ECORE_MAGIC_FAIL(ee, ECORE_MAGIC_EVAS,
"ecore_evas_window_get");
return NULL;
}
if (ee->engine.func->fn_window_get) return ee->engine.func->fn_window_get(ee);
return NULL;
}
#ifndef _WIN32
/* fps debug calls - for debugging how much time your app actually spends */
/* rendering graphics... :) */

@ -425,6 +425,7 @@ static const Ecore_Evas_Engine_Func _ecore_buffer_engine_func =
NULL,
NULL,
NULL,
NULL,
NULL
};
#endif

@ -497,8 +497,19 @@ _ecore_evas_directfb_fullscreen_set(Ecore_Evas *ee, int on)
if(ee->func.fn_resize) ee->func.fn_resize(ee);
}
}
#endif
static void *
_ecore_evas_directfb_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_DIRECTFB
return ee->engine.directfb.window;
#else
return 0;
#endif
}
#ifdef BUILD_ECORE_EVAS_DIRECTFB
static const Ecore_Evas_Engine_Func _ecore_directfb_engine_func =
{
_ecore_evas_directfb_free, /* free an ecore_evas */
@ -544,7 +555,8 @@ static const Ecore_Evas_Engine_Func _ecore_directfb_engine_func =
NULL, /* withdrawn */
NULL, /* sticky */
NULL, /* ignore events */
NULL /* alpha */
NULL, /* alpha */
_ecore_evas_directfb_window_get /* window_get */
};
#endif
@ -554,15 +566,9 @@ static const Ecore_Evas_Engine_Func _ecore_directfb_engine_func =
Ecore_DirectFB_Window *
ecore_evas_directfb_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_DIRECTFB
return ee->engine.directfb.window;
#else
ee = NULL;
return NULL;
#endif
return (Ecore_DirectFB_Window *) _ecore_evas_directfb_window_get(ee);
}
EAPI Ecore_Evas *
ecore_evas_directfb_new(const char *disp_name, int windowed, int x, int y, int w, int h)
{

@ -557,6 +557,7 @@ static const Ecore_Evas_Engine_Func _ecore_fb_engine_func =
_ecore_evas_fullscreen_set,
NULL,
NULL,
NULL,
NULL
};
#endif

@ -124,6 +124,7 @@ struct _Ecore_Evas_Engine_Func
void (*fn_sticky_set) (Ecore_Evas *ee, int sticky);
void (*fn_ignore_events_set) (Ecore_Evas *ee, int ignore);
void (*fn_alpha_set) (Ecore_Evas *ee, int alpha);
void *(*fn_window_get) (Ecore_Evas *ee);
};
struct _Ecore_Evas_Engine

@ -419,6 +419,7 @@ static const Ecore_Evas_Engine_Func _ecore_sdl_engine_func =
NULL,
NULL,
NULL,
NULL,
NULL
};
#endif

@ -874,8 +874,19 @@ _ecore_evas_win32_fullscreen_set(Ecore_Evas *ee, int on)
/* else */
/* _ecore_evas_win32_state_update(ee); */
}
#endif
static void *
_ecore_evas_win32_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_WIN32
return ee->engine.win32.window;
#else
return NULL;
#endif /* BUILD_ECORE_WIN32 */
}
#ifdef BUILD_ECORE_WIN32
static const Ecore_Evas_Engine_Func _ecore_win32_engine_func =
{
_ecore_evas_win32_free,
@ -921,7 +932,8 @@ static const Ecore_Evas_Engine_Func _ecore_win32_engine_func =
NULL, /* _ecore_evas_x_withdrawn_set */
NULL, /* _ecore_evas_x_sticky_set */
NULL, /* _ecore_evas_x_ignore_events_set */
NULL /* _ecore_evas_x_alpha_set */
NULL, /* _ecore_evas_x_alpha_set */
_ecore_evas_win32_window_get
};
#endif /* BUILD_ECORE_WIN32 */
@ -1037,11 +1049,7 @@ ecore_evas_software_ddraw_new(Ecore_Win32_Window *parent,
EAPI Ecore_Win32_Window *
ecore_evas_software_ddraw_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_WIN32
return ee->engine.win32.window;
#else
return NULL;
#endif /* BUILD_ECORE_WIN32 */
return (Ecore_Win32_Window *) _ecore_evas_win32_window_get(ee);
}
EAPI Ecore_Evas *
@ -1154,9 +1162,5 @@ ecore_evas_direct3d_new(Ecore_Win32_Window *parent,
EAPI Ecore_Win32_Window *
ecore_evas_direct3d_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_WIN32
return ee->engine.win32.window;
#else
return NULL;
#endif /* BUILD_ECORE_WIN32 */
return (Ecore_Win32_Window *) _ecore_evas_win32_window_get(ee);
}

@ -2026,6 +2026,16 @@ _ecore_evas_x_alpha_set(Ecore_Evas *ee, int alpha)
}
}
static void *
_ecore_evas_x_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_X11
return (void *) ee->engine.x.win;
#else
return 0;
#endif
}
static void
_ecore_evas_x_show(Ecore_Evas *ee)
{
@ -2544,7 +2554,8 @@ static const Ecore_Evas_Engine_Func _ecore_x_engine_func =
_ecore_evas_x_withdrawn_set,
_ecore_evas_x_sticky_set,
_ecore_evas_x_ignore_events_set,
_ecore_evas_x_alpha_set
_ecore_evas_x_alpha_set,
_ecore_evas_x_window_get
};
#endif
@ -2819,11 +2830,7 @@ ecore_evas_software_x11_new(const char *disp_name, Ecore_X_Window parent,
EAPI Ecore_X_Window
ecore_evas_software_x11_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_X11
return ee->engine.x.win;
#else
return 0;
#endif
return (Ecore_X_Window) _ecore_evas_x_window_get(ee);
}
/**
@ -2834,11 +2841,7 @@ ecore_evas_software_x11_window_get(Ecore_Evas *ee)
EAPI Ecore_X_Window
ecore_evas_software_x11_subwindow_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_X11
return ee->engine.x.win;
#else
return 0;
#endif
return (Ecore_X_Window) _ecore_evas_x_window_get(ee);
}
/**
@ -3012,11 +3015,7 @@ ecore_evas_gl_x11_new(const char *disp_name, Ecore_X_Window parent,
EAPI Ecore_X_Window
ecore_evas_gl_x11_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_X11
return ee->engine.x.win;
#else
return 0;
#endif
return (Ecore_X_Window) _ecore_evas_x_window_get(ee);
}
/**
@ -3027,11 +3026,7 @@ ecore_evas_gl_x11_window_get(Ecore_Evas *ee)
EAPI Ecore_X_Window
ecore_evas_gl_x11_subwindow_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_X11
return ee->engine.x.win;
#else
return 0;
#endif
return (Ecore_X_Window) _ecore_evas_x_window_get(ee);
}
/**
@ -3264,11 +3259,7 @@ ecore_evas_xrender_x11_new(const char *disp_name, Ecore_X_Window parent,
EAPI Ecore_X_Window
ecore_evas_xrender_x11_window_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_X11
return ee->engine.x.win;
#else
return 0;
#endif
return (Ecore_X_Window) _ecore_evas_x_window_get(ee);
}
/**
@ -3279,11 +3270,7 @@ ecore_evas_xrender_x11_window_get(Ecore_Evas *ee)
EAPI Ecore_X_Window
ecore_evas_xrender_x11_subwindow_get(Ecore_Evas *ee)
{
#ifdef BUILD_ECORE_EVAS_X11
return ee->engine.x.win;
#else
return 0;
#endif
return (Ecore_X_Window) _ecore_evas_x_window_get(ee);
}
/**
@ -3474,11 +3461,7 @@ ecore_evas_software_x11_16_new(const char *disp_name, Ecore_X_Window parent,
EAPI Ecore_X_Window
ecore_evas_software_x11_16_window_get(Ecore_Evas *ee)
{
#if BUILD_ECORE_EVAS_X11_16
return ee->engine.x.win;
#else
return 0;
#endif
return (Ecore_X_Window) _ecore_evas_x_window_get(ee);
}
/**
@ -3489,11 +3472,7 @@ ecore_evas_software_x11_16_window_get(Ecore_Evas *ee)
EAPI Ecore_X_Window
ecore_evas_software_x11_16_subwindow_get(Ecore_Evas *ee)
{
#if BUILD_ECORE_EVAS_X11_16
return ee->engine.x.win;
#else
return 0;
#endif
return (Ecore_X_Window) _ecore_evas_x_window_get(ee);
}
/**

@ -0,0 +1,6 @@
.deps
.libs
Makefile
Makefile.in
*.lo
*.la

@ -0,0 +1,162 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#ifndef _ECORE_IMF_H
#define _ECORE_IMF_H
#ifdef EAPI
#undef EAPI
#endif
#ifdef _MSC_VER
# ifdef BUILDING_DLL
# define EAPI __declspec(dllexport)
# else
# define EAPI __declspec(dllimport)
# endif
#else
# ifdef __GNUC__
# if __GNUC__ >= 4
# define EAPI __attribute__ ((visibility("default")))
# else
# define EAPI
# endif
# else
# define EAPI
# endif
#endif
#include <Ecore_Data.h>
#include <Evas.h>
#ifdef __cplusplus
extern "C" {
#endif
typedef struct _Ecore_IMF_Event_Preedit_Start Ecore_IMF_Event_Preedit_Start;
typedef struct _Ecore_IMF_Event_Preedit_End Ecore_IMF_Event_Preedit_End;
typedef struct _Ecore_IMF_Event_Preedit_Changed Ecore_IMF_Event_Preedit_Changed;
typedef struct _Ecore_IMF_Event_Commit Ecore_IMF_Event_Commit;
typedef struct _Ecore_IMF_Event_Delete_Surrounding Ecore_IMF_Event_Delete_Surrounding;
typedef struct _Ecore_IMF_Context Ecore_IMF_Context; /**< An Input Method Context */
typedef struct _Ecore_IMF_Context_Class Ecore_IMF_Context_Class; /**< An Input Method Context class */
typedef struct _Ecore_IMF_Context_Info Ecore_IMF_Context_Info; /**< An Input Method Context info */
EAPI extern int ECORE_IMF_EVENT_PREEDIT_START;
EAPI extern int ECORE_IMF_EVENT_PREEDIT_END;
EAPI extern int ECORE_IMF_EVENT_PREEDIT_CHANGED;
EAPI extern int ECORE_IMF_EVENT_COMMIT;
EAPI extern int ECORE_IMF_EVENT_DELETE_SURROUNDIND;
typedef enum
{
ECORE_IMF_INPUT_MODE_ALPHA = 1 << 0,
ECORE_IMF_INPUT_MODE_NUMERIC = 1 << 1,
ECORE_IMF_INPUT_MODE_SPECIAL = 1 << 2,
ECORE_IMF_INPUT_MODE_HEXA = 1 << 3,
ECORE_IMF_INPUT_MODE_TELE = 1 << 4,
ECORE_IMF_INPUT_MODE_FULL = (ECORE_IMF_INPUT_MODE_ALPHA | ECORE_IMF_INPUT_MODE_NUMERIC | ECORE_IMF_INPUT_MODE_SPECIAL),
ECORE_IMF_INPUT_MODE_INVISIBLE = 1 << 29,
ECORE_IMF_INPUT_MODE_AUTOCAP = 1 << 30
} Ecore_IMF_Input_Mode;
struct _Ecore_IMF_Event_Preedit_Start
{
Ecore_IMF_Context *ctx;
};
struct _Ecore_IMF_Event_Preedit_End
{
Ecore_IMF_Context *ctx;
};
struct _Ecore_IMF_Event_Preedit_Changed
{
Ecore_IMF_Context *ctx;
};
struct _Ecore_IMF_Event_Commit
{
Ecore_IMF_Context *ctx;
char *str;
};
struct _Ecore_IMF_Event_Delete_Surrounding
{
Ecore_IMF_Context *ctx;
int offset;
int n_chars;
};
struct _Ecore_IMF_Context_Class
{
void (*add) (Ecore_IMF_Context *ctx);
void (*del) (Ecore_IMF_Context *ctx);
void (*client_window_set) (Ecore_IMF_Context *ctx, void *window);
void (*show) (Ecore_IMF_Context *ctx);
void (*hide) (Ecore_IMF_Context *ctx);
void (*preedit_string_get) (Ecore_IMF_Context *ctx, char **str, int *cursor_pos);
void (*focus_in) (Ecore_IMF_Context *ctx);
void (*focus_out) (Ecore_IMF_Context *ctx);
void (*reset) (Ecore_IMF_Context *ctx);
void (*cursor_position_set) (Ecore_IMF_Context *ctx, int cursor_pos);
void (*use_preedit_set) (Ecore_IMF_Context *ctx, int use_preedit);
void (*input_mode_set) (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode);
int (*filter_event) (Ecore_IMF_Context *ctx, Evas_Callback_Type type, void *event_info);
};
struct _Ecore_IMF_Context_Info
{
const char *id; /* ID */
const char *description; /* Human readable description */
const char *default_locales; /* Languages for which this context is the default, separated by : */
};
EAPI int ecore_imf_init(void);
EAPI int ecore_imf_shutdown(void);
EAPI Ecore_List *ecore_imf_context_available_ids_get(void);
EAPI const char *ecore_imf_context_default_id_get(void);
EAPI const Ecore_IMF_Context_Info *ecore_imf_context_info_by_id_get(const char *id);
EAPI Ecore_IMF_Context *ecore_imf_context_add(const char *id);
EAPI void ecore_imf_context_del(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window);
EAPI void ecore_imf_context_show(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_hide(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos);
EAPI void ecore_imf_context_focus_in(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_focus_out(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_reset(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos);
EAPI void ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, int use_preedit);
EAPI void ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, int (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data);
EAPI void ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode);
EAPI Ecore_IMF_Input_Mode ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx);
EAPI int ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Evas_Callback_Type type, void *event_info);
/* plugin specific functions */
EAPI Ecore_IMF_Context *ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc);
EAPI void ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data);
EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx);
EAPI int ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos);
EAPI void ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx);
EAPI void ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str);
EAPI void ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars);
/* The following entry points must be exported by each input method module
*/
/*
* int imf_module_init (const Ecore_IMF_Context_Info **info);
* void imf_module_exit (void);
* Ecore_IMF_Context *imf_module_create (void);
*/
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,31 @@
MAINTAINERCLEANFILES = Makefile.in
if BUILD_ECORE_IMF
AM_CPPFLAGS = \
-I$(top_srcdir)/src/lib/ecore \
-DPACKAGE_LIB_DIR=\"$(libdir)\" \
@EVAS_CFLAGS@
lib_LTLIBRARIES = libecore_imf.la
include_HEADERS = \
Ecore_IMF.h
libecore_imf_la_SOURCES = \
ecore_imf.c \
ecore_imf_context.c \
ecore_imf_module.c \
ecore_imf_private.h
libecore_imf_la_LIBADD = \
$(top_builddir)/src/lib/ecore/libecore.la \
@EVAS_LIBS@
libecore_imf_la_LDFLAGS = -version-info @version_info@
endif
EXTRA_DIST = \
Ecore_IMF.h \
ecore_imf.c \
ecore_imf_context.c \
ecore_imf_module.c \
ecore_imf_private.h

@ -0,0 +1,64 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include "config.h"
#include "Ecore_IMF.h"
EAPI int ECORE_IMF_EVENT_PREEDIT_START = 0;
EAPI int ECORE_IMF_EVENT_PREEDIT_END = 0;
EAPI int ECORE_IMF_EVENT_PREEDIT_CHANGED = 0;
EAPI int ECORE_IMF_EVENT_COMMIT = 0;
EAPI int ECORE_IMF_EVENT_RETRIEVE_SURROUNDIND = 0;
EAPI int ECORE_IMF_EVENT_DELETE_SURROUNDIND = 0;
static int init_count = 0;
/**
* @defgroup Ecore_IMF_Lib_Group Ecore Input Method Library Functions
*
* Utility functions that set up and shut down the Ecore Input Method
* library.
*/
/**
* Initialises the Ecore_IMF library.
* @return Number of times the library has been initialised without being
* shut down.
* @ingroup Ecore_IMF_Lib_Group
*/
EAPI int
ecore_imf_init(void)
{
if (++init_count != 1) return init_count;
ecore_init();
ecore_imf_module_init();
ECORE_IMF_EVENT_PREEDIT_START = ecore_event_type_new();
ECORE_IMF_EVENT_PREEDIT_END = ecore_event_type_new();
ECORE_IMF_EVENT_PREEDIT_CHANGED = ecore_event_type_new();
ECORE_IMF_EVENT_COMMIT = ecore_event_type_new();
ECORE_IMF_EVENT_RETRIEVE_SURROUNDIND = ecore_event_type_new();
ECORE_IMF_EVENT_DELETE_SURROUNDIND = ecore_event_type_new();
return init_count;
}
/**
* Shuts down the Ecore_IMF library.
* @return Number of times the library has been initialised without being
* shut down.
* @ingroup Ecore_IMF_Lib_Group
*/
EAPI int
ecore_imf_shutdown(void)
{
if (--init_count != 0) return init_count;
ecore_shutdown();
ecore_imf_module_shutdown();
return init_count;
}

@ -0,0 +1,740 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#include <locale.h>
#include <stdlib.h>
#include "config.h"
#include "Ecore_IMF.h"
#include "ecore_imf_private.h"
/**
* @defgroup Ecore_IMF_Context_Group Ecore Input Method Context Functions
*
* Functions that operate on Ecore Input Method Context objects.
*/
/**
* Get the list of the available Input Method Context ids.
*
* Note that the caller is responsible for freeing the Ecore_List
* when finished with it. There is no need to finish the list strings.
*
* @return Return an Ecore_List of strings;
* on failure it returns NULL.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI Ecore_List *
ecore_imf_context_available_ids_get(void)
{
return ecore_imf_module_context_ids_get();
}
/*
* Match @locale against @against.
*
* 'en_US' against 'en_US' => 4
* 'en_US' against 'en' => 3
* 'en', 'en_UK' against 'en_US' => 2
* all locales, against '*' => 1
*/
static int
_ecore_imf_context_match_locale(const char *locale, const char *against, int against_len)
{
if (strcmp(against, "*") == 0)
return 1;
if (strcasecmp(locale, against) == 0)
return 4;
if (strncasecmp(locale, against, 2) == 0)
return (against_len == 2) ? 3 : 2;
return 0;
}
/**
* Get the id of the default Input Method Context.
* The id may to used to create a new instance of an Input Method
* Context object.
*
* @return Return a string containing the id of the default Input
* Method Context; on failure it returns NULL.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI const char *
ecore_imf_context_default_id_get(void)
{
const char *id;
Ecore_List *modules;
Ecore_IMF_Module *module;
char *locale;
char *tmp;
int best_goodness = 0;
id = getenv("ECORE_IMF_MODULE");
if (id && ecore_imf_module_get(id)) return id;
modules = ecore_imf_module_available_get();
if (!modules) return NULL;
locale = setlocale(LC_CTYPE, NULL);
if (!locale) return NULL;
locale = strdup(locale);
tmp = strchr(locale, '.');
if (tmp) *tmp = '\0';
tmp = strchr(locale, '@');
if (tmp) *tmp = '\0';
id = NULL;
ecore_list_first_goto(modules);
while ((module = ecore_list_next(modules)))
{
const char *p = module->info->default_locales;
while (p)
{
const char *q = strchr(p, ':');
int goodness = _ecore_imf_context_match_locale(locale, p, q ? q - p : strlen (p));
if (goodness > best_goodness)
{
id = module->info->id;
best_goodness = goodness;
}
p = q ? q + 1 : NULL;
}
}
ecore_list_destroy(modules);
free(locale);
return id;
}
/**
* Retrieve the info for the Input Method Context with @p id.
*
* @param id The Input Method Context id to query for.
* @return Return a #Ecore_IMF_Context_Info for the Input Method Context with @p id;
* on failure it returns NULL.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI const Ecore_IMF_Context_Info *
ecore_imf_context_info_by_id_get(const char *id)
{
Ecore_IMF_Module *module;
if (!id) return NULL;
module = ecore_imf_module_get(id);
if (!module) return NULL;
return module->info;
}
/**
* Create a new Input Method Context defined by the given id.
*
* @param id The Input Method Context id.
* @return A newly allocated Input Method Context;
* on failure it returns NULL.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI Ecore_IMF_Context *
ecore_imf_context_add(const char *id)
{
Ecore_IMF_Context *ctx;
if (!id) return NULL;
ctx = ecore_imf_module_context_create(id);
if (!ctx || !ctx->klass) return NULL;
if (ctx->klass->add) ctx->klass->add(ctx);
/* default use_preedit is 1, so let's make sure it's
* set on the immodule */
ecore_imf_context_use_preedit_set(ctx, 1);
/* default input_mode is ECORE_IMF_INPUT_MODE_FULL, so let's make sure it's
* set on the immodule */
ecore_imf_context_input_mode_set(ctx, ECORE_IMF_INPUT_MODE_FULL);
return ctx;
}
/**
* Delete the given Input Method Context and free its memory.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_del(Ecore_IMF_Context *ctx)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_del");
return;
}
if (ctx->klass->del) ctx->klass->del(ctx);
ECORE_MAGIC_SET(ctx, ECORE_MAGIC_NONE);
free(ctx);
}
/**
* Set the client window for the Input Method Context; this is the
* window returned by ecore_evas_window_get() in which the input appears.
* This window is used in order to correctly position status windows, and may
* also be used for purposes internal to the Input Method Context.
*
* @param ctx An #Ecore_IMF_Context.
* @param window The client window. This may be NULL to indicate
* that the previous client window no longer exists.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_client_window_set");
return;
}
if (ctx->klass->client_window_set) ctx->klass->client_window_set(ctx, window);
}
/**
* Ask the Input Method Context to show itself.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_show(Ecore_IMF_Context *ctx)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_show");
return;
}
if (ctx->klass->show) ctx->klass->show(ctx);
}
/**
* Ask the Input Method Context to hide itself.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_hide(Ecore_IMF_Context *ctx)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_hide");
return;
}
if (ctx->klass->hide) ctx->klass->hide(ctx);
}
/*
* Retrieve the current preedit string and cursor position
* for the Input Method Context.
*
* @param ctx An #Ecore_IMF_Context.
* @param str Location to store the retrieved string. The
* string retrieved must be freed with free().
* @param cursor_pos Location to store position of cursor (in characters)
* within the preedit string.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_preedit_string_get");
return;
}
if (ctx->klass->preedit_string_get)
ctx->klass->preedit_string_get(ctx, str, cursor_pos);
else
{
if (str) *str = strdup("");
if (cursor_pos) *cursor_pos = 0;
}
}
/**
* Notify the Input Method Context that the widget to which its
* correspond has gained focus.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_focus_in(Ecore_IMF_Context *ctx)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_focus_in");
return;
}
if (ctx->klass->focus_in) ctx->klass->focus_in(ctx);
}
/**
* Notify the Input Method Context that the widget to which its
* correspond has lost focus.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_focus_out(Ecore_IMF_Context *ctx)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_focus_out");
return;
}
if (ctx->klass->focus_out) ctx->klass->focus_out(ctx);
}
/**
* 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.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_reset(Ecore_IMF_Context *ctx)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_reset");
return;
}
if (ctx->klass->reset) ctx->klass->reset(ctx);
}
/**
* Notify the Input Method Context that a change in the cursor
* position has been made.
*
* @param ctx An #Ecore_IMF_Context.
* @param cursor_pos New cursor position in characters.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_cursor_position_set");
return;
}
if (ctx->klass->cursor_position_set) ctx->klass->cursor_position_set(ctx, cursor_pos);
}
/**
* Set whether the IM context should use the preedit string
* to display feedback. If @use_preedit 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.
*
* @param ctx An #Ecore_IMF_Context.
* @param use_preedit Whether the IM context should use the preedit string.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, int use_preedit)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_use_preedit_set");
return;
}
if (ctx->klass->use_preedit_set) ctx->klass->use_preedit_set(ctx, use_preedit);
}
/**
* Set the callback to be used on get_surrounding request.
*
* This callback will be called when the Input Method Context
* module requests the surrounding context.
*
* @param ctx An #Ecore_IMF_Context.
* @param func The callback to be called.
* @param data The data pointer to be passed to @p func
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, int (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_retrieve_surrounding_callback_set");
return;
}
ctx->retrieve_surrounding_func = func;
ctx->retrieve_surrounding_data = (void *) data;
}
/**
* Set the input mode used by the Ecore Input Context.
*
* The input mode can be one of the input modes defined in
* #Ecore_IMF_Input_Mode. The default input mode is
* ECORE_IMF_INPUT_MODE_FULL.
*
* @param ctx An #Ecore_IMF_Context.
* @param input_mode The input mode to be used by @p ctx.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI void
ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_input_mode_set");
return;
}
if (ctx->klass->input_mode_set) ctx->klass->input_mode_set(ctx, input_mode);
ctx->input_mode = input_mode;
}
/**
* Get the input mode being used by the Ecore Input Context.
*
* See @ref ecore_imf_context_input_mode_set for more details.
*
* @param ctx An #Ecore_IMF_Context.
* @return The input mode being used by @p ctx.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI Ecore_IMF_Input_Mode
ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_input_mode_set");
return 0;
}
return ctx->input_mode;
}
/**
* 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.
*
* @param ctx An #Ecore_IMF_Context.
* @param type The type of event defined in #Evas_Callback_Type
* @param event_info The event itself; This should be one of
* Evas_Event_* types or NULL for some event types as
* EVAS_CALLBACK_SHOW/HIDE for example.
* @return 1 if the event was handled; otherwise 0.
* @ingroup Ecore_IMF_Context_Group
*/
EAPI int
ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Evas_Callback_Type type, void *event_info)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_filter_event");
return 0;
}
if (ctx->klass->filter_event) return ctx->klass->filter_event(ctx, type, event_info);
return 0;
}
/**
* @defgroup Ecore_IMF_Context_Module_Group Ecore Input Method Context Module Functions
*
* Functions that should be used by Ecore Input Method Context modules.
*/
/**
* Creates a new Input Method Context with klass specified by @p ctxc.
*
* This method should be used by modules implementing the Input
* Method Context interface.
*
* @param ctxc An #Ecore_IMF_Context_Class.
* @return A new #Ecore_IMF_Context; on failure it returns NULL.
* @ingroup Ecore_IMF_Context_Module_Group
*/
EAPI Ecore_IMF_Context *
ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc)
{
Ecore_IMF_Context *ctx;
if (!ctx) return NULL;
ctx = malloc(sizeof(Ecore_IMF_Context));
if (!ctx) return NULL;
ECORE_MAGIC_SET(ctx, ECORE_MAGIC_CONTEXT);
ctx->klass = ctxc;
ctx->data = NULL;
ctx->retrieve_surrounding_func = NULL;
ctx->retrieve_surrounding_data = NULL;
return ctx;
}
/**
* Set the Input Method Context specific data.
*
* Note that this method should be used by modules to set
* the Input Method Context specific data and it's not meant to
* be used by applications to store application specific data.
*
* @param ctx An #Ecore_IMF_Context.
* @param data The Input Method Context specific data.
* @return A new #Ecore_IMF_Context; on failure it returns NULL.
* @ingroup Ecore_IMF_Context_Module_Group
*/
EAPI void
ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_data_set");
return;
}
ctx->data = data;
}
/**
* Get the Input Method Context specific data.
*
* See @ref ecore_imf_context_data_set for more details.
*
* @param ctx An #Ecore_IMF_Context.
* @return The Input Method Context specific data.
* @ingroup Ecore_IMF_Context_Module_Group
*/
EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx)
{
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_data_get");
return;
}
return ctx->data;
}
/**
* Retrieve context around insertion point.
*
* This function is implemented by calling the
* Ecore_IMF_Context::retrieve_surrounding_func (
* set using #ecore_imf_context_retrieve_surrounding_callback_set).
*
* There is no obligation for a widget to respond to the
* ::retrieve_surrounding_func, so input methods must be prepared
* to function without context.
*
* @param ctx An #Ecore_IMF_Context.
* @param text Location to store a UTF-8 encoded string of text
* holding context around the insertion point.
* If the function returns 1, then you must free
* the result stored in this location with free().
* @param cursor_pos Location to store the position in characters of
* the insertion cursor within @text.
* @return 1 if surrounding text was provided; otherwise 0.
* @ingroup Ecore_IMF_Context_Module_Group
*/
EAPI int
ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos)
{
int result = 0;
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_surrounding_get");
return 0;
}
if (ctx->retrieve_surrounding_func)
{
result = ctx->retrieve_surrounding_func(ctx->retrieve_surrounding_data, ctx, text, cursor_pos);
if (!result)
{
if (text) *text = NULL;
if (cursor_pos) *cursor_pos = 0;
}
}
return result;
}
static void
_ecore_imf_event_free_preedit(void *data __UNUSED__, void *event)
{
free(event);
}
/**
* Adds ECORE_IMF_EVENT_PREEDIT_START to the event queue.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Module_Group
*/
EAPI void
ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx)
{
Ecore_IMF_Event_Commit *ev;
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_preedit_start_event_add");
return;
}
ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Start));
ev->ctx = ctx;
ecore_event_add(ECORE_IMF_EVENT_PREEDIT_START,
ev, _ecore_imf_event_free_preedit, NULL);
}
/**
* Adds ECORE_IMF_EVENT_PREEDIT_END to the event queue.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Module_Group
*/
EAPI void
ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx)
{
Ecore_IMF_Event_Commit *ev;
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_preedit_end_event_add");
return;
}
ev = malloc(sizeof(Ecore_IMF_Event_Preedit_End));
ev->ctx = ctx;
ecore_event_add(ECORE_IMF_EVENT_PREEDIT_END,
ev, _ecore_imf_event_free_preedit, NULL);
}
/**
* Adds ECORE_IMF_EVENT_PREEDIT_CHANGED to the event queue.
*
* @param ctx An #Ecore_IMF_Context.
* @ingroup Ecore_IMF_Context_Module_Group
*/
EAPI void
ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx)
{
Ecore_IMF_Event_Commit *ev;
if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
{
ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
"ecore_imf_context_preedit_changed_event_add");
return;
}
ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Changed));