summaryrefslogtreecommitdiff
path: root/src/lib/ecore_imf
diff options
context:
space:
mode:
authorVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
committerVincent Torri <vincent.torri@gmail.com>2012-12-02 22:35:45 +0000
commit7d6010b12c47a20e492da808e3192c3f87dab619 (patch)
tree26c6fd189e046a76560c0bc740b85f4d767ae399 /src/lib/ecore_imf
parent53fc441d5475155965d92da89502fe4634a561b2 (diff)
merge: add escape ecore, fix several bugs
SVN revision: 79995
Diffstat (limited to 'src/lib/ecore_imf')
-rw-r--r--src/lib/ecore_imf/Ecore_IMF.h577
-rw-r--r--src/lib/ecore_imf/Ecore_IMF_Evas.h50
-rw-r--r--src/lib/ecore_imf/ecore_imf.c73
-rw-r--r--src/lib/ecore_imf/ecore_imf_context.c1900
-rw-r--r--src/lib/ecore_imf/ecore_imf_evas.c324
-rw-r--r--src/lib/ecore_imf/ecore_imf_module.c212
-rw-r--r--src/lib/ecore_imf/ecore_imf_private.h84
7 files changed, 3220 insertions, 0 deletions
diff --git a/src/lib/ecore_imf/Ecore_IMF.h b/src/lib/ecore_imf/Ecore_IMF.h
new file mode 100644
index 0000000000..641ece74a3
--- /dev/null
+++ b/src/lib/ecore_imf/Ecore_IMF.h
@@ -0,0 +1,577 @@
1#ifndef _ECORE_IMF_H
2#define _ECORE_IMF_H
3
4#include <Eina.h>
5
6#ifdef EAPI
7# undef EAPI
8#endif
9
10#ifdef _WIN32
11# ifdef EFL_ECORE_IMF_BUILD
12# ifdef DLL_EXPORT
13# define EAPI __declspec(dllexport)
14# else
15# define EAPI
16# endif /* ! DLL_EXPORT */
17# else
18# define EAPI __declspec(dllimport)
19# endif /* ! EFL_ECORE_IMF_BUILD */
20#else
21# ifdef __GNUC__
22# if __GNUC__ >= 4
23# define EAPI __attribute__ ((visibility("default")))
24# else
25# define EAPI
26# endif
27# else
28# define EAPI
29# endif
30#endif /* ! _WIN32 */
31
32#ifdef __cplusplus
33extern "C" {
34#endif
35
36/**
37 * @addtogroup Ecore_IMF_Context_Group
38 *
39 * @{
40 */
41/* ecore_imf_context_input_panel_event_callback_add() flag */
42typedef enum
43{
44 ECORE_IMF_INPUT_PANEL_STATE_EVENT, /**< called when the state of the input panel is changed. @since 1.7 */
45 ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT, /**< called when the language of the input panel is changed. @since 1.7 */
46 ECORE_IMF_INPUT_PANEL_SHIFT_MODE_EVENT, /**< called when the shift key state of the input panel is changed @since 1.7 */
47 ECORE_IMF_INPUT_PANEL_GEOMETRY_EVENT, /**< called when the size of the input panel is changed. @since 1.7 */
48 ECORE_IMF_CANDIDATE_PANEL_STATE_EVENT, /**< called when the state of the candidate word panel is changed. @since 1.7 */
49 ECORE_IMF_CANDIDATE_PANEL_GEOMETRY_EVENT /**< called when the size of the candidate word panel is changed. @since 1.7 */
50} Ecore_IMF_Input_Panel_Event;
51
52typedef enum
53{
54 ECORE_IMF_INPUT_PANEL_STATE_SHOW, /**< Notification after the display of the input panel @since 1.7 */
55 ECORE_IMF_INPUT_PANEL_STATE_HIDE, /**< Notification prior to the dismissal of the input panel @since 1.7 */
56 ECORE_IMF_INPUT_PANEL_STATE_WILL_SHOW /**< Notification prior to the display of the input panel @since 1.7 */
57} Ecore_IMF_Input_Panel_State;
58
59typedef enum
60{
61 ECORE_IMF_INPUT_PANEL_SHIFT_MODE_OFF, /**< @since 1.7 */
62 ECORE_IMF_INPUT_PANEL_SHIFT_MODE_ON /**< @since 1.7 */
63} Ecore_IMF_Input_Panel_Shift_Mode;
64
65typedef enum
66{
67 ECORE_IMF_CANDIDATE_PANEL_SHOW, /**< Notification after the display of the candidate word panel @since 1.7 */
68 ECORE_IMF_CANDIDATE_PANEL_HIDE /**< Notification prior to the dismissal of the candidate word panel @since 1.7 */
69} Ecore_IMF_Candidate_Panel_State;
70
71/* Events sent by the Input Method */
72typedef struct _Ecore_IMF_Event_Preedit_Start Ecore_IMF_Event_Preedit_Start;
73typedef struct _Ecore_IMF_Event_Preedit_End Ecore_IMF_Event_Preedit_End;
74typedef struct _Ecore_IMF_Event_Preedit_Changed Ecore_IMF_Event_Preedit_Changed;
75typedef struct _Ecore_IMF_Event_Commit Ecore_IMF_Event_Commit;
76typedef struct _Ecore_IMF_Event_Delete_Surrounding Ecore_IMF_Event_Delete_Surrounding;
77
78/* Events to filter */
79typedef struct _Ecore_IMF_Event_Mouse_Down Ecore_IMF_Event_Mouse_Down;
80typedef struct _Ecore_IMF_Event_Mouse_Up Ecore_IMF_Event_Mouse_Up;
81typedef struct _Ecore_IMF_Event_Mouse_In Ecore_IMF_Event_Mouse_In;
82typedef struct _Ecore_IMF_Event_Mouse_Out Ecore_IMF_Event_Mouse_Out;
83typedef struct _Ecore_IMF_Event_Mouse_Move Ecore_IMF_Event_Mouse_Move;
84typedef struct _Ecore_IMF_Event_Mouse_Wheel Ecore_IMF_Event_Mouse_Wheel;
85typedef struct _Ecore_IMF_Event_Key_Down Ecore_IMF_Event_Key_Down;
86typedef struct _Ecore_IMF_Event_Key_Up Ecore_IMF_Event_Key_Up;
87typedef union _Ecore_IMF_Event Ecore_IMF_Event;
88
89typedef struct _Ecore_IMF_Context Ecore_IMF_Context; /**< An Input Method Context */
90typedef struct _Ecore_IMF_Context_Class Ecore_IMF_Context_Class; /**< An Input Method Context class */
91typedef struct _Ecore_IMF_Context_Info Ecore_IMF_Context_Info; /**< An Input Method Context info */
92
93/* Preedit attribute info */
94typedef struct _Ecore_IMF_Preedit_Attr Ecore_IMF_Preedit_Attr;
95
96EAPI extern int ECORE_IMF_EVENT_PREEDIT_START;
97EAPI extern int ECORE_IMF_EVENT_PREEDIT_END;
98EAPI extern int ECORE_IMF_EVENT_PREEDIT_CHANGED;
99EAPI extern int ECORE_IMF_EVENT_COMMIT;
100EAPI extern int ECORE_IMF_EVENT_DELETE_SURROUNDING;
101
102typedef void (*Ecore_IMF_Event_Cb) (void *data, Ecore_IMF_Context *ctx, void *event_info);
103
104/**
105 * @typedef Ecore_IMF_Callback_Type
106 *
107 * Ecore IMF Event callback types.
108 *
109 * @see ecore_imf_context_event_callback_add()
110 */
111typedef enum
112{
113 ECORE_IMF_CALLBACK_PREEDIT_START, /**< "PREEDIT_START" is called when a new preediting sequence starts. @since 1.2 */
114 ECORE_IMF_CALLBACK_PREEDIT_END, /**< "PREEDIT_END" is called when a preediting sequence has been completed or canceled. @since 1.2 */
115 ECORE_IMF_CALLBACK_PREEDIT_CHANGED, /**< "PREEDIT_CHANGED" is called whenever the preedit sequence currently being entered has changed. @since 1.2 */
116 ECORE_IMF_CALLBACK_COMMIT, /**< "COMMIT" is called when a complete input sequence has been entered by the user @since 1.2 */
117 ECORE_IMF_CALLBACK_DELETE_SURROUNDING /**< "DELETE_SURROUNDING" is called when the input method needs to delete all or part of the context surrounding the cursor @since 1.2 */
118} Ecore_IMF_Callback_Type;
119
120/**
121 * @typedef Ecore_IMF_Event_Type
122 *
123 * Ecore IMF event types.
124 *
125 * @see ecore_imf_context_filter_event()
126 */
127typedef enum
128{
129 ECORE_IMF_EVENT_MOUSE_DOWN, /**< Mouse Down event */
130 ECORE_IMF_EVENT_MOUSE_UP, /**< Mouse Up event */
131 ECORE_IMF_EVENT_MOUSE_IN, /**< Mouse In event */
132 ECORE_IMF_EVENT_MOUSE_OUT, /**< Mouse Out event */
133 ECORE_IMF_EVENT_MOUSE_MOVE, /**< Mouse Move event */
134 ECORE_IMF_EVENT_MOUSE_WHEEL, /**< Mouse Wheel event */
135 ECORE_IMF_EVENT_KEY_DOWN, /**< Key Down event */
136 ECORE_IMF_EVENT_KEY_UP /**< Key Up event */
137} Ecore_IMF_Event_Type;
138/**
139 * @typedef Ecore_IMF_Keyboard_Modifiers
140 * Type for Ecore_IMF keyboard modifiers
141 */
142typedef enum
143{
144 ECORE_IMF_KEYBOARD_MODIFIER_NONE = 0, /**< No active modifiers */
145 ECORE_IMF_KEYBOARD_MODIFIER_CTRL = 1 << 0, /**< "Control" is pressed */
146 ECORE_IMF_KEYBOARD_MODIFIER_ALT = 1 << 1, /**< "Alt" is pressed */
147 ECORE_IMF_KEYBOARD_MODIFIER_SHIFT = 1 << 2, /**< "Shift" is pressed */
148 ECORE_IMF_KEYBOARD_MODIFIER_WIN = 1 << 3, /**< "Win" (between "Ctrl" and "Alt") is pressed */
149 ECORE_IMF_KEYBOARD_MODIFIER_ALTGR = 1 << 4 /**< "AltGr" is pressed @since 1.7 */
150} Ecore_IMF_Keyboard_Modifiers;
151
152/**
153 * @typedef Ecore_IMF_Keyboard_Locks
154 * Type for Ecore_IMF keyboard locks
155 */
156typedef enum
157{
158 ECORE_IMF_KEYBOARD_LOCK_NONE = 0, /**< No locks are active */
159 ECORE_IMF_KEYBOARD_LOCK_NUM = 1 << 0, /**< "Num" lock is active */
160 ECORE_IMF_KEYBOARD_LOCK_CAPS = 1 << 1, /**< "Caps" lock is active */
161 ECORE_IMF_KEYBOARD_LOCK_SCROLL = 1 << 2 /**< "Scroll" lock is active */
162} Ecore_IMF_Keyboard_Locks;
163
164/**
165 * @typedef Ecore_IMF_Mouse_Flags
166 * Type for Ecore_IMF mouse flags
167 */
168typedef enum
169{
170 ECORE_IMF_MOUSE_NONE = 0, /**< A single click */
171 ECORE_IMF_MOUSE_DOUBLE_CLICK = 1 << 0, /**< A double click */
172 ECORE_IMF_MOUSE_TRIPLE_CLICK = 1 << 1 /**< A triple click */
173} Ecore_IMF_Mouse_Flags;
174
175typedef enum
176{
177 ECORE_IMF_INPUT_MODE_ALPHA = 1 << 0,
178 ECORE_IMF_INPUT_MODE_NUMERIC = 1 << 1,
179 ECORE_IMF_INPUT_MODE_SPECIAL = 1 << 2,
180 ECORE_IMF_INPUT_MODE_HEXA = 1 << 3,
181 ECORE_IMF_INPUT_MODE_TELE = 1 << 4,
182 ECORE_IMF_INPUT_MODE_FULL = (ECORE_IMF_INPUT_MODE_ALPHA | ECORE_IMF_INPUT_MODE_NUMERIC | ECORE_IMF_INPUT_MODE_SPECIAL),
183 ECORE_IMF_INPUT_MODE_INVISIBLE = 1 << 29,
184 ECORE_IMF_INPUT_MODE_AUTOCAP = 1 << 30
185} Ecore_IMF_Input_Mode;
186
187/**
188 * @typedef Ecore_IMF_Preedit_Type
189 *
190 * Ecore IMF Preedit style types
191 *
192 * @see ecore_imf_context_preedit_string_with_attributes_get()
193 */
194typedef enum
195{
196 ECORE_IMF_PREEDIT_TYPE_NONE, /**< None style @since 1.1 */
197 ECORE_IMF_PREEDIT_TYPE_SUB1, /**< Substring style 1 @since 1.1 */
198 ECORE_IMF_PREEDIT_TYPE_SUB2, /**< Substring style 2 @since 1.1 */
199 ECORE_IMF_PREEDIT_TYPE_SUB3, /**< Substring style 3 @since 1.1 */
200 ECORE_IMF_PREEDIT_TYPE_SUB4, /**< Substring style 4 @since 1.8 */
201 ECORE_IMF_PREEDIT_TYPE_SUB5, /**< Substring style 5 @since 1.8 */
202 ECORE_IMF_PREEDIT_TYPE_SUB6, /**< Substring style 6 @since 1.8 */
203 ECORE_IMF_PREEDIT_TYPE_SUB7 /**< Substring style 7 @since 1.8 */
204} Ecore_IMF_Preedit_Type;
205
206/**
207 * @typedef Ecore_IMF_Autocapital_Type
208 *
209 * Autocapitalization Types.
210 *
211 * @see ecore_imf_context_autocapital_type_set()
212 */
213typedef enum
214{
215 ECORE_IMF_AUTOCAPITAL_TYPE_NONE, /**< No auto-capitalization when typing @since 1.1 */
216 ECORE_IMF_AUTOCAPITAL_TYPE_WORD, /**< Autocapitalize each word typed @since 1.1 */
217 ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE, /**< Autocapitalize the start of each sentence @since 1.1 */
218 ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER, /**< Autocapitalize all letters @since 1.1 */
219} Ecore_IMF_Autocapital_Type;
220
221/**
222 * @typedef Ecore_IMF_Input_Panel_Layout
223 *
224 * Input panel (virtual keyboard) layout types.
225 *
226 * @see ecore_imf_context_input_panel_layout_set()
227 */
228typedef enum
229{
230 ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL, /**< Default layout */
231 ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER, /**< Number layout */
232 ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL, /**< Email layout */
233 ECORE_IMF_INPUT_PANEL_LAYOUT_URL, /**< URL layout */
234 ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER, /**< Phone Number layout */
235 ECORE_IMF_INPUT_PANEL_LAYOUT_IP, /**< IP layout */
236 ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH, /**< Month layout */
237 ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY, /**< Number Only layout */
238 ECORE_IMF_INPUT_PANEL_LAYOUT_INVALID, /**< Never use this */
239 ECORE_IMF_INPUT_PANEL_LAYOUT_HEX, /**< Hexadecimal layout @since 1.2 */
240 ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL, /**< Command-line terminal layout including esc, alt, ctrl key, so on (no auto-correct, no auto-capitalization) @since 1.2 */
241 ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD /**< Like normal, but no auto-correct, no auto-capitalization etc. @since 1.2 */
242} Ecore_IMF_Input_Panel_Layout;
243
244/**
245 * @typedef Ecore_IMF_Input_Panel_Lang
246 *
247 * Input panel (virtual keyboard) language modes.
248 *
249 * @see ecore_imf_context_input_panel_language_set()
250 */
251typedef enum
252{
253 ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC, /**< Automatic @since 1.2 */
254 ECORE_IMF_INPUT_PANEL_LANG_ALPHABET /**< Alphabet @since 1.2 */
255} Ecore_IMF_Input_Panel_Lang;
256
257/**
258 * @typedef Ecore_IMF_Input_Panel_Return_Key_Type
259 *
260 * "Return" Key types on the input panel (virtual keyboard).
261 *
262 * @see ecore_imf_context_input_panel_return_key_type_set()
263 */
264typedef enum
265{
266 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT, /**< Default @since 1.2 */
267 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DONE, /**< Done @since 1.2 */
268 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_GO, /**< Go @since 1.2 */
269 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_JOIN, /**< Join @since 1.2 */
270 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_LOGIN, /**< Login @since 1.2 */
271 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_NEXT, /**< Next @since 1.2 */
272 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEARCH, /**< Search or magnifier icon @since 1.2 */
273 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SEND, /**< Send @since 1.2 */
274 ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_SIGNIN /**< Sign-in @since 1.8 */
275} Ecore_IMF_Input_Panel_Return_Key_Type;
276
277struct _Ecore_IMF_Event_Preedit_Start
278{
279 Ecore_IMF_Context *ctx;
280};
281
282struct _Ecore_IMF_Event_Preedit_End
283{
284 Ecore_IMF_Context *ctx;
285};
286
287struct _Ecore_IMF_Event_Preedit_Changed
288{
289 Ecore_IMF_Context *ctx;
290};
291
292struct _Ecore_IMF_Event_Commit
293{
294 Ecore_IMF_Context *ctx;
295 char *str;
296};
297
298struct _Ecore_IMF_Event_Delete_Surrounding
299{
300 Ecore_IMF_Context *ctx;
301 int offset;
302 int n_chars;
303};
304
305struct _Ecore_IMF_Event_Mouse_Down
306{
307 int button; /**< The button which has been pressed */
308 struct {
309 int x, y;
310 } output;
311 struct {
312 int x, y;
313 } canvas;
314 Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
315 Ecore_IMF_Keyboard_Locks locks; /**< The keyboard locks active when the event has been emitted */
316 Ecore_IMF_Mouse_Flags flags; /**< The flags corresponding the mouse click (single, double or triple click) */
317 unsigned int timestamp; /**< The timestamp when the event occurred */
318};
319
320struct _Ecore_IMF_Event_Mouse_Up
321{
322 int button; /**< The button which has been pressed */
323 struct {
324 int x, y;
325 } output;
326 struct {
327 int x, y;
328 } canvas;
329 Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
330 Ecore_IMF_Keyboard_Locks locks; /**< The keyboard locks active when the event has been emitted */
331 Ecore_IMF_Mouse_Flags flags; /**< The flags corresponding the mouse click (single, double or triple click) */
332 unsigned int timestamp; /**< The timestamp when the event occurred */
333};
334
335struct _Ecore_IMF_Event_Mouse_In
336{
337 int buttons;
338 struct {
339 int x, y;
340 } output;
341 struct {
342 int x, y;
343 } canvas;
344 Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
345 Ecore_IMF_Keyboard_Locks locks; /**< The keyboard locks active when the event has been emitted */
346 unsigned int timestamp; /**< The timestamp when the event occurred */
347};
348
349struct _Ecore_IMF_Event_Mouse_Out
350{
351 int buttons;
352 struct {
353 int x, y;
354 } output;
355 struct {
356 int x, y;
357 } canvas;
358 Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
359 Ecore_IMF_Keyboard_Locks locks; /**< The keyboard locks active when the event has been emitted */
360 unsigned int timestamp; /**< The timestamp when the event occurred */
361};
362
363struct _Ecore_IMF_Event_Mouse_Move
364{
365 int buttons;
366 struct {
367 struct {
368 int x, y;
369 } output;
370 struct {
371 int x, y;
372 } canvas;
373 } cur, prev;
374 Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
375 Ecore_IMF_Keyboard_Locks locks; /**< The keyboard locks active when the event has been emitted */
376 unsigned int timestamp; /**< The timestamp when the event occurred */
377};
378
379struct _Ecore_IMF_Event_Mouse_Wheel
380{
381 int direction; /* 0 = default up/down wheel */
382 int z; /* ...,-2,-1 = down, 1,2,... = up */
383 struct {
384 int x, y;
385 } output;
386 struct {
387 int x, y;
388 } canvas;
389 Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
390 Ecore_IMF_Keyboard_Locks locks; /**< The keyboard locks active when the event has been emitted */
391 unsigned int timestamp; /**< The timestamp when the event occurred */
392};
393
394struct _Ecore_IMF_Event_Key_Down
395{
396 const char *keyname; /**< The string name of the key pressed */
397 Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
398 Ecore_IMF_Keyboard_Locks locks; /**< The keyboard locks active when the event has been emitted */
399 const char *key; /**< The logical key : (eg shift+1 == exclamation) */
400 const char *string; /**< A UTF8 string if this keystroke has produced a visible string to be ADDED */
401 const char *compose; /**< A UTF8 string if this keystroke has modified a string in the middle of being composed - this string replaces the previous one */
402 unsigned int timestamp; /**< The timestamp when the event occurred */
403};
404
405struct _Ecore_IMF_Event_Key_Up
406{
407 const char *keyname; /**< The string name of the key pressed */
408 Ecore_IMF_Keyboard_Modifiers modifiers; /**< The keyboard modifiers active when the event has been emitted */
409 Ecore_IMF_Keyboard_Locks locks; /**< The keyboard locks active when the event has been emitted */
410 const char *key; /**< The logical key : (eg shift+1 == exclamation) */
411 const char *string; /**< A UTF8 string if this keystroke has produced a visible string to be ADDED */
412 const char *compose; /**< A UTF8 string if this keystroke has modified a string in the middle of being composed - this string replaces the previous one */
413 unsigned int timestamp; /**< The timestamp when the event occurred */
414};
415
416union _Ecore_IMF_Event
417{
418 Ecore_IMF_Event_Mouse_Down mouse_down;
419 Ecore_IMF_Event_Mouse_Up mouse_up;
420 Ecore_IMF_Event_Mouse_In mouse_in;
421 Ecore_IMF_Event_Mouse_Out mouse_out;
422 Ecore_IMF_Event_Mouse_Move mouse_move;
423 Ecore_IMF_Event_Mouse_Wheel mouse_wheel;
424 Ecore_IMF_Event_Key_Down key_down;
425 Ecore_IMF_Event_Key_Up key_up;
426};
427
428struct _Ecore_IMF_Preedit_Attr
429{
430 Ecore_IMF_Preedit_Type preedit_type; /**< preedit style type */
431 unsigned int start_index; /**< start index of the range (in bytes) */
432 unsigned int end_index; /**< end index of the range (in bytes) */
433};
434
435struct _Ecore_IMF_Context_Class
436{
437 void (*add) (Ecore_IMF_Context *ctx);
438 void (*del) (Ecore_IMF_Context *ctx);
439 void (*client_window_set) (Ecore_IMF_Context *ctx, void *window);
440 void (*client_canvas_set) (Ecore_IMF_Context *ctx, void *canvas);
441 void (*show) (Ecore_IMF_Context *ctx);
442 void (*hide) (Ecore_IMF_Context *ctx);
443 void (*preedit_string_get) (Ecore_IMF_Context *ctx, char **str, int *cursor_pos);
444 void (*focus_in) (Ecore_IMF_Context *ctx);
445 void (*focus_out) (Ecore_IMF_Context *ctx);
446 void (*reset) (Ecore_IMF_Context *ctx);
447 void (*cursor_position_set) (Ecore_IMF_Context *ctx, int cursor_pos);
448 void (*use_preedit_set) (Ecore_IMF_Context *ctx, Eina_Bool use_preedit);
449 void (*input_mode_set) (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode);
450 Eina_Bool (*filter_event) (Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event);
451 void (*preedit_string_with_attributes_get) (Ecore_IMF_Context *ctx, char **str, Eina_List **attrs, int *cursor_pos);
452 void (*prediction_allow_set)(Ecore_IMF_Context *ctx, Eina_Bool prediction);
453 void (*autocapital_type_set)(Ecore_IMF_Context *ctx, Ecore_IMF_Autocapital_Type autocapital_type);
454 void (*control_panel_show) (Ecore_IMF_Context *ctx);
455 void (*control_panel_hide) (Ecore_IMF_Context *ctx);
456 void (*input_panel_layout_set) (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Layout layout);
457 Ecore_IMF_Input_Panel_Layout (*input_panel_layout_get) (Ecore_IMF_Context *ctx);
458 void (*input_panel_language_set) (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Lang lang);
459 Ecore_IMF_Input_Panel_Lang (*input_panel_language_get) (Ecore_IMF_Context *ctx);
460 void (*cursor_location_set) (Ecore_IMF_Context *ctx, int x, int y, int w, int h);
461 void (*input_panel_imdata_set)(Ecore_IMF_Context *ctx, const void* data, int len);
462 void (*input_panel_imdata_get)(Ecore_IMF_Context *ctx, void* data, int *len);
463 void (*input_panel_return_key_type_set) (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Return_Key_Type return_key_type);
464 void (*input_panel_return_key_disabled_set) (Ecore_IMF_Context *ctx, Eina_Bool disabled);
465 void (*input_panel_caps_lock_mode_set) (Ecore_IMF_Context *ctx, Eina_Bool mode);
466 void (*input_panel_geometry_get)(Ecore_IMF_Context *ctx, int *x, int *y, int *w, int *h);
467 Ecore_IMF_Input_Panel_State (*input_panel_state_get) (Ecore_IMF_Context *ctx);
468 void (*input_panel_event_callback_add) (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Event type, void (*func) (void *data, Ecore_IMF_Context *ctx, int value), void *data);
469 void (*input_panel_event_callback_del) (Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Event type, void (*func) (void *data, Ecore_IMF_Context *ctx, int value));
470 void (*input_panel_language_locale_get) (Ecore_IMF_Context *ctx, char **lang);
471 void (*candidate_panel_geometry_get)(Ecore_IMF_Context *ctx, int *x, int *y, int *w, int *h);
472};
473
474struct _Ecore_IMF_Context_Info
475{
476 const char *id; /* ID */
477 const char *description; /* Human readable description */
478 const char *default_locales; /* Languages for which this context is the default, separated by : */
479 const char *canvas_type; /* The canvas type used by the input method. Eg.: evas */
480 int canvas_required; /* Whether the canvas usage is required for this input method */
481};
482
483/**
484 * @}
485 */
486
487EAPI int ecore_imf_init(void);
488EAPI int ecore_imf_shutdown(void);
489
490EAPI void ecore_imf_module_register(const Ecore_IMF_Context_Info *info, Ecore_IMF_Context *(*imf_module_create)(void), Ecore_IMF_Context *(*imf_module_exit)(void));
491
492EAPI Eina_List *ecore_imf_context_available_ids_get(void);
493EAPI Eina_List *ecore_imf_context_available_ids_by_canvas_type_get(const char *canvas_type);
494EAPI const char *ecore_imf_context_default_id_get(void);
495EAPI const char *ecore_imf_context_default_id_by_canvas_type_get(const char *canvas_type);
496EAPI const Ecore_IMF_Context_Info *ecore_imf_context_info_by_id_get(const char *id);
497
498EAPI Ecore_IMF_Context *ecore_imf_context_add(const char *id);
499EAPI const Ecore_IMF_Context_Info *ecore_imf_context_info_get(Ecore_IMF_Context *ctx);
500EAPI void ecore_imf_context_del(Ecore_IMF_Context *ctx);
501EAPI void ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window);
502EAPI void *ecore_imf_context_client_window_get(Ecore_IMF_Context *ctx);
503EAPI void ecore_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas);
504EAPI void *ecore_imf_context_client_canvas_get(Ecore_IMF_Context *ctx);
505EAPI void ecore_imf_context_show(Ecore_IMF_Context *ctx);
506EAPI void ecore_imf_context_hide(Ecore_IMF_Context *ctx);
507EAPI void ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos);
508EAPI void ecore_imf_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx, char **str, Eina_List **attrs, int *cursor_pos);
509EAPI void ecore_imf_context_focus_in(Ecore_IMF_Context *ctx);
510EAPI void ecore_imf_context_focus_out(Ecore_IMF_Context *ctx);
511EAPI void ecore_imf_context_reset(Ecore_IMF_Context *ctx);
512EAPI void ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos);
513EAPI void ecore_imf_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int w, int h);
514EAPI void ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, Eina_Bool use_preedit);
515EAPI void ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, Eina_Bool (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data);
516EAPI void ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode);
517EAPI Ecore_IMF_Input_Mode ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx);
518EAPI Eina_Bool ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event);
519
520/* plugin specific functions */
521EAPI Ecore_IMF_Context *ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc);
522EAPI void ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data);
523EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx);
524EAPI Eina_Bool ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos);
525EAPI void ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx);
526EAPI void ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx);
527EAPI void ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx);
528EAPI void ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str);
529EAPI void ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars);
530EAPI void ecore_imf_context_event_callback_add(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func, const void *data);
531EAPI void *ecore_imf_context_event_callback_del(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func);
532EAPI void ecore_imf_context_event_callback_call(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, void *event_info);
533EAPI void ecore_imf_context_prediction_allow_set(Ecore_IMF_Context *ctx, Eina_Bool prediction);
534EAPI Eina_Bool ecore_imf_context_prediction_allow_get(Ecore_IMF_Context *ctx);
535EAPI void ecore_imf_context_autocapital_type_set(Ecore_IMF_Context *ctx, Ecore_IMF_Autocapital_Type autocapital_type);
536EAPI Ecore_IMF_Autocapital_Type ecore_imf_context_autocapital_type_get(Ecore_IMF_Context *ctx);
537
538EAPI void ecore_imf_context_control_panel_show(Ecore_IMF_Context *ctx);
539EAPI void ecore_imf_context_control_panel_hide(Ecore_IMF_Context *ctx);
540
541EAPI void ecore_imf_context_input_panel_show(Ecore_IMF_Context *ctx);
542EAPI void ecore_imf_context_input_panel_hide(Ecore_IMF_Context *ctx);
543EAPI void ecore_imf_context_input_panel_layout_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Layout layout);
544EAPI Ecore_IMF_Input_Panel_Layout ecore_imf_context_input_panel_layout_get(Ecore_IMF_Context *ctx);
545EAPI void ecore_imf_context_input_panel_language_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Lang lang);
546EAPI Ecore_IMF_Input_Panel_Lang ecore_imf_context_input_panel_language_get(Ecore_IMF_Context *ctx);
547EAPI void ecore_imf_context_input_panel_enabled_set(Ecore_IMF_Context *ctx, Eina_Bool enable);
548EAPI Eina_Bool ecore_imf_context_input_panel_enabled_get(Ecore_IMF_Context *ctx);
549EAPI void ecore_imf_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int len);
550EAPI void ecore_imf_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *len);
551EAPI void ecore_imf_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Return_Key_Type return_key_type);
552EAPI Ecore_IMF_Input_Panel_Return_Key_Type ecore_imf_context_input_panel_return_key_type_get(Ecore_IMF_Context *ctx);
553EAPI void ecore_imf_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx, Eina_Bool disabled);
554EAPI Eina_Bool ecore_imf_context_input_panel_return_key_disabled_get(Ecore_IMF_Context *ctx);
555EAPI void ecore_imf_context_input_panel_caps_lock_mode_set(Ecore_IMF_Context *ctx, Eina_Bool mode);
556EAPI Eina_Bool ecore_imf_context_input_panel_caps_lock_mode_get(Ecore_IMF_Context *ctx);
557EAPI void ecore_imf_context_input_panel_geometry_get(Ecore_IMF_Context *ctx, int *x, int *y, int *w, int *h);
558EAPI Ecore_IMF_Input_Panel_State ecore_imf_context_input_panel_state_get(Ecore_IMF_Context *ctx);
559EAPI void ecore_imf_context_input_panel_event_callback_add(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Event type, void (*func) (void *data, Ecore_IMF_Context *ctx, int value), const void *data);
560EAPI void ecore_imf_context_input_panel_event_callback_del(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Event type, void (*func) (void *data, Ecore_IMF_Context *ctx, int value));
561EAPI void ecore_imf_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx, char **lang);
562EAPI void ecore_imf_context_candidate_panel_geometry_get(Ecore_IMF_Context *ctx, int *x, int *y, int *w, int *h);
563
564/* The following entry points must be exported by each input method module
565 */
566
567/*
568 * int imf_module_init (const Ecore_IMF_Context_Info **info);
569 * void imf_module_exit (void);
570 * Ecore_IMF_Context *imf_module_create (void);
571 */
572
573#ifdef __cplusplus
574}
575#endif
576
577#endif
diff --git a/src/lib/ecore_imf/Ecore_IMF_Evas.h b/src/lib/ecore_imf/Ecore_IMF_Evas.h
new file mode 100644
index 0000000000..5f7cdb90f3
--- /dev/null
+++ b/src/lib/ecore_imf/Ecore_IMF_Evas.h
@@ -0,0 +1,50 @@
1#ifndef _ECORE_IMF_EVAS_H
2#define _ECORE_IMF_EVAS_H
3
4#include <Ecore_IMF.h>
5#include <Evas.h>
6
7#ifdef EAPI
8# undef EAPI
9#endif
10
11#ifdef _WIN32
12# ifdef EFL_ECORE_IMF_EVAS_BUILD
13# ifdef DLL_EXPORT
14# define EAPI __declspec(dllexport)
15# else
16# define EAPI
17# endif /* ! DLL_EXPORT */
18# else
19# define EAPI __declspec(dllimport)
20# endif /* ! EFL_ECORE_IMF_BUILD */
21#else
22# ifdef __GNUC__
23# if __GNUC__ >= 4
24# define EAPI __attribute__ ((visibility("default")))
25# else
26# define EAPI
27# endif
28# else
29# define EAPI
30# endif
31#endif /* ! _WIN32 */
32
33#ifdef __cplusplus
34extern "C" {
35#endif
36
37EAPI void ecore_imf_evas_event_mouse_in_wrap(Evas_Event_Mouse_In *evas_event, Ecore_IMF_Event_Mouse_In *imf_event);
38EAPI void ecore_imf_evas_event_mouse_out_wrap(Evas_Event_Mouse_Out *evas_event, Ecore_IMF_Event_Mouse_Out *imf_event);
39EAPI void ecore_imf_evas_event_mouse_move_wrap(Evas_Event_Mouse_Move *evas_event, Ecore_IMF_Event_Mouse_Move *imf_event);
40EAPI void ecore_imf_evas_event_mouse_down_wrap(Evas_Event_Mouse_Down *evas_event, Ecore_IMF_Event_Mouse_Down *imf_event);
41EAPI void ecore_imf_evas_event_mouse_up_wrap(Evas_Event_Mouse_Up *evas_event, Ecore_IMF_Event_Mouse_Up *imf_event);
42EAPI void ecore_imf_evas_event_mouse_wheel_wrap(Evas_Event_Mouse_Wheel *evas_event, Ecore_IMF_Event_Mouse_Wheel *imf_event);
43EAPI void ecore_imf_evas_event_key_down_wrap(Evas_Event_Key_Down *evas_event, Ecore_IMF_Event_Key_Down *imf_event);
44EAPI void ecore_imf_evas_event_key_up_wrap(Evas_Event_Key_Up *evas_event, Ecore_IMF_Event_Key_Up *imf_event);
45
46#ifdef __cplusplus
47}
48#endif
49
50#endif
diff --git a/src/lib/ecore_imf/ecore_imf.c b/src/lib/ecore_imf/ecore_imf.c
new file mode 100644
index 0000000000..7cf8a4a9f6
--- /dev/null
+++ b/src/lib/ecore_imf/ecore_imf.c
@@ -0,0 +1,73 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <Ecore.h>
6#include <ecore_private.h>
7
8#include "Ecore_IMF.h"
9#include "ecore_imf_private.h"
10
11EAPI int ECORE_IMF_EVENT_PREEDIT_START = 0;
12EAPI int ECORE_IMF_EVENT_PREEDIT_END = 0;
13EAPI int ECORE_IMF_EVENT_PREEDIT_CHANGED = 0;
14EAPI int ECORE_IMF_EVENT_COMMIT = 0;
15EAPI int ECORE_IMF_EVENT_DELETE_SURROUNDING = 0;
16
17int _ecore_imf_log_dom = -1;
18static int _ecore_imf_init_count = 0;
19
20/**
21 * @defgroup Ecore_IMF_Lib_Group Ecore Input Method Library Functions
22 *
23 * Utility functions that set up and shut down the Ecore Input Method
24 * library.
25 */
26
27/**
28 * Initialises the Ecore_IMF library.
29 * @return Number of times the library has been initialised without being
30 * shut down.
31 * @ingroup Ecore_IMF_Lib_Group
32 */
33EAPI int
34ecore_imf_init(void)
35{
36 if (++_ecore_imf_init_count != 1) return _ecore_imf_init_count;
37
38 if (!ecore_init()) return --_ecore_imf_init_count;
39 _ecore_imf_log_dom = eina_log_domain_register
40 ("ecore_imf", ECORE_IMF_DEFAULT_LOG_COLOR);
41 if (_ecore_imf_log_dom < 0)
42 {
43 EINA_LOG_ERR("Impossible to create a log domain for the Ecore IMF module.");
44 ecore_shutdown();
45 return --_ecore_imf_init_count;
46 }
47 ecore_imf_module_init();
48
49 ECORE_IMF_EVENT_PREEDIT_START = ecore_event_type_new();
50 ECORE_IMF_EVENT_PREEDIT_END = ecore_event_type_new();
51 ECORE_IMF_EVENT_PREEDIT_CHANGED = ecore_event_type_new();
52 ECORE_IMF_EVENT_COMMIT = ecore_event_type_new();
53 ECORE_IMF_EVENT_DELETE_SURROUNDING = ecore_event_type_new();
54
55 return _ecore_imf_init_count;
56}
57
58/**
59 * Shuts down the Ecore_IMF library.
60 * @return Number of times the library has been initialised without being
61 * shut down.
62 * @ingroup Ecore_IMF_Lib_Group
63 */
64EAPI int
65ecore_imf_shutdown(void)
66{
67 if (--_ecore_imf_init_count != 0) return _ecore_imf_init_count;
68 ecore_imf_module_shutdown();
69 eina_log_domain_unregister(_ecore_imf_log_dom);
70 _ecore_imf_log_dom = -1;
71 ecore_shutdown();
72 return _ecore_imf_init_count;
73}
diff --git a/src/lib/ecore_imf/ecore_imf_context.c b/src/lib/ecore_imf/ecore_imf_context.c
new file mode 100644
index 0000000000..3faa5acbd5
--- /dev/null
+++ b/src/lib/ecore_imf/ecore_imf_context.c
@@ -0,0 +1,1900 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdlib.h>
6#include <string.h>
7#include <locale.h>
8
9#include <Ecore.h>
10#include <ecore_private.h>
11
12#include "Ecore_IMF.h"
13#include "ecore_imf_private.h"
14
15/**
16 * @defgroup Ecore_IMF_Context_Group Ecore Input Method Context Functions
17 *
18 * Functions that operate on Ecore Input Method Context objects.
19
20 * Ecore Input Method Context Function defines the interface for EFL input methods.
21 * An input method is used by EFL text input widgets like elm_entry
22 * (based on edje_entry) to map from key events to Unicode character strings.
23 *
24 * The default input method can be set through setting the ECORE_IMF_MODULE environment variable.
25 *
26 * An input method may consume multiple key events in sequence and finally output the composed result.
27 * This is called preediting, and an input method may provide feedback about
28 * this process by displaying the intermediate composition states as preedit text.
29 *
30 * Immodule is plugin to connect your application and input method framework such as SCIM, ibus, and so on.@n
31 * ecore_imf_init() should be called to initialize and load immodule.@n
32 * ecore_imf_shutdown() is used for shutdowning and unloading immodule.
33 *
34 * An example of usage of these functions can be found at:
35 * @li @ref ecore_imf_example_c
36 */
37
38/**
39 * Get the list of the available Input Method Context ids.
40 *
41 * Note that the caller is responsible for freeing the Eina_List
42 * when finished with it. There is no need to finish the list strings.
43 *
44 * @return Return an Eina_List of strings;
45 * on failure it returns NULL.
46 * @ingroup Ecore_IMF_Context_Group
47 */
48EAPI Eina_List *
49ecore_imf_context_available_ids_get(void)
50{
51 return ecore_imf_module_context_ids_get();
52}
53
54EAPI Eina_List *
55ecore_imf_context_available_ids_by_canvas_type_get(const char *canvas_type)
56{
57 return ecore_imf_module_context_ids_by_canvas_type_get(canvas_type);
58}
59
60/*
61 * Match @locale against @against.
62 *
63 * 'en_US' against 'en_US' => 4
64 * 'en_US' against 'en' => 3
65 * 'en', 'en_UK' against 'en_US' => 2
66 * all locales, against '*' => 1
67 */
68static int
69_ecore_imf_context_match_locale(const char *locale, const char *against, int against_len)
70{
71 if (strcmp(against, "*") == 0)
72 return 1;
73
74 if (strcasecmp(locale, against) == 0)
75 return 4;
76
77 if (strncasecmp(locale, against, 2) == 0)
78 return (against_len == 2) ? 3 : 2;
79
80 return 0;
81}
82
83/**
84 * Get the id of the default Input Method Context.
85 * The id may to used to create a new instance of an Input Method
86 * Context object.
87 *
88 * @return Return a string containing the id of the default Input
89 * Method Context; on failure it returns NULL.
90 * @ingroup Ecore_IMF_Context_Group
91 */
92EAPI const char *
93ecore_imf_context_default_id_get(void)
94{
95 return ecore_imf_context_default_id_by_canvas_type_get(NULL);
96}
97
98EAPI const char *
99ecore_imf_context_default_id_by_canvas_type_get(const char *canvas_type)
100{
101 const char *id;
102 Eina_List *modules;
103 Ecore_IMF_Module *module;
104 char *locale;
105 char *tmp;
106 int best_goodness = 0;
107
108 id = getenv("ECORE_IMF_MODULE");
109 if (id)
110 {
111 if (strcmp(id, "none") == 0) return NULL;
112 if (ecore_imf_module_get(id)) return id;
113 }
114
115 modules = ecore_imf_module_available_get();
116 if (!modules) return NULL;
117
118 locale = setlocale(LC_CTYPE, NULL);
119 if (!locale) return NULL;
120
121 locale = strdup(locale);
122
123 tmp = strchr(locale, '.');
124 if (tmp) *tmp = '\0';
125 tmp = strchr(locale, '@');
126 if (tmp) *tmp = '\0';
127
128 id = NULL;
129
130 EINA_LIST_FREE(modules, module)
131 {
132 if (canvas_type &&
133 strcmp(module->info->canvas_type, canvas_type) == 0)
134 continue;
135
136 const char *p = module->info->default_locales;
137 while (p)
138 {
139 const char *q = strchr(p, ':');
140 int goodness = _ecore_imf_context_match_locale(locale, p, q ? (size_t)(q - p) : strlen (p));
141
142 if (goodness > best_goodness)
143 {
144 id = module->info->id;
145 best_goodness = goodness;
146 }
147
148 p = q ? q + 1 : NULL;
149 }
150 }
151
152 free(locale);
153 return id;
154}
155
156/**
157 * Retrieve the info for the Input Method Context with @p id.
158 *
159 * @param id The Input Method Context id to query for.
160 * @return Return a #Ecore_IMF_Context_Info for the Input Method Context with @p id;
161 * on failure it returns NULL.
162 * @ingroup Ecore_IMF_Context_Group
163 *
164 * Example
165 * @code
166 *
167 * const char *ctx_id;
168 * const Ecore_IMF_Context_Info *ctx_info;
169 * Ecore_IMF_Context *imf_context;
170 * ctx_id = ecore_imf_context_default_id_get();
171 * if (ctx_id)
172 * {
173 * ctx_info = ecore_imf_context_info_by_id_get(ctx_id);
174 * if (!ctx_info->canvas_type ||
175 * strcmp(ctx_info->canvas_type, "evas") == 0)
176 * {
177 * imf_context = ecore_imf_context_add(ctx_id);
178 * }
179 * else
180 * {
181 * ctx_id = ecore_imf_context_default_id_by_canvas_type_get("evas");
182 * if (ctx_id)
183 * {
184 * imf_context = ecore_imf_context_add(ctx_id);
185 * }
186 * }
187 * }
188 * @endcode
189 */
190EAPI const Ecore_IMF_Context_Info *
191ecore_imf_context_info_by_id_get(const char *id)
192{
193 Ecore_IMF_Module *module;
194
195 if (!id) return NULL;
196 module = ecore_imf_module_get(id);
197 if (!module) return NULL;
198 return module->info;
199}
200
201/**
202 * Create a new Input Method Context defined by the given id.
203 *
204 * @param id The Input Method Context id.
205 * @return A newly allocated Input Method Context;
206 * on failure it returns NULL.
207 * @ingroup Ecore_IMF_Context_Group
208 */
209EAPI Ecore_IMF_Context *
210ecore_imf_context_add(const char *id)
211{
212 Ecore_IMF_Context *ctx;
213
214 if (!id) return NULL;
215 ctx = ecore_imf_module_context_create(id);
216 if (!ctx || !ctx->klass) return NULL;
217 if (ctx->klass->add) ctx->klass->add(ctx);
218 /* default use_preedit is EINA_TRUE, so let's make sure it's
219 * set on the immodule */
220 ecore_imf_context_use_preedit_set(ctx, EINA_TRUE);
221
222 /* default prediction is EINA_TRUE, so let's make sure it's
223 * set on the immodule */
224 ecore_imf_context_prediction_allow_set(ctx, EINA_TRUE);
225
226 /* default autocapital type is SENTENCE type, so let's make sure it's
227 * set on the immodule */
228 ecore_imf_context_autocapital_type_set(ctx, ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE);
229
230 /* default input panel enabled status is EINA_TRUE, so let's make sure it's
231 * set on the immodule */
232 ecore_imf_context_input_panel_enabled_set(ctx, EINA_TRUE);
233
234 /* default input panel layout type is NORMAL type, so let's make sure it's
235 * set on the immodule */
236 ecore_imf_context_input_panel_layout_set(ctx, ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL);
237
238 /* default input_mode is ECORE_IMF_INPUT_MODE_FULL, so let's make sure it's
239 * set on the immodule */
240 ecore_imf_context_input_mode_set(ctx, ECORE_IMF_INPUT_MODE_FULL);
241 return ctx;
242}
243
244/**
245 * Retrieve the info for the given Input Method Context.
246 *
247 * @param ctx An #Ecore_IMF_Context.
248 * @return Return a #Ecore_IMF_Context_Info for the given Input Method Context;
249 * on failure it returns NULL.
250 * @ingroup Ecore_IMF_Context_Group
251 */
252EAPI const Ecore_IMF_Context_Info *
253ecore_imf_context_info_get(Ecore_IMF_Context *ctx)
254{
255 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
256 {
257 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
258 "ecore_imf_context_info_get");
259 return NULL;
260 }
261 return ctx->module->info;
262}
263
264/**
265 * Delete the given Input Method Context and free its memory.
266 *
267 * @param ctx An #Ecore_IMF_Context.
268 * @ingroup Ecore_IMF_Context_Group
269 */
270EAPI void
271ecore_imf_context_del(Ecore_IMF_Context *ctx)
272{
273 Ecore_IMF_Func_Node *fn;
274
275 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
276 {
277 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
278 "ecore_imf_context_del");
279 return;
280 }
281 if (ctx->klass->del) ctx->klass->del(ctx);
282
283 if (ctx->callbacks)
284 {
285 EINA_LIST_FREE(ctx->callbacks, fn)
286 free(fn);
287 }
288
289 ECORE_MAGIC_SET(ctx, ECORE_MAGIC_NONE);
290 free(ctx);
291}
292
293/**
294 * Set the client window for the Input Method Context; this is the
295 * Ecore_X_Window when using X11, Ecore_Win32_Window when using Win32, etc.
296 * This window is used in order to correctly position status windows, and may
297 * also be used for purposes internal to the Input Method Context.
298 *
299 * @param ctx An #Ecore_IMF_Context.
300 * @param window The client window. This may be @c NULL to indicate
301 * that the previous client window no longer exists.
302 * @ingroup Ecore_IMF_Context_Group
303 */
304EAPI void
305ecore_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
306{
307 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
308 {
309 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
310 "ecore_imf_context_client_window_set");
311 return;
312 }
313 if (ctx->klass->client_window_set) ctx->klass->client_window_set(ctx, window);
314 ctx->window = window;
315}
316
317/**
318 * Get the client window of the Input Method Context
319 *
320 * See @ref ecore_imf_context_client_window_set for more details.
321 *
322 * @param ctx An #Ecore_IMF_Context.
323 * @return Return the client window.
324 * @ingroup Ecore_IMF_Context_Group
325 * @since 1.1.0
326 */
327EAPI void *
328ecore_imf_context_client_window_get(Ecore_IMF_Context *ctx)
329{
330 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
331 {
332 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
333 "ecore_imf_context_client_window_get");
334 return NULL;
335 }
336 return ctx->window;
337}
338
339/**
340 * Set the client canvas for the Input Method Context; this is the
341 * canvas in which the input appears.
342 * The canvas type can be determined by using the context canvas type.
343 * Actually only canvas with type "evas" (Evas *) is supported.
344 * This canvas may be used in order to correctly position status windows, and may
345 * also be used for purposes internal to the Input Method Context.
346 *
347 * @param ctx An #Ecore_IMF_Context.
348 * @param canvas The client canvas. This may be @c NULL to indicate
349 * that the previous client canvas no longer exists.
350 * @ingroup Ecore_IMF_Context_Group
351 */
352EAPI void
353ecore_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
354{
355 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
356 {
357 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
358 "ecore_imf_context_client_canvas_set");
359 return;
360 }
361 if (ctx->klass->client_canvas_set) ctx->klass->client_canvas_set(ctx, canvas);
362 ctx->client_canvas = canvas;
363}
364
365/**
366 * Get the client canvas of the Input Method Context.
367 *
368 * See @ref ecore_imf_context_client_canvas_set for more details.
369 *
370 * @param ctx An #Ecore_IMF_Context.
371 * @return Return the client canvas.
372 * @ingroup Ecore_IMF_Context_Group
373 * @since 1.1.0
374 */
375EAPI void *
376ecore_imf_context_client_canvas_get(Ecore_IMF_Context *ctx)
377{
378 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
379 {
380 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
381 "ecore_imf_context_client_canvas_get");
382 return NULL;
383 }
384 return ctx->client_canvas;
385}
386
387/**
388 * Ask the Input Method Context to show itself.
389 *
390 * @param ctx An #Ecore_IMF_Context.
391 * @ingroup Ecore_IMF_Context_Group
392 */
393EAPI void
394ecore_imf_context_show(Ecore_IMF_Context *ctx)
395{
396 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
397 {
398 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
399 "ecore_imf_context_show");
400 return;
401 }
402 if (ctx->klass->show) ctx->klass->show(ctx);
403}
404
405/**
406 * Ask the Input Method Context to hide itself.
407 *
408 * @param ctx An #Ecore_IMF_Context.
409 * @ingroup Ecore_IMF_Context_Group
410 */
411EAPI void
412ecore_imf_context_hide(Ecore_IMF_Context *ctx)
413{
414 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
415 {
416 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
417 "ecore_imf_context_hide");
418 return;
419 }
420 if (ctx->klass->hide) ctx->klass->hide(ctx);
421}
422
423/**
424 * Retrieve the current preedit string and cursor position
425 * for the Input Method Context.
426 *
427 * @param ctx An #Ecore_IMF_Context.
428 * @param str Location to store the retrieved string. The
429 * string retrieved must be freed with free().
430 * @param cursor_pos Location to store position of cursor (in characters)
431 * within the preedit string.
432 * @ingroup Ecore_IMF_Context_Group
433 */
434EAPI void
435ecore_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char **str, int *cursor_pos)
436{
437 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
438 {
439 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
440 "ecore_imf_context_preedit_string_get");
441 return;
442 }
443 if (ctx->klass->preedit_string_get)
444 ctx->klass->preedit_string_get(ctx, str, cursor_pos);
445 else
446 {
447 if (str) *str = strdup("");
448 if (cursor_pos) *cursor_pos = 0;
449 }
450}
451
452/**
453 * Retrieve the current preedit string, attributes and
454 * cursor position for the Input Method Context.
455 *
456 * @param ctx An #Ecore_IMF_Context.
457 * @param str Location to store the retrieved string. The
458 * string retrieved must be freed with free().
459 * @param attrs an Eina_List of attributes
460 * @param cursor_pos Location to store position of cursor (in characters)
461 * within the preedit string.
462 * @ingroup Ecore_IMF_Context_Group
463 *
464 * Example
465 * @code
466 * char *preedit_string;
467 * int cursor_pos;
468 * Eina_List *attrs = NULL, *l = NULL;
469 * Ecore_IMF_Preedit_Attr *attr;
470 *
471 * ecore_imf_context_preedit_string_with_attributes_get(imf_context,
472 * &preedit_string,
473 * &attrs, &cursor_pos);
474 * if (!preedit_string) return;
475 *
476 * if (strlen(preedit_string) > 0)
477 * {
478 * if (attrs)
479 * {
480 * EINA_LIST_FOREACH(attrs, l, attr)
481 * {
482 * if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB1)
483 * {
484 * // Something to do
485 * }
486 * else if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB2)
487 * {
488 * // Something to do
489 * }
490 * else if (attr->preedit_type == ECORE_IMF_PREEDIT_TYPE_SUB3)
491 * {
492 * // Something to do
493 * }
494 * }
495 * }
496 * }
497 *
498 * // delete attribute list
499 * EINA_LIST_FREE(attrs, attr) free(attr);
500 *
501 * free(preedit_string);
502 * @endcode
503 * @since 1.1.0
504 */
505EAPI void
506ecore_imf_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx, char **str, Eina_List **attrs, int *cursor_pos)
507{
508 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
509 {
510 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
511 "ecore_imf_context_preedit_string_with_attributes_get");
512 return;
513 }
514 if (ctx->klass->preedit_string_with_attributes_get)
515 ctx->klass->preedit_string_with_attributes_get(ctx, str, attrs, cursor_pos);
516 else
517 {
518 if (str) *str = strdup("");
519 if (attrs) *attrs = NULL;
520 if (cursor_pos) *cursor_pos = 0;
521 }
522}
523
524/**
525 * Notify the Input Method Context that the widget to which its
526 * correspond has gained focus.
527 *
528 * @param ctx An #Ecore_IMF_Context.
529 * @ingroup Ecore_IMF_Context_Group
530 *
531 * Example
532 * @code
533 * static void
534 * _focus_in_cb(void *data, Evas_Object *o, const char *emission, const char *source)
535 * {
536 * ecore_imf_context_reset(imf_context);
537 * ecore_imf_context_focus_in(imf_context);
538 * }
539 *
540 * evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_IN, _focus_in_cb, ed);
541 * @endcode
542 */
543EAPI void
544ecore_imf_context_focus_in(Ecore_IMF_Context *ctx)
545{
546 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
547 {
548 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
549 "ecore_imf_context_focus_in");
550 return;
551 }
552 if (ctx->klass->focus_in) ctx->klass->focus_in(ctx);
553}
554
555/**
556 * Notify the Input Method Context that the widget to which its
557 * correspond has lost focus.
558 *
559 * @param ctx An #Ecore_IMF_Context.
560 * @ingroup Ecore_IMF_Context_Group
561 *
562 * Example
563 * @code
564 * static void
565 * _focus_out_cb(void *data, Evas_Object *o, const char *emission, const char *source)
566 * {
567 * ecore_imf_context_reset(imf_context);
568 * ecore_imf_context_focus_out(imf_context);
569 * }
570 *
571 * evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _focus_out_cb, ed);
572 * @endcode
573 */
574EAPI void
575ecore_imf_context_focus_out(Ecore_IMF_Context *ctx)
576{
577 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
578 {
579 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
580 "ecore_imf_context_focus_out");
581 return;
582 }
583 if (ctx->klass->focus_out) ctx->klass->focus_out(ctx);
584}
585
586/**
587 * Notify the Input Method Context that a change such as a
588 * change in cursor position has been made. This will typically
589 * cause the Input Method Context to clear the preedit state.
590 *
591 * @param ctx An #Ecore_IMF_Context.
592 * @ingroup Ecore_IMF_Context_Group
593 *
594 * Example
595 * @code
596 * static void
597 * _focus_out_cb(void *data, Evas_Object *o, const char *emission, const char *source)
598 * {
599 * ecore_imf_context_reset(imf_context);
600 * ecore_imf_context_focus_out(imf_context);
601 * }
602 *
603 * evas_object_event_callback_add(obj, EVAS_CALLBACK_FOCUS_OUT, _focus_out_cb, ed);
604 * @endcode
605 */
606EAPI void
607ecore_imf_context_reset(Ecore_IMF_Context *ctx)
608{
609 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
610 {
611 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
612 "ecore_imf_context_reset");
613 return;
614 }
615 if (ctx->klass->reset) ctx->klass->reset(ctx);
616}
617
618/**
619 * Notify the Input Method Context that a change in the cursor
620 * position has been made.
621 *
622 * @param ctx An #Ecore_IMF_Context.
623 * @param cursor_pos New cursor position in characters.
624 * @ingroup Ecore_IMF_Context_Group
625 */
626EAPI void
627ecore_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
628{
629 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
630 {
631 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
632 "ecore_imf_context_cursor_position_set");
633 return;
634 }
635 if (ctx->klass->cursor_position_set) ctx->klass->cursor_position_set(ctx, cursor_pos);
636}
637
638/**
639 * Notify the Input Method Context that a change in the cursor
640 * location has been made. The location is relative to the canvas.
641 * The cursor location can be used to determine the position of
642 * candidate word window in the immodule.
643 *
644 * @param ctx An #Ecore_IMF_Context.
645 * @param x cursor x position.
646 * @param y cursor y position.
647 * @param w cursor width.
648 * @param h cursor height.
649 * @ingroup Ecore_IMF_Context_Group
650 * @since 1.1.0
651 */
652EAPI void
653ecore_imf_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int w, int h)
654{
655 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
656 {
657 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
658 "ecore_imf_context_cursor_location_set");
659 return;
660 }
661 if (ctx->klass->cursor_location_set) ctx->klass->cursor_location_set(ctx, x, y, w, h);
662}
663
664/**
665 * Set whether the IM context should use the preedit string
666 * to display feedback. If @c use_preedit is @c EINA_FALSE (default
667 * is @c EINA_TRUE), then the IM context may use some other method to display
668 * feedback, such as displaying it in a child of the root window.
669 *
670 * @param ctx An #Ecore_IMF_Context.
671 * @param use_preedit Whether the IM context should use the preedit string.
672 * @ingroup Ecore_IMF_Context_Group
673 */
674EAPI void
675ecore_imf_context_use_preedit_set(Ecore_IMF_Context *ctx, Eina_Bool use_preedit)
676{
677 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
678 {
679 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
680 "ecore_imf_context_use_preedit_set");
681 return;
682 }
683 if (ctx->klass->use_preedit_set) ctx->klass->use_preedit_set(ctx, use_preedit);
684}
685
686/**
687 * Set whether the IM context should allow to use the text prediction.
688 * If @p prediction is @c EINA_FALSE (default is @c EINA_TRUE), then the IM
689 * context will not display the text prediction window.
690 *
691 * @param ctx An #Ecore_IMF_Context.
692 * @param prediction Whether the IM context should allow to use the text prediction.
693 * @note Default value is EINA_TRUE.
694 * @ingroup Ecore_IMF_Context_Group
695 * @since 1.1.0
696 */
697EAPI void
698ecore_imf_context_prediction_allow_set(Ecore_IMF_Context *ctx, Eina_Bool prediction)
699{
700 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
701 {
702 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
703 "ecore_imf_context_prediction_allow_set");
704 return;
705 }
706
707 ctx->allow_prediction = prediction;
708
709 if (ctx->klass->prediction_allow_set)
710 ctx->klass->prediction_allow_set(ctx, prediction);
711}
712
713/**
714 * Get whether the IM context should allow to use the text prediction.
715 *
716 * @param ctx An #Ecore_IMF_Context.
717 * @return @c EINA_TRUE if it allows to use the text prediction, otherwise
718 * @c EINA_FALSE.
719 * @ingroup Ecore_IMF_Context_Group
720 * @since 1.1.0
721 */
722EAPI Eina_Bool
723ecore_imf_context_prediction_allow_get(Ecore_IMF_Context *ctx)
724{
725 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
726 {
727 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
728 "ecore_imf_context_prediction_allow_get");
729 return EINA_FALSE;
730 }
731
732 return ctx->allow_prediction;
733}
734
735/**
736 * Set the autocapitalization type on the immodule.
737 *
738 * @param ctx An #Ecore_IMF_Context.
739 * @param autocapital_type the autocapitalization type.
740 * @note Default type is ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE.
741 * @ingroup Ecore_IMF_Context_Group
742 * @since 1.1.0
743 */
744EAPI void
745ecore_imf_context_autocapital_type_set(Ecore_IMF_Context *ctx, Ecore_IMF_Autocapital_Type autocapital_type)
746{
747 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
748 {
749 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
750 "ecore_imf_context_autocapital_type_set");
751 return;
752 }
753
754 ctx->autocapital_type = autocapital_type;
755
756 if (ctx->klass->autocapital_type_set) ctx->klass->autocapital_type_set(ctx, autocapital_type);
757}
758
759/**
760 * Get the autocapitalization type.
761 *
762 * @param ctx An #Ecore_IMF_Context.
763 * @return The autocapital type being used by @p ctx.
764 * @ingroup Ecore_IMF_Context_Group
765 * @since 1.1.0
766 */
767EAPI Ecore_IMF_Autocapital_Type
768ecore_imf_context_autocapital_type_get(Ecore_IMF_Context *ctx)
769{
770 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
771 {
772 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
773 "ecore_imf_context_autocapital_allow_get");
774 return ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
775 }
776
777 return ctx->autocapital_type;
778}
779
780/**
781 * Set the callback to be used on surrounding_get request.
782 *
783 * This callback will be called when the Input Method Context
784 * module requests the surrounding context.
785 *
786 * @param ctx An #Ecore_IMF_Context.
787 * @param func The callback to be called.
788 * @param data The data pointer to be passed to @p func
789 * @ingroup Ecore_IMF_Context_Group
790 */
791EAPI void
792ecore_imf_context_retrieve_surrounding_callback_set(Ecore_IMF_Context *ctx, Eina_Bool (*func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos), const void *data)
793{
794 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
795 {
796 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
797 "ecore_imf_context_retrieve_surrounding_callback_set");
798 return;
799 }
800
801 ctx->retrieve_surrounding_func = func;
802 ctx->retrieve_surrounding_data = (void *) data;
803}
804
805/**
806 * Set the input mode used by the Ecore Input Context.
807 *
808 * The input mode can be one of the input modes defined in
809 * Ecore_IMF_Input_Mode. The default input mode is
810 * ECORE_IMF_INPUT_MODE_FULL.
811 *
812 * @param ctx An #Ecore_IMF_Context.
813 * @param input_mode The input mode to be used by @p ctx.
814 * @ingroup Ecore_IMF_Context_Group
815 */
816EAPI void
817ecore_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
818{
819 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
820 {
821 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
822 "ecore_imf_context_input_mode_set");
823 return;
824 }
825 if (ctx->klass->input_mode_set) ctx->klass->input_mode_set(ctx, input_mode);
826 ctx->input_mode = input_mode;
827}
828
829/**
830 * Get the input mode being used by the Ecore Input Context.
831 *
832 * See @ref ecore_imf_context_input_mode_set for more details.
833 *
834 * @param ctx An #Ecore_IMF_Context.
835 * @return The input mode being used by @p ctx.
836 * @ingroup Ecore_IMF_Context_Group
837 */
838EAPI Ecore_IMF_Input_Mode
839ecore_imf_context_input_mode_get(Ecore_IMF_Context *ctx)
840{
841 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
842 {
843 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
844 "ecore_imf_context_input_mode_set");
845 return 0;
846 }
847 return ctx->input_mode;
848}
849
850/**
851 * Allow an Ecore Input Context to internally handle an event.
852 * If this function returns @c EINA_TRUE, then no further processing
853 * should be done for this event.
854 *
855 * Input methods must be able to accept all types of events (simply
856 * returning @c EINA_FALSE if the event was not handled), but there is no
857 * obligation of any events to be submitted to this function.
858 *
859 * @param ctx An #Ecore_IMF_Context.
860 * @param type The type of event defined by #Ecore_IMF_Event_Type.
861 * @param event The event itself.
862 * @return @c EINA_TRUE if the event was handled; otherwise @c EINA_FALSE.
863 * @ingroup Ecore_IMF_Context_Group
864 *
865 * Example
866 * @code
867 * static void
868 * _key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
869 * {
870 * Evas_Event_Key_Down *ev = event_info;
871 * if (!ev->keyname) return;
872 *
873 * if (imf_context)
874 * {
875 * Ecore_IMF_Event_Key_Down ecore_ev;
876 * ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev);
877 * if (ecore_imf_context_filter_event(imf_context,
878 * ECORE_IMF_EVENT_KEY_DOWN,
879 * (Ecore_IMF_Event *)&ecore_ev))
880 * return;
881 * }
882 * }
883 *
884 * evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, data);
885 * @endcode
886 */
887EAPI Eina_Bool
888ecore_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
889{
890 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
891 {
892 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
893 "ecore_imf_context_filter_event");
894 return EINA_FALSE;
895 }
896 if (ctx->klass->filter_event) return ctx->klass->filter_event(ctx, type, event);
897 return EINA_FALSE;
898}
899
900/**
901 * @defgroup Ecore_IMF_Context_Module_Group Ecore Input Method Context Module Functions
902 *
903 * Functions that should be used by Ecore Input Method Context modules.
904 */
905
906/**
907 * Creates a new Input Method Context with klass specified by @p ctxc.
908 *
909 * This method should be used by modules implementing the Input
910 * Method Context interface.
911 *
912 * @param ctxc An #Ecore_IMF_Context_Class.
913 * @return A new #Ecore_IMF_Context; on failure it returns NULL.
914 * @ingroup Ecore_IMF_Context_Module_Group
915 */
916EAPI Ecore_IMF_Context *
917ecore_imf_context_new(const Ecore_IMF_Context_Class *ctxc)
918{
919 Ecore_IMF_Context *ctx;
920
921 if (!ctxc) return NULL;
922 ctx = calloc(1, sizeof(Ecore_IMF_Context));
923 if (!ctx) return NULL;
924 ECORE_MAGIC_SET(ctx, ECORE_MAGIC_CONTEXT);
925 ctx->klass = ctxc;
926 ctx->data = NULL;
927 ctx->retrieve_surrounding_func = NULL;
928 ctx->retrieve_surrounding_data = NULL;
929 return ctx;
930}
931
932/**
933 * Set the Input Method Context specific data.
934 *
935 * Note that this method should be used by modules to set
936 * the Input Method Context specific data and it's not meant to
937 * be used by applications to store application specific data.
938 *
939 * @param ctx An #Ecore_IMF_Context.
940 * @param data The Input Method Context specific data.
941 * @return A new #Ecore_IMF_Context; on failure it returns NULL.
942 * @ingroup Ecore_IMF_Context_Module_Group
943 */
944EAPI void
945ecore_imf_context_data_set(Ecore_IMF_Context *ctx, void *data)
946{
947 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
948 {
949 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
950 "ecore_imf_context_data_set");
951 return;
952 }
953 ctx->data = data;
954}
955
956/**
957 * Get the Input Method Context specific data.
958 *
959 * See @ref ecore_imf_context_data_set for more details.
960 *
961 * @param ctx An #Ecore_IMF_Context.
962 * @return The Input Method Context specific data.
963 * @ingroup Ecore_IMF_Context_Module_Group
964 */
965EAPI void *ecore_imf_context_data_get(Ecore_IMF_Context *ctx)
966{
967 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
968 {
969 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
970 "ecore_imf_context_data_get");
971 return NULL;
972 }
973 return ctx->data;
974}
975
976/**
977 * Retrieve context around insertion point.
978 * Input methods typically want context in order to constrain input text based on existing text;
979 * this is important for languages such as Thai where only some sequences of characters are allowed.
980 * In addition, the text around the insertion point can be used for supporting autocapital feature.
981 *
982 * This function is implemented by calling the
983 * Ecore_IMF_Context::retrieve_surrounding_func (
984 * set using #ecore_imf_context_retrieve_surrounding_callback_set).
985 *
986 * There is no obligation for a widget to respond to the
987 * retrieve_surrounding_func, so input methods must be prepared
988 * to function without context.
989 *
990 * @param ctx An #Ecore_IMF_Context.
991 * @param text Location to store a UTF-8 encoded string of text
992 * holding context around the insertion point.
993 * If the function returns @c EINA_TRUE, then you must free
994 * the result stored in this location with free().
995 * @param cursor_pos Location to store the position in characters of
996 * the insertion cursor within @p text.
997 * @return @c EINA_TRUE if surrounding text was provided; otherwise
998 * @c EINA_FALSE.
999 * @ingroup Ecore_IMF_Context_Module_Group
1000 */
1001EAPI Eina_Bool
1002ecore_imf_context_surrounding_get(Ecore_IMF_Context *ctx, char **text, int *cursor_pos)
1003{
1004 int result = EINA_FALSE;
1005
1006 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1007 {
1008 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1009 "ecore_imf_context_surrounding_get");
1010 return EINA_FALSE;
1011 }
1012
1013 if (ctx->retrieve_surrounding_func)
1014 {
1015 result = ctx->retrieve_surrounding_func(ctx->retrieve_surrounding_data, ctx, text, cursor_pos);
1016 if (!result)
1017 {
1018 if (text) *text = NULL;
1019 if (cursor_pos) *cursor_pos = 0;
1020 }
1021 }
1022 return result;
1023}
1024
1025static void
1026_ecore_imf_event_free_preedit(void *data EINA_UNUSED, void *event)
1027{
1028 free(event);
1029}
1030
1031/**
1032 * Adds ECORE_IMF_EVENT_PREEDIT_START to the event queue.
1033 *
1034 * ECORE_IMF_EVENT_PREEDIT_START should be added when a new preedit sequence starts.
1035 * It's asynchronous method to put event to the event queue.
1036 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1037 *
1038 * @param ctx An #Ecore_IMF_Context.
1039 * @ingroup Ecore_IMF_Context_Module_Group
1040 */
1041EAPI void
1042ecore_imf_context_preedit_start_event_add(Ecore_IMF_Context *ctx)
1043{
1044 Ecore_IMF_Event_Commit *ev;
1045
1046 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1047 {
1048 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1049 "ecore_imf_context_preedit_start_event_add");
1050 return;
1051 }
1052
1053 ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Start));
1054 ev->ctx = ctx;
1055 ecore_event_add(ECORE_IMF_EVENT_PREEDIT_START,
1056 ev, _ecore_imf_event_free_preedit, NULL);
1057}
1058
1059/**
1060 * Adds ECORE_IMF_EVENT_PREEDIT_END to the event queue.
1061 *
1062 * ECORE_IMF_EVENT_PREEDIT_END should be added when a new preedit sequence has been completed or canceled.
1063 * It's asynchronous method to put event to the event queue.
1064 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1065 *
1066 * @param ctx An #Ecore_IMF_Context.
1067 * @ingroup Ecore_IMF_Context_Module_Group
1068 */
1069EAPI void
1070ecore_imf_context_preedit_end_event_add(Ecore_IMF_Context *ctx)
1071{
1072 Ecore_IMF_Event_Commit *ev;
1073
1074 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1075 {
1076 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1077 "ecore_imf_context_preedit_end_event_add");
1078 return;
1079 }
1080
1081 ev = malloc(sizeof(Ecore_IMF_Event_Preedit_End));
1082 ev->ctx = ctx;
1083 ecore_event_add(ECORE_IMF_EVENT_PREEDIT_END,
1084 ev, _ecore_imf_event_free_preedit, NULL);
1085}
1086
1087/**
1088 * Adds ECORE_IMF_EVENT_PREEDIT_CHANGED to the event queue.
1089 *
1090 * It's asynchronous method to put event to the event queue.
1091 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1092 *
1093 * @param ctx An #Ecore_IMF_Context.
1094 * @ingroup Ecore_IMF_Context_Module_Group
1095 */
1096EAPI void
1097ecore_imf_context_preedit_changed_event_add(Ecore_IMF_Context *ctx)
1098{
1099 Ecore_IMF_Event_Commit *ev;
1100
1101 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1102 {
1103 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1104 "ecore_imf_context_preedit_changed_event_add");
1105 return;
1106 }
1107
1108 ev = malloc(sizeof(Ecore_IMF_Event_Preedit_Changed));
1109 ev->ctx = ctx;
1110 ecore_event_add(ECORE_IMF_EVENT_PREEDIT_CHANGED,
1111 ev, _ecore_imf_event_free_preedit, NULL);
1112}
1113
1114static void
1115_ecore_imf_event_free_commit(void *data EINA_UNUSED, void *event)
1116{
1117 Ecore_IMF_Event_Commit *ev;
1118
1119 ev = event;
1120 if (ev->str) free(ev->str);
1121 free(ev);
1122}
1123
1124/**
1125 * Adds ECORE_IMF_EVENT_COMMIT to the event queue.
1126 *
1127 * It's asynchronous method to put event to the event queue.
1128 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1129 *
1130 * @param ctx An #Ecore_IMF_Context.
1131 * @param str The committed string.
1132 * @ingroup Ecore_IMF_Context_Module_Group
1133 */
1134EAPI void
1135ecore_imf_context_commit_event_add(Ecore_IMF_Context *ctx, const char *str)
1136{
1137 Ecore_IMF_Event_Commit *ev;
1138
1139 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1140 {
1141 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1142 "ecore_imf_context_commit_event_add");
1143 return;
1144 }
1145
1146 ev = malloc(sizeof(Ecore_IMF_Event_Commit));
1147 ev->ctx = ctx;
1148 ev->str = str ? strdup(str) : NULL;
1149 ecore_event_add(ECORE_IMF_EVENT_COMMIT,
1150 ev, _ecore_imf_event_free_commit, NULL);
1151
1152}
1153
1154static void
1155_ecore_imf_event_free_delete_surrounding(void *data EINA_UNUSED, void *event)
1156{
1157 free(event);
1158}
1159
1160/**
1161 * Adds ECORE_IMF_EVENT_DELETE_SURROUNDING to the event queue.
1162 *
1163 * Asks the widget that the input context is attached to to delete characters around the cursor position
1164 * by adding the ECORE_IMF_EVENT_DELETE_SURROUNDING to the event queue.
1165 * Note that offset and n_chars are in characters not in bytes.
1166 *
1167 * It's asynchronous method to put ECORE_IMF_EVENT_DELETE_SURROUNDING event to the event queue.
1168 * ecore_imf_context_event_callback_call() can be used as synchronous method.
1169 *
1170 * @param ctx An #Ecore_IMF_Context.
1171 * @param offset The start offset of surrounding to be deleted.
1172 * @param n_chars The number of characters to be deleted.
1173 * @ingroup Ecore_IMF_Context_Module_Group
1174 */
1175EAPI void
1176ecore_imf_context_delete_surrounding_event_add(Ecore_IMF_Context *ctx, int offset, int n_chars)
1177{
1178 Ecore_IMF_Event_Delete_Surrounding *ev;
1179
1180 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1181 {
1182 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1183 "ecore_imf_context_delete_surrounding_event_add");
1184 return;
1185 }
1186
1187 ev = malloc(sizeof(Ecore_IMF_Event_Delete_Surrounding));
1188 ev->ctx = ctx;
1189 ev->offset = offset;
1190 ev->n_chars = n_chars;
1191 ecore_event_add(ECORE_IMF_EVENT_DELETE_SURROUNDING,
1192 ev, _ecore_imf_event_free_delete_surrounding, NULL);
1193}
1194
1195/**
1196 * Add (register) a callback function to a given context event.
1197 *
1198 * This function adds a function callback to the context @p ctx when the
1199 * event of type @p type occurs on it. The function pointer is @p
1200 * func.
1201 *
1202 * The event type @p type to trigger the function may be one of
1203 * #ECORE_IMF_CALLBACK_PREEDIT_START, #ECORE_IMF_CALLBACK_PREEDIT_END,
1204 * #ECORE_IMF_CALLBACK_PREEDIT_CHANGED, #ECORE_IMF_CALLBACK_COMMIT and
1205 * #ECORE_IMF_CALLBACK_DELETE_SURROUNDING.
1206 *
1207 * @param ctx Ecore_IMF_Context to attach a callback to.
1208 * @param type The type of event that will trigger the callback
1209 * @param func The (callback) function to be called when the event is
1210 * triggered
1211 * @param data The data pointer to be passed to @p func
1212 * @ingroup Ecore_IMF_Context_Group
1213 * @since 1.2.0
1214 *
1215 * Example
1216 * @code
1217 * static void
1218 * _imf_event_commit_cb(void *data, Ecore_IMF_Context *ctx, void *event_info)
1219 * {
1220 * char *commit_str = event_info;
1221 * // something to do
1222 * }
1223 *
1224 * ecore_imf_context_event_callback_add(en->imf_context, ECORE_IMF_CALLBACK_COMMIT, _imf_event_commit_cb, data);
1225 * @endcode
1226 */
1227EAPI void
1228ecore_imf_context_event_callback_add(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func, const void *data)
1229{
1230 Ecore_IMF_Func_Node *fn = NULL;
1231
1232 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1233 {
1234 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1235 "ecore_imf_context_event_callback_add");
1236 return;
1237 }
1238
1239 if (!func) return;
1240
1241 fn = calloc(1, sizeof (Ecore_IMF_Func_Node));
1242 if (!fn) return;
1243
1244 fn->func = func;
1245 fn->data = data;
1246 fn->type = type;
1247
1248 ctx->callbacks = eina_list_append(ctx->callbacks, fn);
1249}
1250
1251/**
1252 * Delete (unregister) a callback function registered to a given
1253 * context event.
1254 *
1255 * This function removes a function callback from the context @p ctx when the
1256 * event of type @p type occurs on it. The function pointer is @p
1257 * func.
1258 *
1259 * @see ecore_imf_context_event_callback_add() for more details
1260 *
1261 * @param ctx Ecore_IMF_Context to remove a callback from.
1262 * @param type The type of event that was triggering the callback
1263 * @param func The (callback) function that was to be called when the event was triggered
1264 * @return the data pointer
1265 * @ingroup Ecore_IMF_Context_Group
1266 * @since 1.2.0
1267 */
1268EAPI void *
1269ecore_imf_context_event_callback_del(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, Ecore_IMF_Event_Cb func)
1270{
1271 Eina_List *l = NULL;
1272 Eina_List *l_next = NULL;
1273 Ecore_IMF_Func_Node *fn = NULL;
1274
1275 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1276 {
1277 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1278 "ecore_imf_context_event_callback_del");
1279 return NULL;
1280 }
1281
1282 if (!func) return NULL;
1283 if (!ctx->callbacks) return NULL;
1284
1285 EINA_LIST_FOREACH_SAFE(ctx->callbacks, l, l_next, fn)
1286 {
1287 if ((fn) && (fn->func == func) && (fn->type == type))
1288 {
1289 void *tmp = (void *)fn->data;
1290 free(fn);
1291 ctx->callbacks = eina_list_remove_list(ctx->callbacks, l);
1292 return tmp;
1293 }
1294 }
1295 return NULL;
1296}
1297
1298/**
1299 * Call a given callback on the context @p ctx.
1300 *
1301 * ecore_imf_context_preedit_start_event_add(), ecore_imf_context_preedit_end_event_add(),
1302 * ecore_imf_context_preedit_changed_event_add(), ecore_imf_context_commit_event_add() and
1303 * ecore_imf_context_delete_surrounding_event_add() APIs are asynchronous
1304 * because those API adds each event to the event queue.
1305 *
1306 * This API provides the way to call each callback function immediately.
1307 *
1308 * @param ctx Ecore_IMF_Context.
1309 * @param type The type of event that will trigger the callback
1310 * @param event_info The pointer to event specific struct or information to
1311 * pass to the callback functions registered on this event
1312 * @ingroup Ecore_IMF_Context_Module_Group
1313 * @since 1.2.0
1314 */
1315EAPI void
1316ecore_imf_context_event_callback_call(Ecore_IMF_Context *ctx, Ecore_IMF_Callback_Type type, void *event_info)
1317{
1318 Ecore_IMF_Func_Node *fn = NULL;
1319 Eina_List *l = NULL;
1320
1321 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1322 {
1323 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1324 "ecore_imf_context_event_callback_call");
1325 return;
1326 }
1327
1328 EINA_LIST_FOREACH(ctx->callbacks, l, fn)
1329 {
1330 if ((fn) && (fn->type == type) && (fn->func))
1331 fn->func(fn->data, ctx, event_info);
1332 }
1333}
1334
1335/**
1336 * Ask the Input Method Context to show the control panel of using Input Method.
1337 *
1338 * @param ctx An #Ecore_IMF_Context.
1339 * @ingroup Ecore_IMF_Context_Group
1340 * @since 1.1.0
1341 */
1342EAPI void
1343ecore_imf_context_control_panel_show(Ecore_IMF_Context *ctx)
1344{
1345 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1346 {
1347 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1348 "ecore_imf_context_control_panel_show");
1349 return;
1350 }
1351
1352 if (ctx->klass->control_panel_show) ctx->klass->control_panel_show(ctx);
1353}
1354
1355/**
1356 * Ask the Input Method Context to hide the control panel of using Input Method.
1357 *
1358 * @param ctx An #Ecore_IMF_Context.
1359 * @ingroup Ecore_IMF_Context_Group
1360 * @since 1.1.0
1361 */
1362EAPI void
1363ecore_imf_context_control_panel_hide(Ecore_IMF_Context *ctx)
1364{
1365 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1366 {
1367 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1368 "ecore_imf_context_control_panel_hide");
1369 return;
1370 }
1371
1372 if (ctx->klass->control_panel_hide) ctx->klass->control_panel_hide(ctx);
1373}
1374
1375/**
1376 * Ask the Input Method Context to show the input panel (virtual keyboard).
1377 *
1378 * @param ctx An #Ecore_IMF_Context.
1379 * @ingroup Ecore_IMF_Context_Group
1380 * @since 1.1.0
1381 */
1382EAPI void
1383ecore_imf_context_input_panel_show(Ecore_IMF_Context *ctx)
1384{
1385 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1386 {
1387 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1388 "ecore_imf_context_input_panel_show");
1389 return;
1390 }
1391
1392 if (ctx->klass->show) ctx->klass->show(ctx);
1393}
1394
1395/**
1396 * Ask the Input Method Context to hide the input panel.
1397 *
1398 * @param ctx An #Ecore_IMF_Context.
1399 * @ingroup Ecore_IMF_Context_Group
1400 * @since 1.1.0
1401 */
1402EAPI void
1403ecore_imf_context_input_panel_hide(Ecore_IMF_Context *ctx)
1404{
1405 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1406 {
1407 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1408 "ecore_imf_context_input_panel_hide");
1409 return;
1410 }
1411
1412 if (ctx->klass->hide) ctx->klass->hide(ctx);
1413}
1414
1415/**
1416 * Set the layout of the input panel.
1417 *
1418 * @param ctx An #Ecore_IMF_Context.
1419 * @param layout see #Ecore_IMF_Input_Panel_Layout
1420 * @note Default layout type is ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL.
1421 * @ingroup Ecore_IMF_Context_Group
1422 * @since 1.1.0
1423 */
1424EAPI void
1425ecore_imf_context_input_panel_layout_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Layout layout)
1426{
1427 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1428 {
1429 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1430 "ecore_imf_context_input_panel_layout_set");
1431 return;
1432 }
1433
1434 if (ctx->klass->input_panel_layout_set)
1435 ctx->klass->input_panel_layout_set(ctx, layout);
1436
1437 ctx->input_panel_layout = layout;
1438}
1439
1440/**
1441 * Get the layout of the current active input panel.
1442 *
1443 * @param ctx An #Ecore_IMF_Context.
1444 * @return layout see #Ecore_IMF_Input_Panel_Layout
1445 * @ingroup Ecore_IMF_Context_Group
1446 * @since 1.1.0
1447 */
1448EAPI Ecore_IMF_Input_Panel_Layout
1449ecore_imf_context_input_panel_layout_get(Ecore_IMF_Context *ctx)
1450{
1451 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1452 {
1453 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1454 "ecore_imf_context_input_panel_layout_get");
1455 return ECORE_IMF_INPUT_PANEL_LAYOUT_INVALID;
1456 }
1457
1458 if (ctx->klass->input_panel_layout_get)
1459 return ctx->input_panel_layout;
1460 else
1461 return ECORE_IMF_INPUT_PANEL_LAYOUT_INVALID;
1462}
1463
1464/**
1465 * Set the language of the input panel.
1466 * This API can be used when you want to show the English keyboard.
1467 *
1468 * @param ctx An #Ecore_IMF_Context.
1469 * @param lang the language to be set to the input panel.
1470 * @ingroup Ecore_IMF_Context_Group
1471 * @since 1.1.0
1472 */
1473EAPI void
1474ecore_imf_context_input_panel_language_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Lang lang)
1475{
1476 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1477 {
1478 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1479 "ecore_imf_context_input_panel_language_set");
1480 return;
1481 }
1482
1483 if (ctx->klass->input_panel_language_set) ctx->klass->input_panel_language_set(ctx, lang);
1484 ctx->input_panel_lang = lang;
1485}
1486
1487/**
1488 * Get the language of the input panel.
1489 *
1490 * See @ref ecore_imf_context_input_panel_language_set for more details.
1491 *
1492 * @param ctx An #Ecore_IMF_Context.
1493 * @return Ecore_IMF_Input_Panel_Lang
1494 * @ingroup Ecore_IMF_Context_Group
1495 * @since 1.1.0
1496 */
1497EAPI Ecore_IMF_Input_Panel_Lang
1498ecore_imf_context_input_panel_language_get(Ecore_IMF_Context *ctx)
1499{
1500 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1501 {
1502 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1503 "ecore_imf_context_input_panel_language_get");
1504 return ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
1505 }
1506
1507 return ctx->input_panel_lang;
1508}
1509
1510/**
1511 * Set whether the Input Method Context should request to show the input panel automatically
1512 * when the widget has focus.
1513 *
1514 * @param ctx An #Ecore_IMF_Context.
1515 * @param enabled If true, the input panel will be shown when the widget is clicked or has focus.
1516 * @ingroup Ecore_IMF_Context_Group
1517 * @since 1.1.0
1518 */
1519EAPI void
1520ecore_imf_context_input_panel_enabled_set(Ecore_IMF_Context *ctx,
1521 Eina_Bool enabled)
1522{
1523 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1524 {
1525 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1526 "ecore_imf_context_input_panel_enabled_set");
1527 return;
1528 }
1529
1530 ctx->input_panel_enabled = enabled;
1531}
1532
1533/**
1534 * Get whether the Input Method Context requests to show the input panel automatically.
1535 *
1536 * @param ctx An #Ecore_IMF_Context.
1537 * @return Return the attribute to show the input panel automatically
1538 * @ingroup Ecore_IMF_Context_Group
1539 * @since 1.1.0
1540 */
1541EAPI Eina_Bool
1542ecore_imf_context_input_panel_enabled_get(Ecore_IMF_Context *ctx)
1543{
1544 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1545 {
1546 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1547 "ecore_imf_context_input_panel_enabled_get");
1548 return EINA_FALSE;
1549 }
1550
1551 return ctx->input_panel_enabled;
1552}
1553
1554/**
1555 * Set the input panel-specific data to deliver to the input panel.
1556 * This API is used by applications to deliver specific data to the input panel.
1557 * The data format MUST be negotiated by both application and the input panel.
1558 * The size and format of data are defined by the input panel.
1559 *
1560 * @param ctx An #Ecore_IMF_Context.
1561 * @param data The specific data to be set to the input panel.
1562 * @param len the length of data, in bytes, to send to the input panel
1563 * @ingroup Ecore_IMF_Context_Group
1564 * @since 1.2.0
1565 */
1566EAPI void
1567ecore_imf_context_input_panel_imdata_set(Ecore_IMF_Context *ctx, const void *data, int len)
1568{
1569 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1570 {
1571 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1572 "ecore_imf_context_input_panel_imdata_set");
1573 return;
1574 }
1575
1576 if (!data) return;
1577
1578 if (ctx->klass->input_panel_imdata_set)
1579 ctx->klass->input_panel_imdata_set(ctx, data, len);
1580}
1581
1582/**
1583 * Get the specific data of the current active input panel.
1584 *
1585 * @param ctx An #Ecore_IMF_Context.
1586 * @param data The specific data to be got from the input panel
1587 * @param len The length of data
1588 * @ingroup Ecore_IMF_Context_Group
1589 * @since 1.2.0
1590 */
1591EAPI void
1592ecore_imf_context_input_panel_imdata_get(Ecore_IMF_Context *ctx, void *data, int *len)
1593{
1594 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1595 {
1596 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1597 "ecore_imf_context_input_panel_imdata_get");
1598 return;
1599 }
1600
1601 if (!data) return;
1602
1603 if (ctx->klass->input_panel_imdata_get)
1604 ctx->klass->input_panel_imdata_get(ctx, data, len);
1605}
1606
1607/**
1608 * Set the "return" key type. This type is used to set string or icon on the "return" key of the input panel.
1609 *
1610 * An input panel displays the string or icon associated with this type
1611 *
1612 * @param ctx An #Ecore_IMF_Context.
1613 * @param return_key_type The type of "return" key on the input panel
1614 * @note Default type is ECORE_IMF_INPUT_PANEL_RETURN_KEY_TYPE_DEFAULT.
1615 * @ingroup Ecore_IMF_Context_Group
1616 * @since 1.2.0
1617 */
1618EAPI void
1619ecore_imf_context_input_panel_return_key_type_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Panel_Return_Key_Type return_key_type)
1620{
1621 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1622 {
1623 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1624 "ecore_imf_context_input_panel_return_key_type_set");
1625 return;
1626 }
1627
1628 ctx->input_panel_return_key_type = return_key_type;
1629 if (ctx->klass->input_panel_return_key_type_set) ctx->klass->input_panel_return_key_type_set(ctx, return_key_type);
1630}
1631
1632/**
1633 * Get the "return" key type.
1634 *
1635 * @see ecore_imf_context_input_panel_return_key_type_set() for more details
1636 *
1637 * @param ctx An #Ecore_IMF_Context.
1638 * @return The type of "return" key on the input panel
1639 * @ingroup Ecore_IMF_Context_Group
1640 * @since 1.2.0
1641 */
1642EAPI Ecore_IMF_Input_Panel_Return_Key_Type
1643ecore_imf_context_input_panel_return_key_type_get(Ecore_IMF_Context *ctx)
1644{
1645 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1646 {
1647 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1648 "ecore_imf_context_input_panel_return_key_type_get");
1649 return EINA_FALSE;
1650 }
1651
1652 return ctx->input_panel_return_key_type;
1653}
1654
1655/**
1656 * Set the return key on the input panel to be disabled.
1657 *
1658 * @param ctx An #Ecore_IMF_Context.
1659 * @param disabled The state
1660 * @ingroup Ecore_IMF_Context_Group
1661 * @since 1.2.0
1662 */
1663EAPI void
1664ecore_imf_context_input_panel_return_key_disabled_set(Ecore_IMF_Context *ctx, Eina_Bool disabled)
1665{
1666 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1667 {
1668 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1669 "ecore_imf_context_input_panel_return_key_disabled_set");
1670 return;
1671 }
1672
1673 ctx->input_panel_return_key_disabled = disabled;
1674 if (ctx->klass->input_panel_return_key_disabled_set) ctx->klass->input_panel_return_key_disabled_set(ctx, disabled);
1675}
1676
1677/**
1678 * Get whether the return key on the input panel should be disabled or not.
1679 *
1680 * @param ctx An #Ecore_IMF_Context.
1681 * @return @c EINA_TRUE if it should be disabled.
1682 * @ingroup Ecore_IMF_Context_Group
1683 * @since 1.2.0
1684 */
1685EAPI Eina_Bool
1686ecore_imf_context_input_panel_return_key_disabled_get(Ecore_IMF_Context *ctx)
1687{
1688 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1689 {
1690 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1691 "ecore_imf_context_input_panel_return_key_disabled_get");
1692 return EINA_FALSE;
1693 }
1694
1695 return ctx->input_panel_return_key_disabled;
1696}
1697
1698/**
1699 * Set the caps lock mode on the input panel.
1700 *
1701 * @param ctx An #Ecore_IMF_Context.
1702 * @param mode Turn on caps lock on the input panel if @c EINA_TRUE.
1703 * @ingroup Ecore_IMF_Context_Group
1704 * @since 1.2.0
1705 */
1706EAPI void
1707ecore_imf_context_input_panel_caps_lock_mode_set(Ecore_IMF_Context *ctx, Eina_Bool mode)
1708{
1709 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1710 {
1711 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1712 "ecore_imf_context_input_panel_caps_lock_mode_set");
1713 return;
1714 }
1715
1716 if (ctx->klass->input_panel_caps_lock_mode_set)
1717 ctx->klass->input_panel_caps_lock_mode_set(ctx, mode);
1718
1719 ctx->input_panel_caps_lock_mode = mode;
1720}
1721
1722/**
1723 * Get the caps lock mode on the input panel.
1724 *
1725 * @param ctx An #Ecore_IMF_Context.
1726 * @return @c EINA_TRUE if the caps lock is turned on.
1727 * @ingroup Ecore_IMF_Context_Group
1728 * @since 1.2.0
1729 */
1730EAPI Eina_Bool
1731ecore_imf_context_input_panel_caps_lock_mode_get(Ecore_IMF_Context *ctx)
1732{
1733 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1734 {
1735 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1736 "ecore_imf_context_input_panel_caps_lock_mode_get");
1737 return EINA_FALSE;
1738 }
1739
1740 return ctx->input_panel_caps_lock_mode;
1741}
1742
1743/**
1744 * Get the position of the current active input panel.
1745 *
1746 * @param ctx An #Ecore_IMF_Context.
1747 * @param x top-left x co-ordinate of the input panel
1748 * @param y top-left y co-ordinate of the input panel
1749 * @param w width of the input panel
1750 * @param h height of the input panel
1751 * @ingroup Ecore_IMF_Context_Group
1752 * @since 1.3
1753 */
1754EAPI void
1755ecore_imf_context_input_panel_geometry_get(Ecore_IMF_Context *ctx, int *x, int *y, int *w, int *h)
1756{
1757 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1758 {
1759 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1760 "ecore_imf_context_input_panel_geometry_get");
1761 return;
1762 }
1763
1764 if (ctx->klass->input_panel_geometry_get)
1765 ctx->klass->input_panel_geometry_get(ctx, x, y, w, h);
1766}
1767
1768/**
1769 * Get state of current active input panel.
1770 *
1771 * @param ctx An #Ecore_IMF_Context.
1772 * @return The state of input panel.
1773 * @ingroup Ecore_IMF_Context_Group
1774 * @since 1.3
1775 */
1776EAPI Ecore_IMF_Input_Panel_State
1777ecore_imf_context_input_panel_state_get(Ecore_IMF_Context *ctx)
1778{
1779 Ecore_IMF_Input_Panel_State state = ECORE_IMF_INPUT_PANEL_STATE_HIDE;
1780 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1781 {
1782 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1783 "ecore_imf_context_input_panel_state_get");
1784 return ECORE_IMF_INPUT_PANEL_STATE_HIDE;
1785 }
1786
1787 if (ctx->klass->input_panel_state_get)
1788 state = ctx->klass->input_panel_state_get(ctx);
1789
1790 return state;
1791}
1792
1793/**
1794 * Register a callback function which will be called if there is change in input panel state,language,mode etc.
1795 * In order to deregister the callback function
1796 * Use @ref ecore_imf_context_input_panel_event_callback_del.
1797 *
1798 * @param ctx An #Ecore_IMF_Context
1799 * @param type event type
1800 * @param func the callback function
1801 * @param data application-input panel specific data.
1802 * @ingroup Ecore_IMF_Context_Group
1803 * @since 1.3
1804 */
1805EAPI void
1806ecore_imf_context_input_panel_event_callback_add(Ecore_IMF_Context *ctx,
1807 Ecore_IMF_Input_Panel_Event type,
1808 void (*func) (void *data, Ecore_IMF_Context *ctx, int value),
1809 const void *data)
1810{
1811 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1812 {
1813 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1814 "ecore_imf_context_input_panel_event_callback_add");
1815 return;
1816 }
1817
1818 if (ctx->klass->input_panel_event_callback_add)
1819 ctx->klass->input_panel_event_callback_add(ctx, type, func, (void *)data);
1820}
1821
1822/**
1823 * Unregister a callback function which will be called if there is change in input panel state, language, mode etc.
1824 *
1825 * @param ctx An #Ecore_IMF_Context.
1826 * @param type An #Ecore_IMF_Input_Panel_Event.
1827 * @param func the callback function
1828 * @ingroup Ecore_IMF_Context_Group
1829 * @since 1.3
1830 */
1831EAPI void
1832ecore_imf_context_input_panel_event_callback_del(Ecore_IMF_Context *ctx,
1833 Ecore_IMF_Input_Panel_Event type,
1834 void (*func) (void *data, Ecore_IMF_Context *ctx, int value))
1835{
1836 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1837 {
1838 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1839 "ecore_imf_context_input_panel_event_callback_del");
1840 return;
1841 }
1842
1843 if (ctx->klass->input_panel_event_callback_del)
1844 ctx->klass->input_panel_event_callback_del(ctx, type, func);
1845}
1846
1847/**
1848 * Get the current language locale of the input panel.
1849 *
1850 * ex) fr_FR
1851 *
1852 * @param ctx An #Ecore_IMF_Context.
1853 * @param lang Location to store the retrieved language string. The
1854 * string retrieved must be freed with free().
1855 * @ingroup Ecore_IMF_Context_Group
1856 * @since 1.3
1857 */
1858EAPI void
1859ecore_imf_context_input_panel_language_locale_get(Ecore_IMF_Context *ctx, char **lang)
1860{
1861 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1862 {
1863 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1864 "ecore_imf_context_input_panel_language_locale_get");
1865 return;
1866 }
1867
1868 if (ctx->klass->input_panel_language_locale_get)
1869 ctx->klass->input_panel_language_locale_get(ctx, lang);
1870 else
1871 {
1872 if (lang) *lang = strdup("");
1873 }
1874}
1875
1876/**
1877 * Get the geometry information of the candidate panel.
1878 *
1879 * @param ctx An #Ecore_IMF_Context.
1880 * @param x top-left x co-ordinate of the candidate panel
1881 * @param y top-left y co-ordinate of the candidate panel
1882 * @param w width of the candidate panel
1883 * @param h height of the candidate panel
1884 * @ingroup Ecore_IMF_Context_Group
1885 * @since 1.3
1886 */
1887EAPI void
1888ecore_imf_context_candidate_panel_geometry_get(Ecore_IMF_Context *ctx, int *x, int *y, int *w, int *h)
1889{
1890 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
1891 {
1892 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
1893 "ecore_imf_context_candidate_panel_geometry_get");
1894 return;
1895 }
1896
1897 if (ctx->klass->candidate_panel_geometry_get)
1898 ctx->klass->candidate_panel_geometry_get(ctx, x, y, w, h);
1899}
1900
diff --git a/src/lib/ecore_imf/ecore_imf_evas.c b/src/lib/ecore_imf/ecore_imf_evas.c
new file mode 100644
index 0000000000..4a5f3dd5f4
--- /dev/null
+++ b/src/lib/ecore_imf/ecore_imf_evas.c
@@ -0,0 +1,324 @@
1
2#ifdef HAVE_CONFIG_H
3# include <config.h>
4#endif
5
6#include <Ecore.h>
7#include "ecore_private.h"
8#include "Ecore_IMF_Evas.h"
9
10/**
11 * @defgroup Ecore_IMF_Evas_Group Ecore Input Method Context Evas Helper Functions
12 *
13 * Helper functions to make it easy to use Evas with Ecore_IMF.
14 * Converts each event from Evas to the corresponding event of Ecore_IMF.
15 *
16 * An example of usage of these functions can be found at:
17 * @li @ref ecore_imf_example_c
18 */
19
20static const char *_ecore_imf_evas_event_empty = "";
21
22/* Converts the Evas modifiers to Ecore_IMF keyboard modifiers */
23static void
24_ecore_imf_evas_event_modifiers_wrap(Evas_Modifier *evas_modifiers,
25 Ecore_IMF_Keyboard_Modifiers *imf_keyboard_modifiers)
26{
27 if (!evas_modifiers || !imf_keyboard_modifiers)
28 return;
29
30 *imf_keyboard_modifiers = ECORE_IMF_KEYBOARD_MODIFIER_NONE;
31 if (evas_key_modifier_is_set(evas_modifiers, "Control"))
32 *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_CTRL;
33 if (evas_key_modifier_is_set(evas_modifiers, "Alt"))
34 *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_ALT;
35 if (evas_key_modifier_is_set(evas_modifiers, "Shift"))
36 *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_SHIFT;
37 if (evas_key_modifier_is_set(evas_modifiers, "Super") || evas_key_modifier_is_set(evas_modifiers, "Hyper"))
38 *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_WIN;
39 if (evas_key_modifier_is_set(evas_modifiers, "AltGr"))
40 *imf_keyboard_modifiers |= ECORE_IMF_KEYBOARD_MODIFIER_ALTGR;
41}
42
43/* Converts the Evas locks to Ecore_IMF keyboard locks */
44static void
45_ecore_imf_evas_event_locks_wrap(Evas_Lock *evas_locks,
46 Ecore_IMF_Keyboard_Locks *imf_keyboard_locks)
47{
48 if (!evas_locks || !imf_keyboard_locks)
49 return;
50
51 *imf_keyboard_locks = ECORE_IMF_KEYBOARD_LOCK_NONE;
52 if (evas_key_lock_is_set(evas_locks, "Num_Lock"))
53 *imf_keyboard_locks |= ECORE_IMF_KEYBOARD_LOCK_NUM;
54 if (evas_key_lock_is_set(evas_locks, "Caps_Lock"))
55 *imf_keyboard_locks |= ECORE_IMF_KEYBOARD_LOCK_CAPS;
56 if (evas_key_lock_is_set(evas_locks, "Scroll_Lock"))
57 *imf_keyboard_locks |= ECORE_IMF_KEYBOARD_LOCK_SCROLL;
58}
59
60/* Converts the Evas mouse flags to Ecore_IMF mouse flags */
61static void
62_ecore_imf_evas_event_mouse_flags_wrap(Evas_Button_Flags evas_flags,
63 Ecore_IMF_Mouse_Flags *imf_flags)
64{
65 if (!imf_flags)
66 return;
67
68 *imf_flags = ECORE_IMF_MOUSE_NONE;
69 if (evas_flags & EVAS_BUTTON_DOUBLE_CLICK)
70 *imf_flags |= ECORE_IMF_MOUSE_DOUBLE_CLICK;
71 if (evas_flags & EVAS_BUTTON_TRIPLE_CLICK)
72 *imf_flags |= ECORE_IMF_MOUSE_TRIPLE_CLICK;
73}
74
75/**
76 * Converts a "mouse_in" event from Evas to the corresponding event of Ecore_IMF.
77 *
78 * @param evas_event The received Evas event.
79 * @param imf_event The location to store the converted Ecore_IMF event.
80 * @ingroup Ecore_IMF_Evas_Group
81 */
82EAPI void
83ecore_imf_evas_event_mouse_in_wrap(Evas_Event_Mouse_In *evas_event,
84 Ecore_IMF_Event_Mouse_In *imf_event)
85{
86 if (!evas_event || !imf_event)
87 return;
88
89 imf_event->buttons = evas_event->buttons;
90 imf_event->output.x = evas_event->output.x;
91 imf_event->output.y = evas_event->output.y;
92 imf_event->canvas.x = evas_event->canvas.x;
93 imf_event->canvas.y = evas_event->canvas.y;
94 imf_event->timestamp = evas_event->timestamp;
95 _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
96 _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
97}
98
99/**
100 * Converts a "mouse_out" event from Evas to the corresponding event of Ecore_IMF.
101 *
102 * @param evas_event The received Evas event.
103 * @param imf_event The location to store the converted Ecore_IMF event.
104 * @ingroup Ecore_IMF_Evas_Group
105 */
106EAPI void
107ecore_imf_evas_event_mouse_out_wrap(Evas_Event_Mouse_Out *evas_event,
108 Ecore_IMF_Event_Mouse_Out *imf_event)
109{
110 if (!evas_event || !imf_event)
111 return;
112
113 imf_event->buttons = evas_event->buttons;
114 imf_event->output.x = evas_event->output.x;
115 imf_event->output.y = evas_event->output.y;
116 imf_event->canvas.x = evas_event->canvas.x;
117 imf_event->canvas.y = evas_event->canvas.y;
118 imf_event->timestamp = evas_event->timestamp;
119 _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
120 _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
121}
122
123/**
124 * Converts a "mouse_move" event from Evas to the corresponding event of Ecore_IMF.
125 *
126 * @param evas_event The received Evas event.
127 * @param imf_event The location to store the converted Ecore_IMF event.
128 * @ingroup Ecore_IMF_Evas_Group
129 */
130EAPI void
131ecore_imf_evas_event_mouse_move_wrap(Evas_Event_Mouse_Move *evas_event,
132 Ecore_IMF_Event_Mouse_Move *imf_event)
133{
134 if (!evas_event || !imf_event)
135 return;
136
137 imf_event->buttons = evas_event->buttons;
138 imf_event->cur.output.x = evas_event->cur.output.x;
139 imf_event->cur.output.y = evas_event->cur.output.y;
140 imf_event->prev.output.x = evas_event->prev.output.x;
141 imf_event->prev.output.y = evas_event->prev.output.y;
142 imf_event->cur.canvas.x = evas_event->cur.canvas.x;
143 imf_event->cur.canvas.y = evas_event->cur.canvas.y;
144 imf_event->prev.canvas.x = evas_event->prev.canvas.x;
145 imf_event->prev.canvas.y = evas_event->prev.canvas.y;
146 imf_event->timestamp = evas_event->timestamp;
147 _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
148 _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
149}
150
151/**
152 * Converts a "mouse_down" event from Evas to the corresponding event of Ecore_IMF.
153 *
154 * @param evas_event The received Evas event.
155 * @param imf_event The location to store the converted Ecore_IMF event.
156 * @ingroup Ecore_IMF_Evas_Group
157 */
158EAPI void
159ecore_imf_evas_event_mouse_down_wrap(Evas_Event_Mouse_Down *evas_event,
160 Ecore_IMF_Event_Mouse_Down *imf_event)
161{
162 if (!evas_event || !imf_event)
163 return;
164
165 imf_event->button = evas_event->button;
166 imf_event->output.x = evas_event->output.x;
167 imf_event->output.y = evas_event->output.y;
168 imf_event->canvas.x = evas_event->canvas.x;
169 imf_event->canvas.y = evas_event->canvas.y;
170 imf_event->timestamp = evas_event->timestamp;
171 _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
172 _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
173 _ecore_imf_evas_event_mouse_flags_wrap(evas_event->flags, &imf_event->flags);
174}
175
176/**
177 * Converts a "mouse_up" event from Evas to the corresponding event of Ecore_IMF.
178 *
179 * @param evas_event The received Evas event.
180 * @param imf_event The location to store the converted Ecore_IMF event.
181 * @ingroup Ecore_IMF_Evas_Group
182 */
183EAPI void
184ecore_imf_evas_event_mouse_up_wrap(Evas_Event_Mouse_Up *evas_event,
185 Ecore_IMF_Event_Mouse_Up *imf_event)
186{
187 if (!evas_event || !imf_event)
188 return;
189
190 imf_event->button = evas_event->button;
191 imf_event->output.x = evas_event->output.x;
192 imf_event->output.y = evas_event->output.y;
193 imf_event->canvas.x = evas_event->canvas.x;
194 imf_event->canvas.y = evas_event->canvas.y;
195 imf_event->timestamp = evas_event->timestamp;
196 _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
197 _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
198 _ecore_imf_evas_event_mouse_flags_wrap(evas_event->flags, &imf_event->flags);
199}
200
201/**
202 * Converts a "mouse_wheel" event from Evas to the corresponding event of Ecore_IMF.
203 *
204 * @param evas_event The received Evas event.
205 * @param imf_event The location to store the converted Ecore_IMF event.
206 * @ingroup Ecore_IMF_Evas_Group
207 */
208EAPI void
209ecore_imf_evas_event_mouse_wheel_wrap(Evas_Event_Mouse_Wheel *evas_event,
210 Ecore_IMF_Event_Mouse_Wheel *imf_event)
211{
212 if (!evas_event || !imf_event)
213 return;
214
215 imf_event->direction = evas_event->direction;
216 imf_event->z = evas_event->z;
217 imf_event->output.x = evas_event->output.x;
218 imf_event->output.y = evas_event->output.y;
219 imf_event->canvas.x = evas_event->canvas.x;
220 imf_event->canvas.y = evas_event->canvas.y;
221 imf_event->timestamp = evas_event->timestamp;
222 _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
223 _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
224 imf_event->timestamp = evas_event->timestamp;
225}
226
227/**
228 * Converts a "key_down" event from Evas to the corresponding event of Ecore_IMF.
229 *
230 * @param evas_event The received Evas event.
231 * @param imf_event The location to store the converted Ecore_IMF event.
232 * @ingroup Ecore_IMF_Evas_Group
233 *
234 * Example
235 * @code
236 * static void
237 * _key_down_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
238 * {
239 * Evas_Event_Key_Down *ev = event_info;
240 * if (!ev->keyname) return;
241 *
242 * if (imf_context)
243 * {
244 * Ecore_IMF_Event_Key_Down ecore_ev;
245 * ecore_imf_evas_event_key_down_wrap(ev, &ecore_ev);
246 * if (ecore_imf_context_filter_event(imf_context,
247 * ECORE_IMF_EVENT_KEY_DOWN,
248 * (Ecore_IMF_Event *)&ecore_ev))
249 * return;
250 * }
251 * }
252 *
253 * evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_DOWN, _key_down_cb, data);
254 * @endcode
255 */
256EAPI void
257ecore_imf_evas_event_key_down_wrap(Evas_Event_Key_Down *evas_event,
258 Ecore_IMF_Event_Key_Down *imf_event)
259{
260 if (!evas_event || !imf_event)
261 return;
262
263 imf_event->keyname = evas_event->keyname ? evas_event->keyname : _ecore_imf_evas_event_empty;
264 imf_event->key = evas_event->key ? evas_event->key : _ecore_imf_evas_event_empty;
265 imf_event->string = evas_event->string ? evas_event->string : _ecore_imf_evas_event_empty;
266 imf_event->compose = evas_event->compose ? evas_event->compose : _ecore_imf_evas_event_empty;
267 imf_event->timestamp = evas_event->timestamp;
268 _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
269 _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
270}
271
272/**
273 * Converts a "key_up" event from Evas to the corresponding event of Ecore_IMF.
274 *
275 * @param evas_event The received Evas event.
276 * @param imf_event The location to store the converted Ecore_IMF event.
277 * @ingroup Ecore_IMF_Evas_Group
278 *
279 * Example
280 * @code
281 * static void
282 * _key_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
283 * {
284 * Evas_Event_Key_Up *ev = event_info;
285 * if (!ev->keyname) return;
286 *
287 * if (imf_context)
288 * {
289 * Ecore_IMF_Event_Key_Up ecore_ev;
290 * ecore_imf_evas_event_key_up_wrap(ev, &ecore_ev);
291 * if (ecore_imf_context_filter_event(imf_context,
292 * ECORE_IMF_EVENT_KEY_UP,
293 * (Ecore_IMF_Event *)&ecore_ev))
294 * return;
295 * }
296 * }
297 *
298 * evas_object_event_callback_add(obj, EVAS_CALLBACK_KEY_UP, _key_up_cb, data);
299 * @endcode
300 */
301EAPI void
302ecore_imf_evas_event_key_up_wrap(Evas_Event_Key_Up *evas_event,
303 Ecore_IMF_Event_Key_Up *imf_event)
304{
305 if (!evas_event)
306 {
307 EINA_LOG_ERR("Evas event is missing");
308 return;
309 }
310
311 if (!imf_event)
312 {
313 EINA_LOG_ERR("Imf event is missing");
314 return;
315 }
316
317 imf_event->keyname = evas_event->keyname ? evas_event->keyname : _ecore_imf_evas_event_empty;
318 imf_event->key = evas_event->key ? evas_event->key : _ecore_imf_evas_event_empty;
319 imf_event->string = evas_event->string ? evas_event->string : _ecore_imf_evas_event_empty;
320 imf_event->compose = evas_event->compose ? evas_event->compose : _ecore_imf_evas_event_empty;
321 imf_event->timestamp = evas_event->timestamp;
322 _ecore_imf_evas_event_modifiers_wrap(evas_event->modifiers, &imf_event->modifiers);
323 _ecore_imf_evas_event_locks_wrap(evas_event->locks, &imf_event->locks);
324}
diff --git a/src/lib/ecore_imf/ecore_imf_module.c b/src/lib/ecore_imf/ecore_imf_module.c
new file mode 100644
index 0000000000..cbdee47178
--- /dev/null
+++ b/src/lib/ecore_imf/ecore_imf_module.c
@@ -0,0 +1,212 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6#include <stdlib.h>
7#include <string.h>
8#include <limits.h>
9
10#include <Ecore.h>
11#include <ecore_private.h>
12
13#include "Ecore_IMF.h"
14#include "ecore_imf_private.h"
15
16static void _ecore_imf_module_free(Ecore_IMF_Module *module);
17static int _ecore_imf_modules_exists(const char *ctx_id);
18
19typedef struct _Ecore_IMF_Selector
20{
21 const char *toselect;
22 void *selected;
23} Ecore_IMF_Selector;
24
25static Eina_Hash *modules = NULL;
26static Eina_Array *module_list = NULL;
27
28void
29ecore_imf_module_init(void)
30{
31 char *homedir;
32
33 module_list = eina_module_list_get(NULL, PACKAGE_LIB_DIR "/ecore/immodules", 0, NULL, NULL);
34 homedir = eina_module_environment_path_get("HOME", "/.ecore/immodules");
35 if (homedir)
36 {
37 module_list = eina_module_list_get(module_list, homedir, 0, NULL, NULL);
38 free(homedir);
39 }
40 eina_module_list_load(module_list);
41}
42
43void
44ecore_imf_module_shutdown(void)
45{
46 if (modules)
47 {
48 eina_hash_free(modules);
49 modules = NULL;
50 }
51 if (module_list)
52 {
53 eina_module_list_free(module_list);
54 eina_array_free(module_list);
55 module_list = NULL;
56 }
57}
58
59static Eina_Bool
60_hash_module_available_get(const Eina_Hash *hash EINA_UNUSED, int *data, void *list)
61{
62 *(Eina_List**)list = eina_list_append(*(Eina_List**)list, data);
63 return EINA_TRUE;
64}
65
66Eina_List *
67ecore_imf_module_available_get(void)
68{
69 Eina_List *values = NULL;
70 Eina_Iterator *it = NULL;
71
72 if (!modules) return NULL;
73
74 it = eina_hash_iterator_data_new(modules);
75 if (!it)
76 return NULL;
77
78 eina_iterator_foreach(it, EINA_EACH_CB(_hash_module_available_get), &values);
79 eina_iterator_free(it);
80
81 return values;
82}
83
84Ecore_IMF_Module *
85ecore_imf_module_get(const char *ctx_id)
86{
87 if (!modules) return NULL;
88 return eina_hash_find(modules, ctx_id);
89}
90
91Ecore_IMF_Context *
92ecore_imf_module_context_create(const char *ctx_id)
93{
94 Ecore_IMF_Module *module;
95 Ecore_IMF_Context *ctx = NULL;
96
97 if (!modules) return NULL;
98 module = eina_hash_find(modules, ctx_id);
99 if (module)
100 {
101 ctx = module->create();
102 if (!ECORE_MAGIC_CHECK(ctx, ECORE_MAGIC_CONTEXT))
103 {
104 ECORE_MAGIC_FAIL(ctx, ECORE_MAGIC_CONTEXT,
105 "ecore_imf_module_context_create");
106 return NULL;
107 }
108 ctx->module = module;
109 }
110 return ctx;
111}
112
113static Eina_Bool
114_hash_ids_get(const Eina_Hash *hash EINA_UNUSED, const char *key, void *list)
115{
116 *(Eina_List**)list = eina_list_append(*(Eina_List**)list, key);
117 return EINA_TRUE;
118}
119
120Eina_List *
121ecore_imf_module_context_ids_get(void)
122{
123 Eina_List *l = NULL;
124 Eina_Iterator *it = NULL;
125
126 if (!modules) return NULL;
127
128 it = eina_hash_iterator_key_new(modules);
129 if (!it)
130 return NULL;
131
132 eina_iterator_foreach(it, EINA_EACH_CB(_hash_ids_get), &l);
133 eina_iterator_free(it);
134
135 return l;
136}
137
138static Eina_Bool
139_hash_ids_by_canvas_type_get(const Eina_Hash *hash EINA_UNUSED, void *data, void *fdata)
140{
141 Ecore_IMF_Module *module = data;
142 Ecore_IMF_Selector *selector = fdata;
143
144 if (!strcmp(module->info->canvas_type, selector->toselect))
145 selector->selected = eina_list_append(selector->selected, (void *)module->info->id);
146
147 return EINA_TRUE;
148}
149
150Eina_List *
151ecore_imf_module_context_ids_by_canvas_type_get(const char *canvas_type)
152{
153 Ecore_IMF_Selector selector;
154 Eina_List *values = NULL;
155 Eina_Iterator *it = NULL;
156
157 if (!modules) return NULL;
158
159 if (!canvas_type)
160 return ecore_imf_module_context_ids_get();
161
162 it = eina_hash_iterator_data_new(modules);
163 if (!it)
164 return NULL;
165
166 selector.toselect = canvas_type;
167 selector.selected = values;
168 eina_iterator_foreach(it, EINA_EACH_CB(_hash_ids_by_canvas_type_get), &selector);
169 eina_iterator_free(it);
170
171 return values;
172}
173
174EAPI void
175ecore_imf_module_register(const Ecore_IMF_Context_Info *info,
176 Ecore_IMF_Context *(*imf_module_create)(void),
177 Ecore_IMF_Context *(*imf_module_exit)(void))
178{
179 Ecore_IMF_Module *module;
180
181 if (_ecore_imf_modules_exists(info->id)) return;
182
183 if (!modules)
184 modules = eina_hash_string_superfast_new(EINA_FREE_CB(_ecore_imf_module_free));
185
186 module = malloc(sizeof(Ecore_IMF_Module));
187 module->info = info;
188 /* cache imf_module_create as it may be used several times */
189 module->create = imf_module_create;
190 module->exit = imf_module_exit;
191
192 eina_hash_add(modules, info->id, module);
193}
194
195static void
196_ecore_imf_module_free(Ecore_IMF_Module *module)
197{
198 if (module->exit) module->exit();
199 free(module);
200}
201
202static int
203_ecore_imf_modules_exists(const char *ctx_id)
204{
205 if (!modules) return 0;
206 if (!ctx_id) return 0;
207
208 if (eina_hash_find(modules, ctx_id))
209 return 1;
210
211 return 0;
212}
diff --git a/src/lib/ecore_imf/ecore_imf_private.h b/src/lib/ecore_imf/ecore_imf_private.h
new file mode 100644
index 0000000000..b4ff0f2ee0
--- /dev/null
+++ b/src/lib/ecore_imf/ecore_imf_private.h
@@ -0,0 +1,84 @@
1#ifndef _ECORE_IMF_PRIVATE_H
2#define _ECORE_IMF_PRIVATE_H
3
4#define ECORE_MAGIC_CONTEXT 0x56c1b39a
5
6#ifdef ECORE_IMF_DEFAULT_LOG_COLOR
7#undef ECORE_IMF_DEFAULT_LOG_COLOR
8#endif
9#define ECORE_IMF_DEFAULT_LOG_COLOR EINA_COLOR_BLUE
10
11extern int _ecore_imf_log_dom;
12#ifdef ERR
13# undef ERR
14#endif
15#define ERR(...) EINA_LOG_DOM_ERR(_ecore_imf_log_dom, __VA_ARGS__)
16
17#ifdef DBG
18# undef DBG
19#endif
20#define DBG(...) EINA_LOG_DOM_DBG(_ecore_imf_log_dom, __VA_ARGS__)
21
22#ifdef INF
23# undef INF
24#endif
25#define INF(...) EINA_LOG_DOM_INFO(_ecore_imf_log_dom, __VA_ARGS__)
26
27#ifdef WRN
28# undef WRN
29#endif
30#define WRN(...) EINA_LOG_DOM_WARN(_ecore_imf_log_dom, __VA_ARGS__)
31
32#ifdef CRIT
33# undef CRIT
34#endif
35#define CRIT(...) EINA_LOG_DOM_CRIT(_ecore_imf_log_dom, __VA_ARGS__)
36
37typedef struct _Ecore_IMF_Module Ecore_IMF_Module;
38typedef struct _Ecore_IMF_Func_Node Ecore_IMF_Func_Node;
39
40struct _Ecore_IMF_Context
41{
42 ECORE_MAGIC;
43 const Ecore_IMF_Module *module;
44 const Ecore_IMF_Context_Class *klass;
45 void *data;
46 int input_mode;
47 void *window;
48 void *client_canvas;
49 Eina_Bool (*retrieve_surrounding_func)(void *data, Ecore_IMF_Context *ctx, char **text, int *cursor_pos);
50 void *retrieve_surrounding_data;
51 Eina_List *callbacks;
52 Ecore_IMF_Autocapital_Type autocapital_type;
53 Ecore_IMF_Input_Panel_Layout input_panel_layout;
54 Ecore_IMF_Input_Panel_Lang input_panel_lang;
55 Ecore_IMF_Input_Panel_Return_Key_Type input_panel_return_key_type;
56 Eina_Bool allow_prediction : 1;
57 Eina_Bool input_panel_enabled : 1;
58 Eina_Bool input_panel_return_key_disabled : 1;
59 Eina_Bool input_panel_caps_lock_mode : 1;
60};
61
62struct _Ecore_IMF_Module
63{
64 const Ecore_IMF_Context_Info *info;
65 Ecore_IMF_Context *(*create)(void);
66 Ecore_IMF_Context *(*exit)(void);
67};
68
69struct _Ecore_IMF_Func_Node
70{
71 void (*func) ();
72 const void *data;
73 Ecore_IMF_Callback_Type type;
74};
75
76void ecore_imf_module_init(void);
77void ecore_imf_module_shutdown(void);
78Eina_List *ecore_imf_module_available_get(void);
79Ecore_IMF_Module *ecore_imf_module_get(const char *ctx_id);
80Ecore_IMF_Context *ecore_imf_module_context_create(const char *ctx_id);
81Eina_List *ecore_imf_module_context_ids_get(void);
82Eina_List *ecore_imf_module_context_ids_by_canvas_type_get(const char *canvas_type);
83
84#endif