summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac18
-rw-r--r--src/Makefile_Ecore_IMF.am26
-rw-r--r--src/modules/ecore_imf/wayland/text-client-protocol.h544
-rw-r--r--src/modules/ecore_imf/wayland/text-protocol.c94
-rw-r--r--src/modules/ecore_imf/wayland/wayland_imcontext.c778
-rw-r--r--src/modules/ecore_imf/wayland/wayland_imcontext.h70
-rw-r--r--src/modules/ecore_imf/wayland/wayland_module.c154
7 files changed, 1684 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac
index 4a6a4bec41..556f996afc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2771,6 +2771,7 @@ want_ecore_imf="yes"
2771want_ecore_imf_xim="no" 2771want_ecore_imf_xim="no"
2772want_ecore_imf_scim="no" 2772want_ecore_imf_scim="no"
2773want_ecore_imf_ibus="no" 2773want_ecore_imf_ibus="no"
2774want_ecore_imf_wayland="no"
2774 2775
2775if test "${have_wince}" = "yes"; then 2776if test "${have_wince}" = "yes"; then
2776 want_ecore_imf="no" 2777 want_ecore_imf="no"
@@ -2782,6 +2783,9 @@ else
2782 want_ecore_imf_xim="yes" 2783 want_ecore_imf_xim="yes"
2783 want_ecore_imf_scim="yes" 2784 want_ecore_imf_scim="yes"
2784 want_ecore_imf_ibus="yes" 2785 want_ecore_imf_ibus="yes"
2786 if test "${want_wayland}" = "yes"; then
2787 want_ecore_imf_wayland="yes"
2788 fi
2785 fi 2789 fi
2786fi 2790fi
2787 2791
@@ -2851,6 +2855,20 @@ fi
2851AM_CONDITIONAL([BUILD_ECORE_IMF_XIM], [test "x${have_ecore_imf_xim}" = "xyes"]) 2855AM_CONDITIONAL([BUILD_ECORE_IMF_XIM], [test "x${have_ecore_imf_xim}" = "xyes"])
2852EFL_ADD_FEATURE([ECORE_IMF], [xim]) 2856EFL_ADD_FEATURE([ECORE_IMF], [xim])
2853 2857
2858# wayland
2859if test "x${want_ecore_imf_wayland}" = "xyes" ; then
2860 PKG_CHECK_MODULES([WAYLAND],
2861 [wayland-client],
2862 [
2863 have_ecore_imf_wayland="yes"
2864 AC_DEFINE([BUILD_ECORE_IMF_WAYLAND], [1], [Ecore Imf Wayland Support])
2865 ],
2866 [have_ecore_imf_wayland="no"])
2867fi
2868
2869AM_CONDITIONAL([BUILD_ECORE_IMF_WAYLAND], [test "x${have_ecore_imf_wayland}" = "xyes"])
2870EFL_ADD_FEATURE([ECORE_IMF], [wayland], [${want_ecore_imf_wayland}])
2871
2854### Checks for header files 2872### Checks for header files
2855 2873
2856### Checks for types 2874### Checks for types
diff --git a/src/Makefile_Ecore_IMF.am b/src/Makefile_Ecore_IMF.am
index cb6176986b..c4c78721c9 100644
--- a/src/Makefile_Ecore_IMF.am
+++ b/src/Makefile_Ecore_IMF.am
@@ -101,3 +101,29 @@ modules_ecore_imf_xim_module_la_DEPENDENCIES = \
101modules_ecore_imf_xim_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@ 101modules_ecore_imf_xim_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
102modules_ecore_imf_xim_module_la_LIBTOOLFLAGS = --tag=disable-static 102modules_ecore_imf_xim_module_la_LIBTOOLFLAGS = --tag=disable-static
103endif 103endif
104
105# Wayland
106if BUILD_ECORE_IMF_WAYLAND
107ecoreimfwaylandpkgdir = $(libdir)/ecore_imf/modules/wayland/$(MODULE_ARCH)
108ecoreimfwaylandpkg_LTLIBRARIES = modules/ecore_imf/wayland/module.la
109modules_ecore_imf_wayland_module_la_SOURCES = \
110modules/ecore_imf/wayland/wayland_module.c \
111modules/ecore_imf/wayland/wayland_imcontext.c \
112modules/ecore_imf/wayland/wayland_imcontext.h \
113modules/ecore_imf/wayland/text-client-protocol.h \
114modules/ecore_imf/wayland/text-protocol.c
115modules_ecore_imf_wayland_module_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
116@ECORE_IMF_CFLAGS@ \
117@ECORE_EVAS_CFLAGS@ \
118@ECORE_WAYLAND_CFLAGS@
119modules_ecore_imf_wayland_module_la_LIBADD = \
120@USE_ECORE_IMF_LIBS@ \
121@USE_ECORE_EVAS_LIBS@ \
122@USE_ECORE_WAYLAND_LIBS@
123modules_ecore_imf_wayland_module_la_DEPENDENCIES = \
124@USE_ECORE_IMF_INTERNAL_LIBS@ \
125@USE_ECORE_EVAS_INTERNAL_LIBS@ \
126@USE_ECORE_WAYLAND_INTERNAL_LIBS@
127modules_ecore_imf_wayland_module_la_LDFLAGS = -module @EFL_LTMODULE_FLAGS@
128modules_ecore_imf_wayland_module_la_LIBTOOLFLAGS = --tag=disable-static
129endif
diff --git a/src/modules/ecore_imf/wayland/text-client-protocol.h b/src/modules/ecore_imf/wayland/text-client-protocol.h
new file mode 100644
index 0000000000..cfea94bbeb
--- /dev/null
+++ b/src/modules/ecore_imf/wayland/text-client-protocol.h
@@ -0,0 +1,544 @@
1/*
2 * Copyright © 2012, 2013 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this
5 * software and its documentation for any purpose is hereby granted
6 * without fee, provided that the above copyright notice appear in
7 * all copies and that both that copyright notice and this permission
8 * notice appear in supporting documentation, and that the name of
9 * the copyright holders not be used in advertising or publicity
10 * pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no
12 * representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied
14 * warranty.
15 *
16 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23 * THIS SOFTWARE.
24 */
25
26#ifndef TEXT_CLIENT_PROTOCOL_H
27#define TEXT_CLIENT_PROTOCOL_H
28
29#ifdef __cplusplus
30extern "C" {
31#endif
32
33#include <stdint.h>
34#include <stddef.h>
35#include "wayland-client.h"
36
37struct wl_client;
38struct wl_resource;
39
40struct wl_text_input;
41struct wl_text_input_manager;
42
43extern const struct wl_interface wl_text_input_interface;
44extern const struct wl_interface wl_text_input_manager_interface;
45
46#ifndef WL_TEXT_INPUT_CONTENT_HINT_ENUM
47#define WL_TEXT_INPUT_CONTENT_HINT_ENUM
48/**
49 * wl_text_input_content_hint - content hint
50 * @WL_TEXT_INPUT_CONTENT_HINT_NONE: no special behaviour
51 * @WL_TEXT_INPUT_CONTENT_HINT_DEFAULT: auto completion, correction and
52 * capitalization
53 * @WL_TEXT_INPUT_CONTENT_HINT_PASSWORD: hidden and sensitive text
54 * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION: suggest word completions
55 * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION: suggest word corrections
56 * @WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION: switch to uppercase
57 * letters at the start of a sentence
58 * @WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE: prefer lowercase letters
59 * @WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE: prefer uppercase letters
60 * @WL_TEXT_INPUT_CONTENT_HINT_TITLECASE: prefer casing for titles and
61 * headings (can be language dependent)
62 * @WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT: characters should be hidden
63 * @WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA: typed text should not be
64 * stored
65 * @WL_TEXT_INPUT_CONTENT_HINT_LATIN: just latin characters should be
66 * entered
67 * @WL_TEXT_INPUT_CONTENT_HINT_MULTILINE: the text input is multiline
68 *
69 * Content hint is a bitmask to allow to modify the behavior of the text
70 * input.
71 */
72enum wl_text_input_content_hint {
73 WL_TEXT_INPUT_CONTENT_HINT_NONE = 0x0,
74 WL_TEXT_INPUT_CONTENT_HINT_DEFAULT = 0x7,
75 WL_TEXT_INPUT_CONTENT_HINT_PASSWORD = 0xc0,
76 WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION = 0x1,
77 WL_TEXT_INPUT_CONTENT_HINT_AUTO_CORRECTION = 0x2,
78 WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION = 0x4,
79 WL_TEXT_INPUT_CONTENT_HINT_LOWERCASE = 0x8,
80 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE = 0x10,
81 WL_TEXT_INPUT_CONTENT_HINT_TITLECASE = 0x20,
82 WL_TEXT_INPUT_CONTENT_HINT_HIDDEN_TEXT = 0x40,
83 WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA = 0x80,
84 WL_TEXT_INPUT_CONTENT_HINT_LATIN = 0x100,
85 WL_TEXT_INPUT_CONTENT_HINT_MULTILINE = 0x200,
86};
87#endif /* WL_TEXT_INPUT_CONTENT_HINT_ENUM */
88
89#ifndef WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM
90#define WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM
91/**
92 * wl_text_input_content_purpose - content purpose
93 * @WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL: default input, allowing all
94 * characters
95 * @WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA: allow only alphabetic characters
96 * @WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS: allow only digits
97 * @WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER: input a number (including
98 * decimal separator and sign)
99 * @WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE: input a phone number
100 * @WL_TEXT_INPUT_CONTENT_PURPOSE_URL: input an URL
101 * @WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL: input an email address
102 * @WL_TEXT_INPUT_CONTENT_PURPOSE_NAME: input a name of a person
103 * @WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD: input a password (combine
104 * with password or sensitive_data hint)
105 * @WL_TEXT_INPUT_CONTENT_PURPOSE_DATE: input a date
106 * @WL_TEXT_INPUT_CONTENT_PURPOSE_TIME: input a time
107 * @WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME: input a date and time
108 * @WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL: input for a terminal
109 *
110 * The content purpose allows to specify the primary purpose of a text
111 * input.
112 *
113 * This allows an input method to show special purpose input panels with
114 * extra characters or to disallow some characters.
115 */
116enum wl_text_input_content_purpose {
117 WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL = 0,
118 WL_TEXT_INPUT_CONTENT_PURPOSE_ALPHA = 1,
119 WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS = 2,
120 WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER = 3,
121 WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE = 4,
122 WL_TEXT_INPUT_CONTENT_PURPOSE_URL = 5,
123 WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL = 6,
124 WL_TEXT_INPUT_CONTENT_PURPOSE_NAME = 7,
125 WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD = 8,
126 WL_TEXT_INPUT_CONTENT_PURPOSE_DATE = 9,
127 WL_TEXT_INPUT_CONTENT_PURPOSE_TIME = 10,
128 WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME = 11,
129 WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL = 12,
130};
131#endif /* WL_TEXT_INPUT_CONTENT_PURPOSE_ENUM */
132
133#ifndef WL_TEXT_INPUT_PREEDIT_STYLE_ENUM
134#define WL_TEXT_INPUT_PREEDIT_STYLE_ENUM
135enum wl_text_input_preedit_style {
136 WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT = 0,
137 WL_TEXT_INPUT_PREEDIT_STYLE_NONE = 1,
138 WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE = 2,
139 WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE = 3,
140 WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT = 4,
141 WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE = 5,
142 WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION = 6,
143 WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT = 7,
144};
145#endif /* WL_TEXT_INPUT_PREEDIT_STYLE_ENUM */
146
147#ifndef WL_TEXT_INPUT_TEXT_DIRECTION_ENUM
148#define WL_TEXT_INPUT_TEXT_DIRECTION_ENUM
149enum wl_text_input_text_direction {
150 WL_TEXT_INPUT_TEXT_DIRECTION_AUTO = 0,
151 WL_TEXT_INPUT_TEXT_DIRECTION_LTR = 1,
152 WL_TEXT_INPUT_TEXT_DIRECTION_RTL = 2,
153};
154#endif /* WL_TEXT_INPUT_TEXT_DIRECTION_ENUM */
155
156/**
157 * wl_text_input - text input
158 * @enter: enter event
159 * @leave: leave event
160 * @modifiers_map: modifiers map
161 * @input_panel_state: state of the input panel
162 * @preedit_string: pre-edit
163 * @preedit_styling: pre-edit styling
164 * @preedit_cursor: pre-edit cursor
165 * @commit_string: commit
166 * @cursor_position: set cursor to new position
167 * @delete_surrounding_text: delete surrounding text
168 * @keysym: keysym
169 * @language: language
170 * @text_direction: text direction
171 *
172 * An object used for text input. Adds support for text input and input
173 * methods to applications. A text-input object is created from a
174 * wl_text_input_manager and corresponds typically to a text entry in an
175 * application. Requests are used to activate/deactivate the text-input
176 * object and set state information like surrounding and selected text or
177 * the content type. The information about entered text is sent to the
178 * text-input object via the pre-edit and commit events. Using this
179 * interface removes the need for applications to directly process hardware
180 * key events and compose text out of them.
181 *
182 * Text is generally UTF-8 encoded, indices and lengths are in Unicode
183 * characters.
184 *
185 * Serials are used to synchronize the state between the text input and an
186 * input method. New serials are sent by the text input in the commit_state
187 * request and are used by the input method to indicate the known text
188 * input state in events like preedit_string, commit_string, and keysym.
189 * The text input can then ignore events from the input method which are
190 * based on an outdated state (for example after a reset).
191 */
192struct wl_text_input_listener {
193 /**
194 * enter - enter event
195 * @surface: (none)
196 *
197 * Notify the text-input object when it received focus. Typically
198 * in response to an activate request.
199 */
200 void (*enter)(void *data,
201 struct wl_text_input *wl_text_input,
202 struct wl_surface *surface);
203 /**
204 * leave - leave event
205 *
206 * Notify the text-input object when it lost focus. Either in
207 * response to a deactivate request or when the assigned surface
208 * lost focus or was destroyed.
209 */
210 void (*leave)(void *data,
211 struct wl_text_input *wl_text_input);
212 /**
213 * modifiers_map - modifiers map
214 * @map: (none)
215 *
216 * Transfer an array of 0-terminated modifiers names. The
217 * position in the array is the index of the modifier as used in
218 * the modifiers bitmask in the keysym event.
219 */
220 void (*modifiers_map)(void *data,
221 struct wl_text_input *wl_text_input,
222 struct wl_array *map);
223 /**
224 * input_panel_state - state of the input panel
225 * @state: (none)
226 *
227 * Notify when the visibility state of the input panel changed.
228 */
229 void (*input_panel_state)(void *data,
230 struct wl_text_input *wl_text_input,
231 uint32_t state);
232 /**
233 * preedit_string - pre-edit
234 * @serial: serial of the latest known text input state
235 * @text: (none)
236 * @commit: (none)
237 *
238 * Notify when a new composing text (pre-edit) should be set
239 * around the current cursor position. Any previously set composing
240 * text should be removed.
241 *
242 * The commit text can be used to replace the preedit text on reset
243 * (for example on unfocus).
244 *
245 * The text input should also handle all preedit_style and
246 * preedit_cursor events occuring directly before preedit_string.
247 */
248 void (*preedit_string)(void *data,
249 struct wl_text_input *wl_text_input,
250 uint32_t serial,
251 const char *text,
252 const char *commit);
253 /**
254 * preedit_styling - pre-edit styling
255 * @index: (none)
256 * @length: (none)
257 * @style: (none)
258 *
259 * Sets styling information on composing text. The style is
260 * applied for length Unicode characters from index relative to the
261 * beginning of the composing text (as Unicode character offset).
262 * Multiple styles can be applied to a composing text by sending
263 * multiple preedit_styling events.
264 *
265 * This event is handled as part of a following preedit_string
266 * event.
267 */
268 void (*preedit_styling)(void *data,
269 struct wl_text_input *wl_text_input,
270 uint32_t index,
271 uint32_t length,
272 uint32_t style);
273 /**
274 * preedit_cursor - pre-edit cursor
275 * @index: (none)
276 *
277 * Sets the cursor position inside the composing text (as Unicode
278 * character offset) relative to the start of the composing text.
279 * When index is a negative number no cursor is shown.
280 *
281 * This event is handled as part of a following preedit_string
282 * event.
283 */
284 void (*preedit_cursor)(void *data,
285 struct wl_text_input *wl_text_input,
286 int32_t index);
287 /**
288 * commit_string - commit
289 * @serial: serial of the latest known text input state
290 * @text: (none)
291 *
292 * Notify when text should be inserted into the editor widget.
293 * The text to commit could be either just a single character after
294 * a key press or the result of some composing (pre-edit). It could
295 * be also an empty text when some text should be removed (see
296 * delete_surrounding_text) or when the input cursor should be
297 * moved (see cursor_position).
298 *
299 * Any previously set composing text should be removed.
300 */
301 void (*commit_string)(void *data,
302 struct wl_text_input *wl_text_input,
303 uint32_t serial,
304 const char *text);
305 /**
306 * cursor_position - set cursor to new position
307 * @index: (none)
308 * @anchor: (none)
309 *
310 * Notify when the cursor or anchor position should be modified.
311 *
312 * This event should be handled as part of a following
313 * commit_string event.
314 */
315 void (*cursor_position)(void *data,
316 struct wl_text_input *wl_text_input,
317 int32_t index,
318 int32_t anchor);
319 /**
320 * delete_surrounding_text - delete surrounding text
321 * @index: (none)
322 * @length: (none)
323 *
324 * Notify when the text around the current cursor position should
325 * be deleted.
326 *
327 * Index is relative to the current cursor (in Unicode characters).
328 * Length is the length of deleted text (in Unicode characters).
329 *
330 * This event should be handled as part of a following
331 * commit_string event.
332 */
333 void (*delete_surrounding_text)(void *data,
334 struct wl_text_input *wl_text_input,
335 int32_t index,
336 uint32_t length);
337 /**
338 * keysym - keysym
339 * @serial: serial of the latest known text input state
340 * @time: (none)
341 * @sym: (none)
342 * @state: (none)
343 * @modifiers: (none)
344 *
345 * Notify when a key event was sent. Key events should not be
346 * used for normal text input operations, which should be done with
347 * commit_string, delete_surrounding_text, etc. The key event
348 * follows the wl_keyboard key event convention. Sym is a XKB
349 * keysym, state a wl_keyboard key_state. Modifiers are a mask for
350 * effective modifiers (where the modifier indices are set by the
351 * modifiers_map event)
352 */
353 void (*keysym)(void *data,
354 struct wl_text_input *wl_text_input,
355 uint32_t serial,
356 uint32_t time,
357 uint32_t sym,
358 uint32_t state,
359 uint32_t modifiers);
360 /**
361 * language - language
362 * @serial: serial of the latest known text input state
363 * @language: (none)
364 *
365 * Sets the language of the input text. The "language" argument
366 * is a RFC-3066 format language tag.
367 */
368 void (*language)(void *data,
369 struct wl_text_input *wl_text_input,
370 uint32_t serial,
371 const char *language);
372 /**
373 * text_direction - text direction
374 * @serial: serial of the latest known text input state
375 * @direction: (none)
376 *
377 * Sets the text direction of input text.
378 *
379 * It is mainly needed for showing input cursor on correct side of
380 * the editor when there is no input yet done and making sure
381 * neutral direction text is laid out properly.
382 */
383 void (*text_direction)(void *data,
384 struct wl_text_input *wl_text_input,
385 uint32_t serial,
386 uint32_t direction);
387};
388
389static inline int
390wl_text_input_add_listener(struct wl_text_input *wl_text_input,
391 const struct wl_text_input_listener *listener, void *data)
392{
393 return wl_proxy_add_listener((struct wl_proxy *) wl_text_input,
394 (void (**)(void)) listener, data);
395}
396
397#define WL_TEXT_INPUT_ACTIVATE 0
398#define WL_TEXT_INPUT_DEACTIVATE 1
399#define WL_TEXT_INPUT_SHOW_INPUT_PANEL 2
400#define WL_TEXT_INPUT_HIDE_INPUT_PANEL 3
401#define WL_TEXT_INPUT_RESET 4
402#define WL_TEXT_INPUT_SET_SURROUNDING_TEXT 5
403#define WL_TEXT_INPUT_SET_CONTENT_TYPE 6
404#define WL_TEXT_INPUT_SET_CURSOR_RECTANGLE 7
405#define WL_TEXT_INPUT_SET_PREFERRED_LANGUAGE 8
406#define WL_TEXT_INPUT_COMMIT_STATE 9
407#define WL_TEXT_INPUT_INVOKE_ACTION 10
408
409static inline void
410wl_text_input_set_user_data(struct wl_text_input *wl_text_input, void *user_data)
411{
412 wl_proxy_set_user_data((struct wl_proxy *) wl_text_input, user_data);
413}
414
415static inline void *
416wl_text_input_get_user_data(struct wl_text_input *wl_text_input)
417{
418 return wl_proxy_get_user_data((struct wl_proxy *) wl_text_input);
419}
420
421static inline void
422wl_text_input_destroy(struct wl_text_input *wl_text_input)
423{
424 wl_proxy_destroy((struct wl_proxy *) wl_text_input);
425}
426
427static inline void
428wl_text_input_activate(struct wl_text_input *wl_text_input, struct wl_seat *seat, struct wl_surface *surface)
429{
430 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
431 WL_TEXT_INPUT_ACTIVATE, seat, surface);
432}
433
434static inline void
435wl_text_input_deactivate(struct wl_text_input *wl_text_input, struct wl_seat *seat)
436{
437 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
438 WL_TEXT_INPUT_DEACTIVATE, seat);
439}
440
441static inline void
442wl_text_input_show_input_panel(struct wl_text_input *wl_text_input)
443{
444 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
445 WL_TEXT_INPUT_SHOW_INPUT_PANEL);
446}
447
448static inline void
449wl_text_input_hide_input_panel(struct wl_text_input *wl_text_input)
450{
451 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
452 WL_TEXT_INPUT_HIDE_INPUT_PANEL);
453}
454
455static inline void
456wl_text_input_reset(struct wl_text_input *wl_text_input)
457{
458 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
459 WL_TEXT_INPUT_RESET);
460}
461
462static inline void
463wl_text_input_set_surrounding_text(struct wl_text_input *wl_text_input, const char *text, uint32_t cursor, uint32_t anchor)
464{
465 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
466 WL_TEXT_INPUT_SET_SURROUNDING_TEXT, text, cursor, anchor);
467}
468
469static inline void
470wl_text_input_set_content_type(struct wl_text_input *wl_text_input, uint32_t hint, uint32_t purpose)
471{
472 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
473 WL_TEXT_INPUT_SET_CONTENT_TYPE, hint, purpose);
474}
475
476static inline void
477wl_text_input_set_cursor_rectangle(struct wl_text_input *wl_text_input, int32_t x, int32_t y, int32_t width, int32_t height)
478{
479 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
480 WL_TEXT_INPUT_SET_CURSOR_RECTANGLE, x, y, width, height);
481}
482
483static inline void
484wl_text_input_set_preferred_language(struct wl_text_input *wl_text_input, const char *language)
485{
486 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
487 WL_TEXT_INPUT_SET_PREFERRED_LANGUAGE, language);
488}
489
490static inline void
491wl_text_input_commit_state(struct wl_text_input *wl_text_input, uint32_t serial)
492{
493 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
494 WL_TEXT_INPUT_COMMIT_STATE, serial);
495}
496
497static inline void
498wl_text_input_invoke_action(struct wl_text_input *wl_text_input, uint32_t button, uint32_t index)
499{
500 wl_proxy_marshal((struct wl_proxy *) wl_text_input,
501 WL_TEXT_INPUT_INVOKE_ACTION, button, index);
502}
503
504#define WL_TEXT_INPUT_MANAGER_CREATE_TEXT_INPUT 0
505
506static inline void
507wl_text_input_manager_set_user_data(struct wl_text_input_manager *wl_text_input_manager, void *user_data)
508{
509 wl_proxy_set_user_data((struct wl_proxy *) wl_text_input_manager, user_data);
510}
511
512static inline void *
513wl_text_input_manager_get_user_data(struct wl_text_input_manager *wl_text_input_manager)
514{
515 return wl_proxy_get_user_data((struct wl_proxy *) wl_text_input_manager);
516}
517
518static inline void
519wl_text_input_manager_destroy(struct wl_text_input_manager *wl_text_input_manager)
520{
521 wl_proxy_destroy((struct wl_proxy *) wl_text_input_manager);
522}
523
524static inline struct wl_text_input *
525wl_text_input_manager_create_text_input(struct wl_text_input_manager *wl_text_input_manager)
526{
527 struct wl_proxy *id;
528
529 id = wl_proxy_create((struct wl_proxy *) wl_text_input_manager,
530 &wl_text_input_interface);
531 if (!id)
532 return NULL;
533
534 wl_proxy_marshal((struct wl_proxy *) wl_text_input_manager,
535 WL_TEXT_INPUT_MANAGER_CREATE_TEXT_INPUT, id);
536
537 return (struct wl_text_input *) id;
538}
539
540#ifdef __cplusplus
541}
542#endif
543
544#endif
diff --git a/src/modules/ecore_imf/wayland/text-protocol.c b/src/modules/ecore_imf/wayland/text-protocol.c
new file mode 100644
index 0000000000..af549d5866
--- /dev/null
+++ b/src/modules/ecore_imf/wayland/text-protocol.c
@@ -0,0 +1,94 @@
1/*
2 * Copyright © 2012, 2013 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this
5 * software and its documentation for any purpose is hereby granted
6 * without fee, provided that the above copyright notice appear in
7 * all copies and that both that copyright notice and this permission
8 * notice appear in supporting documentation, and that the name of
9 * the copyright holders not be used in advertising or publicity
10 * pertaining to distribution of the software without specific,
11 * written prior permission. The copyright holders make no
12 * representations about the suitability of this software for any
13 * purpose. It is provided "as is" without express or implied
14 * warranty.
15 *
16 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
22 * ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
23 * THIS SOFTWARE.
24 */
25
26#include <stdlib.h>
27#include <stdint.h>
28#include "wayland-util.h"
29
30extern const struct wl_interface wl_seat_interface;
31extern const struct wl_interface wl_surface_interface;
32extern const struct wl_interface wl_seat_interface;
33extern const struct wl_interface wl_surface_interface;
34extern const struct wl_interface wl_text_input_interface;
35
36static const struct wl_interface *types[] = {
37 NULL,
38 NULL,
39 NULL,
40 NULL,
41 NULL,
42 &wl_seat_interface,
43 &wl_surface_interface,
44 &wl_seat_interface,
45 &wl_surface_interface,
46 &wl_text_input_interface,
47};
48
49static const struct wl_message wl_text_input_requests[] = {
50 { "activate", "oo", types + 5 },
51 { "deactivate", "o", types + 7 },
52 { "show_input_panel", "", types + 0 },
53 { "hide_input_panel", "", types + 0 },
54 { "reset", "", types + 0 },
55 { "set_surrounding_text", "suu", types + 0 },
56 { "set_content_type", "uu", types + 0 },
57 { "set_cursor_rectangle", "iiii", types + 0 },
58 { "set_preferred_language", "s", types + 0 },
59 { "commit_state", "u", types + 0 },
60 { "invoke_action", "uu", types + 0 },
61};
62
63static const struct wl_message wl_text_input_events[] = {
64 { "enter", "o", types + 8 },
65 { "leave", "", types + 0 },
66 { "modifiers_map", "a", types + 0 },
67 { "input_panel_state", "u", types + 0 },
68 { "preedit_string", "uss", types + 0 },
69 { "preedit_styling", "uuu", types + 0 },
70 { "preedit_cursor", "i", types + 0 },
71 { "commit_string", "us", types + 0 },
72 { "cursor_position", "ii", types + 0 },
73 { "delete_surrounding_text", "iu", types + 0 },
74 { "keysym", "uuuuu", types + 0 },
75 { "language", "us", types + 0 },
76 { "text_direction", "uu", types + 0 },
77};
78
79WL_EXPORT const struct wl_interface wl_text_input_interface = {
80 "wl_text_input", 1,
81 11, wl_text_input_requests,
82 13, wl_text_input_events,
83};
84
85static const struct wl_message wl_text_input_manager_requests[] = {
86 { "create_text_input", "n", types + 9 },
87};
88
89WL_EXPORT const struct wl_interface wl_text_input_manager_interface = {
90 "wl_text_input_manager", 1,
91 1, wl_text_input_manager_requests,
92 0, NULL,
93};
94
diff --git a/src/modules/ecore_imf/wayland/wayland_imcontext.c b/src/modules/ecore_imf/wayland/wayland_imcontext.c
new file mode 100644
index 0000000000..f91b8a7893
--- /dev/null
+++ b/src/modules/ecore_imf/wayland/wayland_imcontext.c
@@ -0,0 +1,778 @@
1/*
2 * Copyright © 2012, 2013 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include <Ecore.h>
28#include <Ecore_Evas.h>
29#include <Ecore_Input.h>
30#include <Ecore_Wayland.h>
31
32#include "wayland_imcontext.h"
33
34struct _WaylandIMContext
35{
36 Ecore_IMF_Context *ctx;
37
38 struct wl_text_input_manager *text_input_manager;
39 struct wl_text_input *text_input;
40
41 Ecore_Wl_Window *window;
42 Evas *canvas;
43
44 char *preedit_text;
45 char *preedit_commit;
46 Eina_List *preedit_attrs;
47 int32_t preedit_cursor;
48
49 struct
50 {
51 Eina_List *attrs;
52 int32_t cursor;
53 } pending_preedit;
54
55 struct
56 {
57 int32_t cursor;
58 int32_t anchor;
59 uint32_t delete_index;
60 uint32_t delete_length;
61 } pending_commit;
62
63 struct
64 {
65 int x;
66 int y;
67 int width;
68 int height;
69 } cursor_location;
70
71 xkb_mod_mask_t control_mask;
72 xkb_mod_mask_t alt_mask;
73 xkb_mod_mask_t shift_mask;
74
75 uint32_t serial;
76 uint32_t reset_serial;
77};
78
79static unsigned int
80utf8_offset_to_characters(const char *str, int offset)
81{
82 int index = 0;
83 unsigned int i = 0;
84 for (; index < offset; i++)
85 eina_unicode_utf8_next_get(str, &index);
86
87 return i;
88}
89
90static void
91update_state(WaylandIMContext *imcontext)
92{
93 char *surrounding;
94 int cursor_pos;
95 Ecore_Evas *ee;
96 int canvas_x = 0, canvas_y = 0;
97
98 if (!imcontext->ctx)
99 return;
100
101 /* cursor_pos is a byte index */
102 if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos))
103 {
104 wl_text_input_set_surrounding_text(imcontext->text_input,
105 surrounding,
106 cursor_pos,
107 cursor_pos);
108 free(surrounding);
109 }
110
111 if (imcontext->canvas)
112 {
113 ee = ecore_evas_ecore_evas_get(imcontext->canvas);
114 if (ee)
115 ecore_evas_geometry_get(ee, &canvas_x, &canvas_y, NULL, NULL);
116 }
117
118 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "canvas (x: %d, y: %d)", canvas_x, canvas_y);
119
120 wl_text_input_set_cursor_rectangle(imcontext->text_input,
121 imcontext->cursor_location.x + canvas_x,
122 imcontext->cursor_location.y + canvas_y,
123 imcontext->cursor_location.width,
124 imcontext->cursor_location.height);
125
126 wl_text_input_commit_state(imcontext->text_input, ++imcontext->serial);
127}
128
129static Eina_Bool
130check_serial(WaylandIMContext *imcontext, uint32_t serial)
131{
132 Ecore_IMF_Preedit_Attr *attr;
133
134 if ((imcontext->serial - serial) > (imcontext->serial - imcontext->reset_serial))
135 {
136 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
137 "outdated serial: %u, current: %u, reset: %u",
138 serial, imcontext->serial, imcontext->reset_serial);
139
140 /* Clear pending data */
141 imcontext->pending_commit.delete_index = 0;
142 imcontext->pending_commit.delete_length = 0;
143 imcontext->pending_commit.cursor = 0;
144 imcontext->pending_commit.anchor = 0;
145
146 imcontext->pending_preedit.cursor = 0;
147 EINA_LIST_FREE(imcontext->pending_preedit.attrs, attr) free(attr);
148 imcontext->pending_preedit.attrs = NULL;
149
150 return EINA_FALSE;
151 }
152
153 return EINA_TRUE;
154}
155
156static void
157clear_preedit(WaylandIMContext *imcontext)
158{
159 Ecore_IMF_Preedit_Attr *attr;
160
161 imcontext->preedit_cursor = 0;
162
163 free(imcontext->preedit_text);
164 imcontext->preedit_text = NULL;
165
166 free(imcontext->preedit_commit);
167 imcontext->preedit_commit = NULL;
168
169 EINA_LIST_FREE(imcontext->preedit_attrs, attr)
170 free(attr);
171
172 imcontext->preedit_attrs = NULL;
173}
174
175static void
176text_input_commit_string(void *data,
177 struct wl_text_input *text_input EINA_UNUSED,
178 uint32_t serial,
179 const char *text)
180{
181 WaylandIMContext *imcontext = (WaylandIMContext *)data;
182 Eina_Bool old_preedit = EINA_FALSE;
183 char *surrounding;
184 int cursor_pos, cursor;
185 Ecore_IMF_Event_Delete_Surrounding ev;
186
187 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
188 "commit event (text: `%s', current pre-edit: `%s')",
189 text,
190 imcontext->preedit_text ? imcontext->preedit_text : "");
191
192 old_preedit = imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
193
194 if (!imcontext->ctx)
195 return;
196
197 if (!check_serial(imcontext, serial))
198 return;
199
200 if (old_preedit)
201 {
202 ecore_imf_context_preedit_end_event_add(imcontext->ctx);
203 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
204 }
205
206 clear_preedit(imcontext);
207
208 if (imcontext->pending_commit.delete_length > 0)
209 {
210 /* cursor_pos is a byte index */
211 if (ecore_imf_context_surrounding_get(imcontext->ctx, &surrounding, &cursor_pos))
212 {
213 ev.ctx = imcontext->ctx;
214 /* offset and n_chars are in characters */
215 ev.offset = utf8_offset_to_characters(surrounding, cursor_pos + imcontext->pending_commit.delete_index);
216 ev.n_chars = utf8_offset_to_characters(surrounding,
217 cursor_pos + imcontext->pending_commit.delete_index + imcontext->pending_commit.delete_length) - ev.offset;
218
219 /* cursor in characters */
220 cursor = utf8_offset_to_characters(surrounding, cursor_pos);
221
222 ev.offset -= cursor;
223
224 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
225 "delete on commit (text: `%s', offset `%d', length: `%d')",
226 surrounding, ev.offset, ev.n_chars);
227
228 ecore_imf_context_delete_surrounding_event_add(imcontext->ctx, ev.offset, ev.n_chars);
229 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
230 }
231 }
232
233 imcontext->pending_commit.delete_index = 0;
234 imcontext->pending_commit.delete_length = 0;
235 imcontext->pending_commit.cursor = 0;
236 imcontext->pending_commit.anchor = 0;
237
238 ecore_imf_context_commit_event_add(imcontext->ctx, text);
239 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)text);
240}
241
242static void
243commit_preedit(WaylandIMContext *imcontext)
244{
245 if (!imcontext->preedit_commit)
246 return;
247
248 if (!imcontext->ctx)
249 return;
250
251 ecore_imf_context_commit_event_add(imcontext->ctx, imcontext->preedit_commit);
252 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)imcontext->preedit_commit);
253}
254
255static void
256text_input_preedit_string(void *data,
257 struct wl_text_input *text_input EINA_UNUSED,
258 uint32_t serial,
259 const char *text,
260 const char *commit)
261{
262 WaylandIMContext *imcontext = (WaylandIMContext *)data;
263 Eina_Bool old_preedit = EINA_FALSE;
264
265 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
266 "preedit event (text: `%s', current pre-edit: `%s')",
267 text,
268 imcontext->preedit_text ? imcontext->preedit_text : "");
269
270 if (!check_serial(imcontext, serial))
271 return;
272
273 old_preedit = imcontext->preedit_text && strlen(imcontext->preedit_text) > 0;
274
275 clear_preedit(imcontext);
276
277 imcontext->preedit_text = strdup(text);
278 imcontext->preedit_commit = strdup(commit);
279 imcontext->preedit_cursor = utf8_offset_to_characters(text, imcontext->pending_preedit.cursor);
280 imcontext->preedit_attrs = imcontext->pending_preedit.attrs;
281
282 imcontext->pending_preedit.attrs = NULL;
283
284 if (!old_preedit)
285 {
286 ecore_imf_context_preedit_start_event_add(imcontext->ctx);
287 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
288 }
289
290 ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
291 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
292
293 if (strlen(imcontext->preedit_text) == 0)
294 {
295 ecore_imf_context_preedit_end_event_add(imcontext->ctx);
296 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
297 }
298}
299
300static void
301text_input_delete_surrounding_text(void *data,
302 struct wl_text_input *text_input EINA_UNUSED,
303 int32_t index,
304 uint32_t length)
305{
306 WaylandIMContext *imcontext = (WaylandIMContext *)data;
307
308 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
309 "delete surrounding text (index: %d, length: %u)",
310 index,
311 length);
312
313 imcontext->pending_commit.delete_index = index;
314 imcontext->pending_commit.delete_length = length;
315}
316
317static void
318text_input_cursor_position(void *data,
319 struct wl_text_input *text_input EINA_UNUSED,
320 int32_t index,
321 int32_t anchor)
322{
323 WaylandIMContext *imcontext = (WaylandIMContext *)data;
324
325 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
326 "cursor_position for next commit (index: %d, anchor: %d)",
327 index,
328 anchor);
329
330 imcontext->pending_commit.cursor = index;
331 imcontext->pending_commit.anchor = anchor;
332}
333
334static void
335text_input_preedit_styling(void *data,
336 struct wl_text_input *text_input EINA_UNUSED,
337 uint32_t index,
338 uint32_t length,
339 uint32_t style)
340{
341 WaylandIMContext *imcontext = (WaylandIMContext *)data;
342 Ecore_IMF_Preedit_Attr *attr = calloc(1, sizeof(*attr));
343
344 switch (style)
345 {
346 case WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT:
347 case WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE:
348 case WL_TEXT_INPUT_PREEDIT_STYLE_INCORRECT:
349 case WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT:
350 case WL_TEXT_INPUT_PREEDIT_STYLE_ACTIVE:
351 case WL_TEXT_INPUT_PREEDIT_STYLE_INACTIVE:
352 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
353 break;
354 case WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION:
355 attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
356 break;
357 }
358
359 attr->start_index = index;
360 attr->end_index = index + length;
361
362 imcontext->pending_preedit.attrs = eina_list_append(imcontext->pending_preedit.attrs, attr);
363}
364
365static void
366text_input_preedit_cursor(void *data,
367 struct wl_text_input *text_input EINA_UNUSED,
368 int32_t index)
369{
370 WaylandIMContext *imcontext = (WaylandIMContext *)data;
371
372 imcontext->pending_preedit.cursor = index;
373}
374
375static xkb_mod_index_t
376modifiers_get_index(struct wl_array *modifiers_map,
377 const char *name)
378{
379 xkb_mod_index_t index = 0;
380 char *p = modifiers_map->data;
381
382 while ((const char *)p < ((const char *)modifiers_map->data + modifiers_map->size))
383 {
384 if (strcmp(p, name) == 0)
385 return index;
386
387 index++;
388 p += strlen(p) + 1;
389 }
390
391 return XKB_MOD_INVALID;
392}
393
394static xkb_mod_mask_t
395modifiers_get_mask(struct wl_array *modifiers_map,
396 const char *name)
397{
398 xkb_mod_index_t index = modifiers_get_index(modifiers_map, name);
399
400 if (index == XKB_MOD_INVALID)
401 return XKB_MOD_INVALID;
402
403 return 1 << index;
404}
405static void
406text_input_modifiers_map(void *data,
407 struct wl_text_input *text_input EINA_UNUSED,
408 struct wl_array *map)
409{
410 WaylandIMContext *imcontext = (WaylandIMContext *)data;
411
412 imcontext->shift_mask = modifiers_get_mask(map, "Shift");
413 imcontext->control_mask = modifiers_get_mask(map, "Control");
414 imcontext->alt_mask = modifiers_get_mask(map, "Mod1");
415}
416
417static void
418text_input_keysym(void *data,
419 struct wl_text_input *text_input EINA_UNUSED,
420 uint32_t serial EINA_UNUSED,
421 uint32_t time,
422 uint32_t sym,
423 uint32_t state,
424 uint32_t modifiers)
425{
426 WaylandIMContext *imcontext = (WaylandIMContext *)data;
427 char string[32], key[32], keyname[32];
428 Ecore_Event_Key *e;
429
430 memset(key, 0, sizeof(key));
431 xkb_keysym_get_name(sym, key, sizeof(key));
432
433 memset(keyname, 0, sizeof(keyname));
434 xkb_keysym_get_name(sym, keyname, sizeof(keyname));
435 if (keyname[0] == '\0')
436 snprintf(keyname, sizeof(keyname), "Keysym-%u", sym);
437
438 memset(string, 0, sizeof(string));
439 xkb_keysym_to_utf8(sym, string, 32);
440
441 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
442 "key event (key: %s)",
443 keyname);
444
445 e = malloc(sizeof(Ecore_Event_Key) + strlen(key) + strlen(keyname) + strlen(string) + 3);
446 if (!e)
447 return;
448
449 e->keyname = (char *)(e + 1);
450 e->key = e->keyname + strlen(keyname) + 1;
451 e->string = e->key + strlen(key) + 1;
452 e->compose = e->string;
453
454 strcpy((char *)e->keyname, keyname);
455 strcpy((char *)e->key, key);
456 strcpy((char *)e->string, string);
457
458 e->window = imcontext->window->id;
459 e->event_window = imcontext->window->id;
460 e->timestamp = time;
461
462 e->modifiers = 0;
463 if (modifiers & imcontext->shift_mask)
464 e->modifiers |= ECORE_EVENT_MODIFIER_SHIFT;
465
466 if (modifiers & imcontext->control_mask)
467 e->modifiers |= ECORE_EVENT_MODIFIER_CTRL;
468
469 if (modifiers & imcontext->alt_mask)
470 e->modifiers |= ECORE_EVENT_MODIFIER_ALT;
471
472 if (state)
473 ecore_event_add(ECORE_EVENT_KEY_DOWN, e, NULL, NULL);
474 else
475 ecore_event_add(ECORE_EVENT_KEY_UP, e, NULL, NULL);
476}
477
478static void
479text_input_enter(void *data,
480 struct wl_text_input *text_input EINA_UNUSED,
481 struct wl_surface *surface EINA_UNUSED)
482{
483 WaylandIMContext *imcontext = (WaylandIMContext *)data;
484
485 update_state(imcontext);
486
487 imcontext->reset_serial = imcontext->serial;
488}
489
490static void
491text_input_leave(void *data,
492 struct wl_text_input *text_input)
493{
494 WaylandIMContext *imcontext = (WaylandIMContext *)data;
495
496 wl_text_input_hide_input_panel(text_input);
497
498 /* clear preedit */
499 commit_preedit(imcontext);
500 clear_preedit(imcontext);
501
502 ecore_imf_context_preedit_changed_event_add(imcontext->ctx);
503 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
504
505 ecore_imf_context_preedit_end_event_add(imcontext->ctx);
506 ecore_imf_context_event_callback_call(imcontext->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
507}
508
509static void
510text_input_input_panel_state(void *data EINA_UNUSED,
511 struct wl_text_input *text_input EINA_UNUSED,
512 uint32_t state EINA_UNUSED)
513{
514}
515
516static void
517text_input_language(void *data EINA_UNUSED,
518 struct wl_text_input *text_input EINA_UNUSED,
519 uint32_t serial EINA_UNUSED,
520 const char *language EINA_UNUSED)
521{
522}
523
524static void
525text_input_text_direction(void *data EINA_UNUSED,
526 struct wl_text_input *text_input EINA_UNUSED,
527 uint32_t serial EINA_UNUSED,
528 uint32_t direction EINA_UNUSED)
529{
530}
531
532static const struct wl_text_input_listener text_input_listener =
533{
534 text_input_enter,
535 text_input_leave,
536 text_input_modifiers_map,
537 text_input_input_panel_state,
538 text_input_preedit_string,
539 text_input_preedit_styling,
540 text_input_preedit_cursor,
541 text_input_commit_string,
542 text_input_cursor_position,
543 text_input_delete_surrounding_text,
544 text_input_keysym,
545 text_input_language,
546 text_input_text_direction
547};
548
549EAPI void
550wayland_im_context_add(Ecore_IMF_Context *ctx)
551{
552 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
553
554 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "context_add");
555
556 imcontext->ctx = ctx;
557
558 imcontext->text_input = wl_text_input_manager_create_text_input(imcontext->text_input_manager);
559 wl_text_input_add_listener(imcontext->text_input, &text_input_listener, imcontext);
560}
561
562EAPI void
563wayland_im_context_del(Ecore_IMF_Context *ctx)
564{
565 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
566
567 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "context_del");
568
569 wl_text_input_destroy(imcontext->text_input);
570
571 clear_preedit(imcontext);
572}
573
574EAPI void
575wayland_im_context_reset(Ecore_IMF_Context *ctx)
576{
577 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
578
579 commit_preedit(imcontext);
580 clear_preedit(imcontext);
581
582 wl_text_input_reset(imcontext->text_input);
583
584 update_state(imcontext);
585
586 imcontext->reset_serial = imcontext->serial;
587}
588
589EAPI void
590wayland_im_context_focus_in(Ecore_IMF_Context *ctx)
591{
592 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
593 Ecore_Wl_Input *input;
594
595 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "focus-in");
596
597 if (!imcontext->window)
598 return;
599
600 input = imcontext->window->keyboard_device;
601 if (!input || !input->seat)
602 return;
603
604 wl_text_input_show_input_panel(imcontext->text_input);
605 wl_text_input_activate(imcontext->text_input,
606 input->seat,
607 ecore_wl_window_surface_get(imcontext->window));
608}
609
610EAPI void
611wayland_im_context_focus_out(Ecore_IMF_Context *ctx)
612{
613 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
614
615 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "focus-out");
616
617 if (!imcontext->window)
618 return;
619
620 wl_text_input_deactivate(imcontext->text_input,
621 imcontext->window->display->input->seat);
622}
623
624EAPI void
625wayland_im_context_preedit_string_get(Ecore_IMF_Context *ctx,
626 char **str,
627 int *cursor_pos)
628{
629 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
630
631 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
632 "pre-edit string requested (preedit: `%s')",
633 imcontext->preedit_text ? imcontext->preedit_text : "");
634
635 if (str)
636 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
637
638 if (cursor_pos)
639 *cursor_pos = imcontext->preedit_cursor;
640}
641
642EAPI void
643wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
644 char **str,
645 Eina_List **attrs,
646 int *cursor_pos)
647{
648 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
649
650 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
651 "pre-edit string with attributes requested (preedit: `%s')",
652 imcontext->preedit_text ? imcontext->preedit_text : "");
653
654 if (str)
655 *str = strdup(imcontext->preedit_text ? imcontext->preedit_text : "");
656
657 if (attrs)
658 {
659 Eina_List *l;
660 Ecore_IMF_Preedit_Attr *a, *attr;
661
662 EINA_LIST_FOREACH(imcontext->preedit_attrs, l, a)
663 {
664 attr = malloc(sizeof(*attr));
665 attr = memcpy(attr, a, sizeof(*attr));
666 *attrs = eina_list_append(*attrs, attr);
667 }
668 }
669
670 if (cursor_pos)
671 *cursor_pos = imcontext->preedit_cursor;
672}
673
674EAPI void
675wayland_im_context_cursor_position_set(Ecore_IMF_Context *ctx,
676 int cursor_pos)
677{
678 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
679
680 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom,
681 "set cursor position (cursor: %d)",
682 cursor_pos);
683
684 update_state(imcontext);
685}
686
687EAPI void
688wayland_im_context_use_preedit_set(Ecore_IMF_Context *ctx EINA_UNUSED,
689 Eina_Bool use_preedit EINA_UNUSED)
690{
691}
692
693EAPI void
694wayland_im_context_client_window_set(Ecore_IMF_Context *ctx,
695 void *window)
696{
697 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
698
699 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "client window set (window: %p)", window);
700
701 if (window != NULL)
702 imcontext->window = ecore_wl_window_find((Ecore_Window)window);
703}
704
705EAPI void
706wayland_im_context_client_canvas_set(Ecore_IMF_Context *ctx,
707 void *canvas)
708{
709 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
710
711 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "client canvas set (canvas: %p)", canvas);
712
713 if (canvas != NULL)
714 imcontext->canvas = canvas;
715}
716
717EAPI void
718wayland_im_context_show(Ecore_IMF_Context *ctx)
719{
720 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
721
722 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "context_show");
723
724 wl_text_input_show_input_panel(imcontext->text_input);
725}
726
727EAPI void
728wayland_im_context_hide(Ecore_IMF_Context *ctx)
729{
730 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
731
732 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "context_hide");
733
734 wl_text_input_hide_input_panel(imcontext->text_input);
735}
736
737EAPI Eina_Bool
738wayland_im_context_filter_event(Ecore_IMF_Context *ctx EINA_UNUSED,
739 Ecore_IMF_Event_Type type EINA_UNUSED,
740 Ecore_IMF_Event *event EINA_UNUSED)
741{
742 return EINA_FALSE;
743}
744
745EAPI void
746wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx, int x, int y, int width, int height)
747{
748 WaylandIMContext *imcontext = (WaylandIMContext *)ecore_imf_context_data_get(ctx);
749
750 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "cursor_location_set (x: %d, y: %d, w: %d, h: %d)", x, y, width, height);
751
752 if ((imcontext->cursor_location.x != x) ||
753 (imcontext->cursor_location.y != y) ||
754 (imcontext->cursor_location.width != width) ||
755 (imcontext->cursor_location.height != height))
756 {
757 imcontext->cursor_location.x = x;
758 imcontext->cursor_location.y = y;
759 imcontext->cursor_location.width = width;
760 imcontext->cursor_location.height = height;
761
762 update_state(imcontext);
763 }
764}
765
766
767WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager)
768{
769 WaylandIMContext *context = calloc(1, sizeof(WaylandIMContext));
770
771 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "new context created");
772 context->text_input_manager = text_input_manager;
773
774 return context;
775}
776
777/* vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0
778*/
diff --git a/src/modules/ecore_imf/wayland/wayland_imcontext.h b/src/modules/ecore_imf/wayland/wayland_imcontext.h
new file mode 100644
index 0000000000..fb6906c2e8
--- /dev/null
+++ b/src/modules/ecore_imf/wayland/wayland_imcontext.h
@@ -0,0 +1,70 @@
1/*
2 * Copyright © 2012, 2013 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifndef __WAYLAND_IM_CONTEXT_H_
24#define __WAYLAND_IM_CONTEXT_H_
25
26#include <Ecore_IMF.h>
27#include "text-client-protocol.h"
28
29typedef struct _WaylandIMContext WaylandIMContext;
30
31EAPI void wayland_im_context_add (Ecore_IMF_Context *ctx);
32EAPI void wayland_im_context_del (Ecore_IMF_Context *ctx);
33EAPI void wayland_im_context_reset (Ecore_IMF_Context *ctx);
34EAPI void wayland_im_context_focus_in (Ecore_IMF_Context *ctx);
35EAPI void wayland_im_context_focus_out (Ecore_IMF_Context *ctx);
36EAPI void wayland_im_context_preedit_string_get (Ecore_IMF_Context *ctx,
37 char **str,
38 int *cursor_pos);
39EAPI void wayland_im_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx,
40 char **str,
41 Eina_List **attr,
42 int *cursor_pos);
43
44EAPI void wayland_im_context_cursor_position_set(Ecore_IMF_Context *ctx,
45 int cursor_pos);
46EAPI void wayland_im_context_use_preedit_set (Ecore_IMF_Context *ctx,
47 Eina_Bool use_preedit);
48EAPI void wayland_im_context_client_window_set (Ecore_IMF_Context *ctx,
49 void *window);
50EAPI void wayland_im_context_client_canvas_set (Ecore_IMF_Context *ctx,
51 void *canvas);
52EAPI void wayland_im_context_show (Ecore_IMF_Context *ctx);
53EAPI void wayland_im_context_hide (Ecore_IMF_Context *ctx);
54EAPI Eina_Bool wayland_im_context_filter_event (Ecore_IMF_Context *ctx,
55 Ecore_IMF_Event_Type type,
56 Ecore_IMF_Event *event);
57EAPI void wayland_im_context_cursor_location_set(Ecore_IMF_Context *ctx,
58 int x,
59 int y,
60 int width,
61 int height);
62
63WaylandIMContext *wayland_im_context_new (struct wl_text_input_manager *text_input_manager);
64
65extern int _ecore_imf_wayland_log_dom;
66
67#endif
68
69/* vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0
70 */
diff --git a/src/modules/ecore_imf/wayland/wayland_module.c b/src/modules/ecore_imf/wayland/wayland_module.c
new file mode 100644
index 0000000000..6b4e337fa5
--- /dev/null
+++ b/src/modules/ecore_imf/wayland/wayland_module.c
@@ -0,0 +1,154 @@
1/*
2 * Copyright © 2012, 2013 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <Ecore.h>
24#include <Ecore_IMF.h>
25#include <Ecore_Wayland.h>
26#include <stdio.h>
27
28#include "wayland_imcontext.h"
29#include "text-client-protocol.h"
30
31int _ecore_imf_wayland_log_dom = -1;
32
33static const Ecore_IMF_Context_Info wayland_im_info =
34{
35 "wayland",
36 "Wayland",
37 "*",
38 NULL,
39 0
40};
41
42static Ecore_IMF_Context_Class wayland_imf_class =
43{
44 wayland_im_context_add, /* add */
45 wayland_im_context_del, /* del */
46 wayland_im_context_client_window_set, /* client_window_set */
47 wayland_im_context_client_canvas_set, /* client_canvas_set */
48 wayland_im_context_show, /* show */
49 wayland_im_context_hide, /* hide */
50 wayland_im_context_preedit_string_get, /* get_preedit_string */
51 wayland_im_context_focus_in, /* focus_in */
52 wayland_im_context_focus_out, /* focus_out */
53 wayland_im_context_reset, /* reset */
54 wayland_im_context_cursor_position_set, /* cursor_position_set */
55 wayland_im_context_use_preedit_set, /* use_preedit_set */
56 NULL, /* input_mode_set */
57 wayland_im_context_filter_event, /* filter_event */
58 wayland_im_context_preedit_string_with_attributes_get, /* preedit_string_with_attribute_get */
59 NULL, /* prediction_allow_set */
60 NULL, /* autocapital_type_set */
61 NULL, /* control panel show */
62 NULL, /* control panel hide */
63 NULL, /* input_panel_layout_set */
64 NULL, /* input_panel_layout_get, */
65 NULL, /* input_panel_language_set, */
66 NULL, /* input_panel_language_get, */
67 wayland_im_context_cursor_location_set, /* cursor_location_set */
68 NULL, /* input_panel_imdata_set */
69 NULL, /* input_panel_imdata_get */
70 NULL, /* input_panel_return_key_type_set */
71 NULL, /* input_panel_return_key_disabled_set */
72 NULL, /* input_panel_caps_lock_mode_set */
73 NULL,
74 NULL,
75 NULL,
76 NULL,
77 NULL,
78 NULL
79};
80
81static struct wl_text_input_manager *text_input_manager = NULL;
82
83static Ecore_IMF_Context *
84im_module_exit(void)
85{
86 return NULL;
87}
88
89static Ecore_IMF_Context *
90im_module_create()
91{
92 Ecore_IMF_Context *ctx = NULL;
93 WaylandIMContext *ctxd = NULL;
94
95 ctxd = wayland_im_context_new(text_input_manager);
96 if (!ctxd)
97 {
98 return NULL;
99 }
100
101 ctx = ecore_imf_context_new(&wayland_imf_class);
102 if (!ctx)
103 {
104 free(ctxd);
105 return NULL;
106 }
107
108 ecore_imf_context_data_set(ctx, ctxd);
109
110 return ctx;
111}
112
113static Eina_Bool
114im_module_init(void)
115{
116 struct wl_registry *registry;
117 struct wl_list *globals;
118 Ecore_Wl_Global *global;
119
120 ecore_wl_init(NULL);
121
122 _ecore_imf_wayland_log_dom = eina_log_domain_register("ecore_imf_wayland", EINA_COLOR_YELLOW);
123
124 ecore_wl_display_iterate();
125 registry = ecore_wl_registry_get();
126 globals = ecore_wl_globals_get();
127
128 wl_list_for_each(global, globals, link)
129 {
130 if (!strcmp(global->interface, "wl_text_input_manager"))
131 {
132 text_input_manager = wl_registry_bind(registry, global->id, &wl_text_input_manager_interface, 1);
133 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "bound wl_text_input_manager interface");
134 }
135 }
136
137 ecore_imf_module_register(&wayland_im_info, im_module_create, im_module_exit);
138 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "im module initalized");
139
140 return EINA_TRUE;
141}
142
143static void
144im_module_shutdown(void)
145{
146 ecore_wl_shutdown();
147 EINA_LOG_DOM_INFO(_ecore_imf_wayland_log_dom, "im module shutdown");
148}
149
150EINA_MODULE_INIT(im_module_init);
151EINA_MODULE_SHUTDOWN(im_module_shutdown);
152
153/* vim:ts=8 sw=3 sts=3 expandtab cino=>5n-3f0^-2{2(0W1st0
154*/