Delete the timer callback when destroying WSCContextISF pointer
[platform/core/uifw/isf.git] / ism / modules / panelagent / wayland / wayland_panel_agent_module.cpp
1 /*
2  * ISF(Input Service Framework)
3  *
4  * ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable.
5  * Copyright (c) 2013 Intel Corporation
6  * Copyright (c) 2013-2015 Samsung Electronics Co., Ltd.
7  *
8  * Contact: Jihoon Kim <jihoon48.kim@samsung.com>, Li Zhang <li2012.zhang@samsung.com>
9  *
10  * This library is free software; you can redistribute it and/or modify it under
11  * the terms of the GNU Lesser General Public License as published by the
12  * Free Software Foundation; either version 2.1 of the License, or (at your option)
13  * any later version.
14  *
15  * This library is distributed in the hope that it will be useful, but WITHOUT ANY
16  * WARRANTY; without even the implied warranty of MERCHANTABILITY or
17  * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
18  * License for more details.
19  *
20  * You should have received a copy of the GNU Lesser General Public License
21  * along with this library; if not, write to the Free Software Foundation, Inc., 51
22  * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23  *
24  */
25
26 #define Uses_SCIM_PANEL_CLIENT
27 #define Uses_SCIM_CONFIG_PATH
28 #define Uses_SCIM_PANEL_AGENT
29
30 #include <sys/types.h>
31 #include <sys/wait.h>
32 #include <sys/time.h>
33 #include <sys/times.h>
34 #include <pthread.h>
35 #include <langinfo.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38
39 #include <signal.h>
40 #include <stdlib.h>
41 #include <string.h>
42 #include <malloc.h>
43 #include <dlog.h>
44 #include <glib.h>
45 #include <limits.h>
46
47 #include <Eina.h>
48 #include <Ecore.h>
49 #include <Ecore_Wayland.h>
50 #include <vconf.h>
51 #include <vconf-keys.h>
52 #include <input-method-client-protocol.h>
53 #include <text-client-protocol.h>
54
55 #include "scim_private.h"
56 #include "scim.h"
57 #include "isf_wsc_context.h"
58 #include "isf_wsc_control_ui.h"
59 #include "tizen_profile.h"
60
61 #include <linux/input.h>
62
63 #if ENABLE_GRAB_KEYBOARD
64 #include <xkbcommon/xkbcommon.h>
65 #endif
66
67 #include <sys/mman.h>
68 #include "isf_debug.h"
69
70
71 #ifdef LOG_TAG
72 # undef LOG_TAG
73 #endif
74 #define LOG_TAG                                         "ISF_WAYLAND_MODULE"
75
76 using namespace scim;
77
78 struct _WSCContextISFImpl {
79     WSCContextISF           *parent;
80     Ecore_Wl_Window         *client_window;
81     Ecore_IMF_Input_Mode     input_mode;
82     WideString               surrounding_text;
83     WideString               preedit_string;
84     AttributeList            preedit_attrlist;
85     WideString               commit_string;
86     Ecore_IMF_Autocapital_Type autocapital_type;
87     Ecore_IMF_Input_Hints    input_hint;
88     Ecore_IMF_BiDi_Direction bidi_direction;
89     Ecore_IMF_Input_Panel_Layout panel_layout;
90     String                   mime_type;
91     void                    *imdata;
92     int                      imdata_size;
93     int                      preedit_caret;
94     int                      cursor_x;
95     int                      cursor_y;
96     int                      cursor_top_y;
97     int                      cursor_pos;
98     int                      variation;
99     int                      return_key_disabled;
100     bool                     use_preedit;
101     bool                     is_on;
102     bool                     preedit_started;
103     bool                     need_commit_preedit;
104     bool                     init_remote_entry_metadata;
105     bool                     init_remote_surrounding_text;
106     bool                     block_input_resource;
107     Input_Resource           input_resource;
108
109     WSCContextISFImpl        *next;
110
111     /* Constructor */
112     _WSCContextISFImpl() : parent(NULL),
113                            client_window(0),
114                            input_mode(ECORE_IMF_INPUT_MODE_FULL),
115                            autocapital_type(ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE),
116                            input_hint(ECORE_IMF_INPUT_HINT_NONE),
117                            bidi_direction(ECORE_IMF_BIDI_DIRECTION_NEUTRAL),
118                            panel_layout(ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL),
119                            imdata(NULL),
120                            imdata_size(0),
121                            preedit_caret(0),
122                            cursor_x(0),
123                            cursor_y(0),
124                            cursor_top_y(0),
125                            cursor_pos(-1),
126                            variation(0),
127                            return_key_disabled(0),
128                            use_preedit(true),
129                            is_on(true),
130                            preedit_started(false),
131                            need_commit_preedit(false),
132                            init_remote_entry_metadata(true),
133                            init_remote_surrounding_text(true),
134                            block_input_resource(false),
135                            input_resource(INPUT_RESOURCE_NONE),
136                            next(NULL)
137     {
138     }
139 };
140
141 /* private functions */
142
143 static void     panel_slot_update_preedit_caret         (int                     context,
144                                                          int                     caret);
145 static void     panel_slot_process_key_event            (int                     context,
146                                                          const KeyEvent         &key);
147 static void     panel_slot_commit_string                (int                     context,
148                                                          const WideString       &wstr,
149                                                          bool                    remote_mode);
150 static void     panel_slot_forward_key_event            (int                     context,
151                                                          const KeyEvent         &key,
152                                                          bool                    remote_mode);
153 static void     panel_slot_update_preedit_string        (int                     context,
154                                                          const WideString        str,
155                                                          const WideString        commit,
156                                                          const AttributeList    &attrs,
157                                                          int                     caret,
158                                                          bool                    remote_mode);
159 static void     _show_preedit_string          (int                     context);
160
161 static void     panel_req_update_bidi_direction         (WSCContextISF     *ic, int direction);
162
163 static void     remote_surrounding_get                  (WSCContextISF     *wsc_ctx);
164
165 static void     wl_im_destroy                           (void);
166
167 /* Panel iochannel handler*/
168 static void     panel_initialize                        (void);
169 static void     panel_finalize                          (void);
170
171 /* utility functions */
172
173 static bool     filter_keys                             (const char *keyname,
174                                                          const char *config_path);
175 static void     set_ic_capabilities                     (WSCContextISF     *ic);
176
177 static void     initialize                              (void);
178 static void     finalize                                (void);
179
180 static void     send_wl_key_event                       (WSCContextISF *ic, const KeyEvent &key, bool fake);
181 static void     _hide_preedit_string                    (int context, bool update_preedit);
182
183 /* Local variables declaration */
184 static String                                           _language;
185 static WSCContextISFImpl                               *_used_ic_impl_list          = 0;
186 static WSCContextISFImpl                               *_free_ic_impl_list          = 0;
187 static WSCContextISF                                   *_ic_list                    = 0;
188
189 static KeyboardLayout                                   _keyboard_layout            = SCIM_KEYBOARD_Default;
190 static int                                              _valid_key_mask             = SCIM_KEY_AllMasks;
191
192 static ConfigPointer                                    _config;
193
194 static WSCContextISF                                   *_focused_ic                 = 0;
195
196 static bool                                             _scim_initialized           = false;
197
198 static int                                              _panel_client_id            = 0;
199 static uint32                                           _active_helper_option       = 0;
200
201 static bool                                             _on_the_spot                = true;
202 static bool                                             _change_keyboard_mode_by_focus_move = false;
203 static bool                                             _support_hw_keyboard_mode   = false;
204
205 static bool                                             _x_key_event_is_valid       = false;
206
207 static Ecore_Timer                                     *_resource_check_timer       = NULL;
208
209 static bool                                             _need_wl_im_init           = false;
210 static struct _wl_im                                    *_wl_im_ctx                = NULL;
211 static int                                              _ecore_wl_init_count       = 0;
212
213 #define WAYLAND_MODULE_CLIENT_ID (0)
214 #define MAX_PREEDIT_BUFSIZE 4000
215
216 #define MOD_SHIFT_MASK      0x01
217 #define MOD_CAPS_MASK       0x02
218 #define MOD_CONTROL_MASK    0x04
219 #define MOD_ALT_MASK        0x08
220 #define MOD_NUM_MASK        0x100
221 #define MOD_Mod5_MASK       0x80
222
223 //////////////////////////////wayland_panel_agent_module begin//////////////////////////////////////////////////
224
225 #define scim_module_init wayland_LTX_scim_module_init
226 #define scim_module_exit wayland_LTX_scim_module_exit
227 #define scim_panel_agent_module_init wayland_LTX_scim_panel_agent_module_init
228 #define scim_panel_agent_module_get_instance wayland_LTX_scim_panel_agent_module_get_instance
229
230 static struct weescim _wsc                                  = {0};
231
232 InfoManager* g_info_manager = NULL;
233 static scim::PanelAgentPointer instance;
234
235
236 /////////////////////////////////////////////////////////////////////////////
237 // Implementation of Wayland Input Method functions.
238 /////////////////////////////////////////////////////////////////////////////
239
240 static void
241 _wsc_im_ctx_reset (void *data, struct wl_input_method_context *im_ctx)
242 {
243     WSCContextISF *context_scim = (WSCContextISF*)data;
244     LOGD ("");
245     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
246         g_info_manager->socket_reset_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
247     }
248 }
249
250 static void
251 _wsc_im_ctx_content_type (void *data, struct wl_input_method_context *im_ctx, uint32_t hint, uint32_t purpose)
252 {
253     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
254     if (!wsc_ctx) return;
255
256     LOGD ("im_context = %p hint = %04x purpose = %d\n", im_ctx, hint, purpose);
257
258     // Set layout
259     if (wsc_ctx->content_purpose != purpose || !wsc_ctx->layout_initialized) {
260         wsc_ctx->layout_initialized = EINA_TRUE;
261         wsc_ctx->content_purpose = purpose;
262         isf_wsc_context_input_panel_layout_set (wsc_ctx, wsc_context_input_panel_layout_get (wsc_ctx));
263     }
264
265     if (wsc_ctx->content_hint != hint) {
266         uint32_t hint_copy, old_hintbit, new_hintbit;
267         const uint32_t autocap_type = WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
268                                       WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
269                                       WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
270
271         hint_copy = wsc_ctx->content_hint;
272         wsc_ctx->content_hint = hint;
273
274         // Set prediction allow
275         old_hintbit = hint_copy & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
276         new_hintbit = hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
277         if (old_hintbit != new_hintbit || !wsc_ctx->prediction_allow_initialized) {
278             wsc_ctx->prediction_allow_initialized = EINA_TRUE;
279             g_info_manager->set_prediction_allow (WAYLAND_MODULE_CLIENT_ID, wsc_context_prediction_allow_get (wsc_ctx));
280         }
281
282         // Set autocapital type
283         old_hintbit = hint_copy & autocap_type;
284         new_hintbit = hint & autocap_type;
285         if (old_hintbit != new_hintbit || !wsc_ctx->autocapital_type_initialized) {
286             wsc_ctx->autocapital_type_initialized = EINA_TRUE;
287             isf_wsc_context_autocapital_type_set (wsc_ctx, wsc_context_autocapital_type_get (wsc_ctx));
288         }
289
290         // Set language
291         old_hintbit = hint_copy & WL_TEXT_INPUT_CONTENT_HINT_LATIN;
292         new_hintbit = hint & WL_TEXT_INPUT_CONTENT_HINT_LATIN;
293         if (old_hintbit != new_hintbit || !wsc_ctx->language_initialized) {
294             wsc_ctx->language_initialized = EINA_TRUE;
295             isf_wsc_context_input_panel_language_set (wsc_ctx, wsc_context_input_panel_language_get (wsc_ctx));
296         }
297     }
298
299     if (_TV) {
300         isf_wsc_context_send_entry_metadata (wsc_ctx, wsc_context_input_hint_get (wsc_ctx), wsc_context_input_panel_layout_get (wsc_ctx),
301                 wsc_context_input_panel_layout_variation_get (wsc_ctx), wsc_context_autocapital_type_get (wsc_ctx), wsc_ctx->return_key_disabled);
302     }
303 }
304
305 static void
306 _wsc_im_ctx_invoke_action (void *data, struct wl_input_method_context *im_ctx, uint32_t button, uint32_t index)
307 {
308     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
309     if (!wsc_ctx) return;
310
311     LOGD ("invoke action. button : %d\n", button);
312
313     if (button != BTN_LEFT)
314         return;
315
316     wsc_context_send_preedit_string (wsc_ctx);
317 }
318
319 static void
320 _wsc_im_ctx_commit_state (void *data, struct wl_input_method_context *im_ctx, uint32_t serial)
321 {
322     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
323     if (!wsc_ctx) return;
324
325     wsc_ctx->serial = serial;
326
327     if (wsc_ctx->language)
328         wl_input_method_context_language (im_ctx, wsc_ctx->serial, wsc_ctx->language);
329 }
330
331 static void
332 _wsc_im_ctx_preferred_language (void *data, struct wl_input_method_context *im_ctx, const char *language)
333 {
334     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
335     if (!wsc_ctx) return;
336
337     if (language && wsc_ctx->language && !strcmp (language, wsc_ctx->language))
338         return;
339
340     if (wsc_ctx->language) {
341         free (wsc_ctx->language);
342         wsc_ctx->language = NULL;
343     }
344
345     if (language) {
346         wsc_ctx->language = strdup (language);
347         LOGD ("Language changed, new: '%s'\n", language);
348     }
349 }
350
351 static void
352 _wsc_im_ctx_return_key_type (void *data, struct wl_input_method_context *im_ctx, uint32_t return_key_type)
353 {
354     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
355
356     LOGD ("im_context = %p return key type = %d\n", im_ctx, return_key_type);
357     if (!wsc_ctx) return;
358
359     if (wsc_ctx->return_key_type != return_key_type) {
360         wsc_ctx->return_key_type = return_key_type;
361         isf_wsc_context_input_panel_return_key_type_set (wsc_ctx, (Ecore_IMF_Input_Panel_Return_Key_Type)wsc_ctx->return_key_type);
362     }
363 }
364
365 static void
366 _wsc_im_ctx_return_key_disabled (void *data, struct wl_input_method_context *im_ctx, uint32_t disabled)
367 {
368     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
369     Eina_Bool return_key_disabled = !!disabled;
370
371     LOGD ("im_context = %p return key disabled = %d\n", im_ctx, return_key_disabled);
372     if (!wsc_ctx) return;
373
374     if (wsc_ctx->return_key_disabled != return_key_disabled) {
375         wsc_ctx->return_key_disabled = return_key_disabled;
376         isf_wsc_context_input_panel_return_key_disabled_set (wsc_ctx, wsc_ctx->return_key_disabled);
377         if (_TV)
378             isf_wsc_context_send_entry_metadata (wsc_ctx, wsc_context_input_hint_get (wsc_ctx), wsc_context_input_panel_layout_get (wsc_ctx),
379                     wsc_context_input_panel_layout_variation_get (wsc_ctx), wsc_context_autocapital_type_get (wsc_ctx), wsc_ctx->return_key_disabled);
380     }
381 }
382
383 static void
384 _wsc_im_ctx_input_panel_data (void *data, struct wl_input_method_context *im_ctx, const char *input_panel_data, uint32_t input_panel_data_length)
385 {
386     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
387     LOGD ("im_context = %p input panel data = %s len = %d\n", im_ctx, input_panel_data, input_panel_data_length);
388     if (!wsc_ctx) return;
389
390     if (wsc_ctx->impl) {
391         if (wsc_ctx->impl->imdata) {
392             free(wsc_ctx->impl->imdata);
393         }
394
395         wsc_ctx->impl->imdata = calloc(1, input_panel_data_length);
396         if (wsc_ctx->impl->imdata)
397             memcpy(wsc_ctx->impl->imdata, input_panel_data, input_panel_data_length);
398
399         wsc_ctx->impl->imdata_size = input_panel_data_length;
400     }
401
402     isf_wsc_context_input_panel_imdata_set (wsc_ctx, (void *)input_panel_data, input_panel_data_length);
403 }
404
405 static void
406 _wsc_im_ctx_bidi_direction (void *data, struct wl_input_method_context *im_ctx, uint32_t bidi_direction)
407 {
408     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
409
410     LOGD ("im_context = %p bidi_direction = %d\n", im_ctx, bidi_direction);
411     if (!wsc_ctx) return;
412
413     if (wsc_ctx->bidi_direction != bidi_direction) {
414         wsc_ctx->bidi_direction = bidi_direction;
415
416         isf_wsc_context_bidi_direction_set (wsc_ctx, (Ecore_IMF_BiDi_Direction)wsc_ctx->bidi_direction);
417     }
418 }
419
420 static void
421 _wsc_im_ctx_cursor_position (void *data, struct wl_input_method_context *im_ctx, uint32_t cursor_pos)
422 {
423     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
424
425     LOGD ("im_context = %p cursor_pos = %d\n", im_ctx, cursor_pos);
426     if (!wsc_ctx || !wsc_ctx->impl) return;
427     wsc_ctx->impl->cursor_pos = cursor_pos;
428     wsc_ctx->surrounding_cursor = cursor_pos;
429     LOGD ("wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
430     g_info_manager->socket_update_cursor_position (cursor_pos);
431
432     if (_TV)
433         remote_surrounding_get (wsc_ctx);
434 }
435
436 static void
437 _wsc_im_ctx_process_input_device_event (void *data, struct wl_input_method_context *im_ctx, uint32_t type, const char *input_data, uint32_t input_data_len)
438 {
439     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
440
441     LOGD("im_context = %p type = %d, data = (%p) %d\n", im_ctx, type, input_data, input_data_len);
442     if (!wsc_ctx) return;
443
444     isf_wsc_context_process_input_device_event (wsc_ctx, type, input_data, input_data_len);
445 }
446
447 static void
448 _wsc_im_ctx_filter_key_event (void *data, struct wl_input_method_context *im_ctx, uint32_t serial, uint32_t time, const char *keyname, uint32_t state, uint32_t modifiers, const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
449 {
450     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
451     if (!wsc_ctx) return;
452
453 #if !(ENABLE_GRAB_KEYBOARD)
454     isf_wsc_context_filter_key_event (wsc_ctx, serial, time, keyname,
455             ((wl_keyboard_key_state)state) == WL_KEYBOARD_KEY_STATE_PRESSED, modifiers, dev_name, dev_class, dev_subclass);
456 #endif
457 }
458
459 static void
460 _wsc_im_ctx_captial_mode (void *data, struct wl_input_method_context *im_ctx, uint32_t mode)
461 {
462     LOGD ("capital mode %d", mode);
463     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
464     if (!wsc_ctx) return;
465     wsc_ctx->caps_mode = mode;
466     isf_wsc_context_input_panel_caps_mode_set (wsc_ctx, mode);
467 }
468
469 static void
470 _wsc_im_ctx_prediction_hint (void *data, struct wl_input_method_context *im_ctx, const char *prediction_hint)
471 {
472     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
473
474     LOGD ("im_context = %p, prediction hint = %s\n", im_ctx, prediction_hint);
475     if (!wsc_ctx) return;
476
477     isf_wsc_context_input_panel_prediction_hint_set (wsc_ctx, prediction_hint);
478 }
479
480 static void
481 _wsc_im_ctx_mime_type (void *data, struct wl_input_method_context *im_ctx, const char *mime_type)
482 {
483     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
484
485     LOGD ("im_context = %p, mime_type = %s\n", im_ctx, mime_type);
486     if (!wsc_ctx) return;
487
488     if (wsc_ctx->impl) {
489         wsc_ctx->impl->mime_type = strdup (mime_type);
490     }
491
492     isf_wsc_context_input_panel_mime_type_accept_set (wsc_ctx, mime_type);
493 }
494
495 static const struct wl_input_method_context_listener wsc_im_context_listener = {
496      _wsc_im_ctx_reset,
497      _wsc_im_ctx_content_type,
498      _wsc_im_ctx_invoke_action,
499      _wsc_im_ctx_commit_state,
500      _wsc_im_ctx_preferred_language,
501      _wsc_im_ctx_return_key_type,
502      _wsc_im_ctx_return_key_disabled,
503      _wsc_im_ctx_input_panel_data,
504      _wsc_im_ctx_bidi_direction,
505      _wsc_im_ctx_cursor_position,
506      _wsc_im_ctx_process_input_device_event,
507      _wsc_im_ctx_filter_key_event,
508      _wsc_im_ctx_captial_mode,
509      _wsc_im_ctx_prediction_hint,
510      _wsc_im_ctx_mime_type
511 };
512
513 #if ENABLE_GRAB_KEYBOARD
514 static void
515 _init_keysym2keycode (WSCContextISF *wsc_ctx)
516 {
517     uint32_t i = 0;
518     uint32_t code;
519     uint32_t num_syms;
520     const xkb_keysym_t *syms;
521
522     if (!wsc_ctx || !wsc_ctx->state)
523         return;
524
525     for (i = 0; i < 256; i++) {
526         code = i + 8;
527         num_syms = xkb_key_get_syms (wsc_ctx->state, code, &syms);
528
529         if (num_syms == 1)
530             wsc_ctx->_keysym2keycode[syms[0]] = i;
531     }
532 }
533
534 static void
535 _fini_keysym2keycode (WSCContextISF *wsc_ctx)
536 {
537     wsc_ctx->_keysym2keycode.clear ();
538 }
539
540 static void
541 _wsc_im_keyboard_keymap (void *data,
542         struct wl_keyboard *wl_keyboard,
543         uint32_t format,
544         int32_t fd,
545         uint32_t size)
546 {
547     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
548     char *map_str;
549
550     if (!wsc_ctx) {
551         close (fd);
552         return;
553     }
554
555     _fini_keysym2keycode (wsc_ctx);
556
557     if (wsc_ctx->state) {
558         xkb_state_unref (wsc_ctx->state);
559         wsc_ctx->state = NULL;
560     }
561
562     if (wsc_ctx->keymap) {
563         xkb_map_unref (wsc_ctx->keymap);
564         wsc_ctx->keymap = NULL;
565     }
566
567     if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
568         close (fd);
569         return;
570     }
571
572     map_str = (char*)mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
573     if (map_str == MAP_FAILED) {
574         close (fd);
575         return;
576     }
577
578     wsc_ctx->keymap =
579         xkb_map_new_from_string (wsc_ctx->xkb_context,
580                 map_str,
581                 XKB_KEYMAP_FORMAT_TEXT_V1,
582                 (xkb_keymap_compile_flags)0);
583
584     munmap (map_str, size);
585     close (fd);
586
587     if (!wsc_ctx->keymap) {
588         LOGW ("failed to compile keymap\n");
589         return;
590     }
591
592     wsc_ctx->state = xkb_state_new (wsc_ctx->keymap);
593     if (!wsc_ctx->state) {
594         LOGW ("failed to create XKB state\n");
595         xkb_map_unref (wsc_ctx->keymap);
596         return;
597     }
598
599     wsc_ctx->control_mask =
600         1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Control");
601     wsc_ctx->alt_mask =
602         1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Mod1");
603     wsc_ctx->shift_mask =
604         1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Shift");
605
606     LOGD ("create _keysym2keycode\n");
607     _init_keysym2keycode (wsc_ctx);
608 }
609
610 static void
611 _wsc_im_keyboard_key (void *data,
612         struct wl_keyboard *wl_keyboard,
613         uint32_t serial,
614         uint32_t time,
615         uint32_t key,
616         uint32_t state_w)
617 {
618     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
619     uint32_t code;
620     uint32_t num_syms;
621     const xkb_keysym_t *syms;
622     xkb_keysym_t sym;
623     char keyname[64] = {0};
624     enum wl_keyboard_key_state state = (wl_keyboard_key_state)state_w;
625
626     if (!wsc_ctx || !wsc_ctx->state)
627         return;
628
629     code = key + 8;
630     num_syms = xkb_key_get_syms (wsc_ctx->state, code, &syms);
631
632     sym = XKB_KEY_NoSymbol;
633     if (num_syms == 1) {
634         sym = syms[0];
635         xkb_keysym_get_name (sym, keyname, 64);
636     }
637
638     isf_wsc_context_filter_key_event (wsc_ctx, serial, time, code, sym, keyname,
639                 state);
640 }
641
642 static void
643 _wsc_im_keyboard_modifiers (void *data,
644         struct wl_keyboard *wl_keyboard,
645         uint32_t serial,
646         uint32_t mods_depressed,
647         uint32_t mods_latched,
648         uint32_t mods_locked,
649         uint32_t group)
650 {
651     WSCContextISF *wsc_ctx = (WSCContextISF*)data;
652     if (!wsc_ctx || !wsc_ctx->state)
653         return;
654
655     struct wl_input_method_context *context = wsc_ctx->im_ctx;
656     xkb_mod_mask_t mask;
657
658     xkb_state_update_mask (wsc_ctx->state, mods_depressed,
659             mods_latched, mods_locked, 0, 0, group);
660     mask = xkb_state_serialize_mods (wsc_ctx->state,
661             (xkb_state_component)(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED));
662
663     wsc_ctx->modifiers = 0;
664     if (mask & wsc_ctx->control_mask)
665         wsc_ctx->modifiers |= SCIM_KEY_ControlMask;
666     if (mask & wsc_ctx->alt_mask)
667         wsc_ctx->modifiers |= SCIM_KEY_AltMask;
668     if (mask & wsc_ctx->shift_mask)
669         wsc_ctx->modifiers |= SCIM_KEY_ShiftMask;
670
671     wl_input_method_context_modifiers (context, serial,
672             mods_depressed, mods_depressed,
673             mods_latched, group);
674 }
675
676 static const struct wl_keyboard_listener wsc_im_keyboard_listener = {
677     _wsc_im_keyboard_keymap,
678     NULL, /* enter */
679     NULL, /* leave */
680     _wsc_im_keyboard_key,
681     _wsc_im_keyboard_modifiers
682 };
683 #endif
684
685 static void
686 wl_im_destroy ()
687 {
688     if (!_wl_im_ctx || !_wl_im_ctx->wsc || !_wl_im_ctx->wsc->wsc_ctx)
689         return;
690
691     WSCContextISF *wsc_ctx = _wl_im_ctx->wsc->wsc_ctx;
692
693     if (_wl_im_ctx->need_focus_event)
694         isf_wsc_context_focus_out (wsc_ctx);
695
696 #if ENABLE_GRAB_KEYBOARD
697     if (wsc_ctx->keyboard) {
698         wl_keyboard_destroy (wsc_ctx->keyboard);
699         wsc_ctx->keyboard = NULL;
700     }
701
702     _fini_keysym2keycode (wsc_ctx);
703
704     if (wsc_ctx->state) {
705         xkb_state_unref (wsc_ctx->state);
706         wsc_ctx->state = NULL;
707     }
708
709     if (wsc_ctx->keymap) {
710         xkb_map_unref (wsc_ctx->keymap);
711         wsc_ctx->keymap = NULL;
712     }
713
714     if (wsc_ctx->xkb_context) {
715         xkb_context_unref (wsc_ctx->xkb_context);
716         wsc_ctx->xkb_context = NULL;
717     }
718 #endif
719
720     if (wsc_ctx->im_ctx) {
721         wl_input_method_context_destroy (wsc_ctx->im_ctx);
722         wsc_ctx->im_ctx = NULL;
723     }
724
725     if (wsc_ctx->preedit_str) {
726         free (wsc_ctx->preedit_str);
727         wsc_ctx->preedit_str = NULL;
728     }
729
730     if (wsc_ctx->surrounding_text) {
731         free (wsc_ctx->surrounding_text);
732         wsc_ctx->surrounding_text = NULL;
733     }
734
735     if (wsc_ctx->remote_surrounding_text) {
736         free (wsc_ctx->remote_surrounding_text);
737         wsc_ctx->remote_surrounding_text = NULL;
738     }
739
740     if (wsc_ctx->language) {
741         free (wsc_ctx->language);
742         wsc_ctx->language = NULL;
743     }
744
745     wsc_ctx->layout_initialized = EINA_FALSE;
746     wsc_ctx->prediction_allow_initialized = EINA_FALSE;
747     wsc_ctx->autocapital_type_initialized = EINA_FALSE;
748     wsc_ctx->language_initialized = EINA_FALSE;
749
750     if (_resource_check_timer)
751         ecore_timer_del (_resource_check_timer);
752     _resource_check_timer = NULL;
753
754     isf_wsc_context_del (wsc_ctx);
755     delete wsc_ctx;
756     _wl_im_ctx->wsc->wsc_ctx = NULL;
757     _wl_im_ctx->input_method = NULL;
758     _wl_im_ctx->im_ctx = NULL;
759     _wl_im_ctx->need_focus_event = EINA_FALSE;
760     _need_wl_im_init = false;
761 }
762
763 static void
764 _wsc_im_activate (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx, uint32_t text_input_id, uint32_t focus_in_event)
765 {
766     struct weescim *wsc = (weescim*)data;
767     if (!wsc) return;
768
769     WSCContextISF *wsc_ctx = new WSCContextISF;
770     if (!wsc_ctx) {
771         return;
772     }
773
774     if (_need_wl_im_init)
775         wl_im_destroy ();
776
777 #if ENABLE_GRAB_KEYBOARD
778     wsc_ctx->xkb_context = xkb_context_new ((xkb_context_flags)0);
779     if (wsc_ctx->xkb_context == NULL) {
780         LOGW ("Failed to create XKB context\n");
781         delete wsc_ctx;
782         return;
783     }
784     wsc_ctx->state = NULL;
785     wsc_ctx->keymap = NULL;
786     wsc_ctx->modifiers = 0;
787 #endif
788
789     wsc_ctx->id = text_input_id;
790     wsc->wsc_ctx = wsc_ctx;
791     wsc_ctx->ctx = wsc;
792     wsc_ctx->surrounding_text = NULL;
793     wsc_ctx->remote_surrounding_text = NULL;
794     wsc_ctx->surrounding_cursor = 0;
795     LOGD ("wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
796
797     get_language (&wsc_ctx->language);
798
799     wsc_ctx->preedit_str = strdup ("");
800     wsc_ctx->content_hint = WL_TEXT_INPUT_CONTENT_HINT_NONE;
801     wsc_ctx->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
802
803     wsc_ctx->im_ctx = im_ctx;
804     wl_input_method_context_add_listener (im_ctx, &wsc_im_context_listener, wsc_ctx);
805
806 #if ENABLE_GRAB_KEYBOARD
807     wsc_ctx->keyboard = wl_input_method_context_grab_keyboard (im_ctx);
808     if (wsc_ctx->keyboard)
809         wl_keyboard_add_listener (wsc_ctx->keyboard, &wsc_im_keyboard_listener, wsc_ctx);
810 #endif
811
812     if (wsc_ctx->language)
813         wl_input_method_context_language (im_ctx, wsc_ctx->serial, wsc_ctx->language);
814
815     isf_wsc_context_add (wsc_ctx);
816
817     if (focus_in_event) {
818         isf_wsc_context_focus_in (wsc_ctx);
819         _wl_im_ctx->need_focus_event = EINA_TRUE;
820     }
821 }
822
823 static void
824 _wsc_im_deactivate (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx, uint32_t focus_out_event)
825 {
826     struct weescim *wsc = (weescim*)data;
827     if (!wsc || !wsc->wsc_ctx) return;
828
829     /* When the focus_in/input_panel_shutdown event is called,
830      * it is not possible to know the information of wl_input_method to destroy */
831     _wl_im_ctx->wsc = wsc;
832     _wl_im_ctx->input_method = input_method;
833     _wl_im_ctx->im_ctx = im_ctx;
834     _need_wl_im_init = true;
835
836     if (focus_out_event) {
837         isf_wsc_context_focus_out (wsc->wsc_ctx);
838         _wl_im_ctx->need_focus_event = EINA_FALSE;
839     }
840 }
841
842 static void
843 _wsc_im_show_input_panel (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
844 {
845     struct weescim *wsc = (weescim*)data;
846     if (!wsc || !wsc->wsc_ctx) return;
847
848     isf_wsc_context_input_panel_show (wsc->wsc_ctx);
849     wsc->wsc_ctx->input_panel_shown = true;
850
851     if (_TV)
852         remote_surrounding_get (wsc->wsc_ctx);
853 }
854
855 static void
856 _wsc_im_hide_input_panel (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
857 {
858     struct weescim *wsc = (weescim*)data;
859     if (!wsc || !wsc->wsc_ctx) return;
860
861     isf_wsc_context_input_panel_hide (wsc->wsc_ctx);
862     wsc->wsc_ctx->input_panel_shown = false;
863 }
864
865 static const struct wl_input_method_listener wsc_im_listener = {
866     _wsc_im_activate,
867     _wsc_im_deactivate,
868     _wsc_im_show_input_panel,
869     _wsc_im_hide_input_panel
870 };
871
872 static bool
873 _wsc_setup (struct weescim *wsc)
874 {
875     Eina_Inlist *globals;
876     struct wl_registry *registry;
877     Ecore_Wl_Global *global;
878
879     if (!wsc) return false;
880
881     if (!(registry = ecore_wl_registry_get ())) {
882         LOGW ("failed to get wl_registry");
883         return false;
884     }
885
886     if (!(globals = ecore_wl_globals_get ())) {
887         LOGW ("failed to get wl_globals");
888         return false;
889     }
890
891     EINA_INLIST_FOREACH(globals, global) {
892         if (strcmp (global->interface, "wl_input_method") == 0)
893             wsc->im = (wl_input_method*)wl_registry_bind (registry, global->id, &wl_input_method_interface, 1);
894     }
895
896     if (wsc->im == NULL) {
897         LOGW ("Failed because wl_input_method is null\n");
898         return false;
899     }
900
901     /* Input method listener */
902     LOGD ("Adding wl_input_method listener\n");
903
904     if (wsc->im)
905         wl_input_method_add_listener (wsc->im, &wsc_im_listener, wsc);
906     else {
907         LOGW ("Couldn't get wayland input method interface\n");
908         return false;
909     }
910
911     return true;
912 }
913
914
915 //////////////////////////////wayland_panel_agent_module end//////////////////////////////////////////////////
916
917 WSCContextISF *
918 get_focused_ic ()
919 {
920     return _focused_ic;
921 }
922
923 int
924 get_panel_client_id (void)
925 {
926     return _panel_client_id;
927 }
928
929 void
930 get_language (char **language)
931 {
932     *language = strdup (_language.c_str ());
933 }
934
935 static unsigned int
936 get_time (void)
937 {
938     unsigned int tint;
939     struct timeval tv;
940     struct timezone tz;           /* is not used since ages */
941     gettimeofday (&tv, &tz);
942     tint = (unsigned int)(tv.tv_sec * 1000);
943     tint = tint / 1000 * 1000;
944     tint = (unsigned int)(tint + tv.tv_usec / 1000);
945     return tint;
946 }
947
948 /* Function Implementations */
949 static WSCContextISFImpl *
950 new_ic_impl (WSCContextISF *parent)
951 {
952     WSCContextISFImpl *impl = NULL;
953
954     if (_free_ic_impl_list != NULL) {
955         impl = _free_ic_impl_list;
956         _free_ic_impl_list = _free_ic_impl_list->next;
957     } else {
958         impl = new WSCContextISFImpl;
959         if (impl == NULL)
960             return NULL;
961     }
962
963     impl->next = _used_ic_impl_list;
964     _used_ic_impl_list = impl;
965
966     impl->parent = parent;
967
968     return impl;
969 }
970
971 static void
972 delete_ic_impl (WSCContextISFImpl *impl)
973 {
974     WSCContextISFImpl *rec = _used_ic_impl_list, *last = 0;
975
976     for (; rec != 0; last = rec, rec = rec->next) {
977         if (rec == impl) {
978             if (last != 0)
979                 last->next = rec->next;
980             else
981                 _used_ic_impl_list = rec->next;
982
983             rec->next = _free_ic_impl_list;
984             _free_ic_impl_list = rec;
985
986             if (rec->imdata) {
987                 free (rec->imdata);
988                 rec->imdata = NULL;
989             }
990
991             rec->imdata_size = 0;
992             rec->parent = 0;
993             rec->client_window = 0;
994             rec->mime_type = String ();
995             rec->surrounding_text = WideString ();
996             rec->preedit_string = WideString ();
997             rec->preedit_attrlist.clear ();
998             rec->commit_string = WideString ();
999             rec->block_input_resource = true;
1000             return;
1001         }
1002     }
1003 }
1004
1005 static void
1006 delete_all_ic_impl (void)
1007 {
1008     WSCContextISFImpl *it = _used_ic_impl_list;
1009
1010     while (it != 0) {
1011         _used_ic_impl_list = it->next;
1012         delete it;
1013         it = _used_ic_impl_list;
1014     }
1015
1016     it = _free_ic_impl_list;
1017     while (it != 0) {
1018         _free_ic_impl_list = it->next;
1019         delete it;
1020         it = _free_ic_impl_list;
1021     }
1022 }
1023
1024 static WSCContextISF *
1025 find_ic (int id)
1026 {
1027     WSCContextISFImpl *rec = _used_ic_impl_list;
1028
1029     while (rec != 0) {
1030         if (rec->parent && rec->parent->id == id)
1031             return rec->parent;
1032         rec = rec->next;
1033     }
1034
1035     return 0;
1036 }
1037
1038 static bool
1039 check_valid_ic (WSCContextISF * ic)
1040 {
1041     if (ic && ic->impl && ic->ctx)
1042         return true;
1043     else
1044         return false;
1045 }
1046
1047 void context_scim_imdata_get (WSCContextISF *wsc_ctx, void* data, int* length)
1048 {
1049     WSCContextISF* context_scim = wsc_ctx;
1050     LOGD ("");
1051     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1052
1053     if (context_scim && context_scim->impl) {
1054         if (data && context_scim->impl->imdata)
1055             memcpy (data, context_scim->impl->imdata, context_scim->impl->imdata_size);
1056
1057         if (length)
1058             *length = context_scim->impl->imdata_size;
1059     }
1060 }
1061
1062 void context_scim_mime_type_get (WSCContextISF *wsc_ctx, const char *mime_type)
1063 {
1064     WSCContextISF* context_scim = wsc_ctx;
1065     LOGD ("");
1066     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1067
1068     if (context_scim && context_scim->impl) {
1069         if (!(context_scim->impl->mime_type).empty ())
1070             memcpy ((void *)mime_type ,(context_scim->impl->mime_type).c_str (),
1071                 strlen ((context_scim->impl->mime_type).c_str ()));
1072     }
1073 }
1074
1075 static char *
1076 insert_text (const char *text, uint32_t offset, const char *insert)
1077 {
1078     uint32_t tlen = strlen (text), ilen = strlen (insert);
1079     char *new_text = (char*)malloc (tlen + ilen + 1);
1080     if (new_text) {
1081         if ((unsigned int) tlen < offset)
1082             offset = tlen;
1083         memcpy (new_text, text, offset);
1084         memcpy (new_text + offset, insert, ilen);
1085         memcpy (new_text + offset + ilen, text + offset, tlen - offset);
1086         new_text[tlen + ilen] = '\0';
1087     }
1088
1089     return new_text;
1090 }
1091
1092 static Eina_Bool
1093 change_block_status_timer_cb (void *data)
1094 {
1095     WSCContextISF* context_scim = static_cast<WSCContextISF*>(data);
1096     if (context_scim && context_scim->impl)
1097         context_scim->impl->block_input_resource = false;
1098
1099     _resource_check_timer = NULL;
1100
1101     return ECORE_CALLBACK_CANCEL;
1102 }
1103
1104 static void
1105 check_input_resource (WSCContextISF* wsc_ctx, Input_Resource input_res)
1106 {
1107     WSCContextISF* context_scim = wsc_ctx;
1108     LOGD ("Input resource : %d\n", input_res);
1109     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1110
1111     if (context_scim && context_scim->impl) {
1112         if (context_scim->impl->input_resource == input_res)
1113             return;
1114
1115         if (_TV)
1116             if (context_scim->impl->input_resource != input_res && input_res != INPUT_RESOURCE_NONE)
1117                 g_info_manager->remoteinput_callback_input_resource (input_res);
1118
1119         if (context_scim->impl->input_resource == INPUT_RESOURCE_REMOTE && input_res == INPUT_RESOURCE_LOCAL) {
1120             if (context_scim->impl->need_commit_preedit) {
1121                 WideString wstr = context_scim->impl->preedit_string;
1122                 _hide_preedit_string (context_scim->id, false);
1123                 wsc_context_commit_string (context_scim, utf8_wcstombs (wstr).c_str ());
1124
1125                 context_scim->impl->need_commit_preedit = false;
1126                 context_scim->impl->preedit_string.clear ();
1127             }
1128
1129             if (_resource_check_timer)
1130                 ecore_timer_del (_resource_check_timer);
1131             _resource_check_timer = ecore_timer_add (2.0, change_block_status_timer_cb, context_scim);
1132             context_scim->impl->block_input_resource = true;
1133         }
1134         context_scim->impl->input_resource = input_res;
1135     }
1136 }
1137
1138 /* Public functions */
1139 void
1140 isf_wsc_context_init (void)
1141 {
1142     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1143     LOGD ("");
1144
1145     if (!_scim_initialized) {
1146         _ecore_wl_init_count = ecore_wl_init (NULL);
1147         initialize ();
1148         _scim_initialized = true;
1149         isf_wsc_input_panel_init ();
1150         //isf_wsc_context_set_hardware_keyboard_mode(context_scim);
1151     }
1152 }
1153
1154 void
1155 isf_wsc_context_shutdown (void)
1156 {
1157     LOGD ("");
1158     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1159
1160     if (_scim_initialized) {
1161         _scim_initialized = false;
1162
1163         isf_wsc_input_panel_shutdown ();
1164         finalize ();
1165
1166         if (_ecore_wl_init_count > 0) {
1167             ecore_wl_shutdown ();
1168             _ecore_wl_init_count = 0;
1169         }
1170     }
1171 }
1172
1173 void
1174 isf_wsc_context_add (WSCContextISF *wsc_ctx)
1175 {
1176     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1177     LOGD ("");
1178     WSCContextISF* context_scim = wsc_ctx;
1179
1180     if (!context_scim) return;
1181     context_scim->surrounding_text_fd_read_handler = NULL;
1182     context_scim->selection_text_fd_read_handler = NULL;
1183     context_scim->remote_surrounding_text_fd_read_handler = NULL;
1184     context_scim->surrounding_text = NULL;
1185     context_scim->remote_surrounding_text = NULL;
1186     context_scim->selection_text = NULL;
1187
1188     context_scim->impl                      = new_ic_impl (context_scim);
1189     if (context_scim->impl == NULL) {
1190         std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
1191         return;
1192     }
1193
1194     context_scim->impl->client_window       = 0;
1195     context_scim->impl->preedit_caret       = 0;
1196     context_scim->impl->cursor_x            = 0;
1197     context_scim->impl->cursor_y            = 0;
1198     context_scim->impl->cursor_pos          = -1;
1199     context_scim->impl->cursor_top_y        = 0;
1200     context_scim->impl->is_on               = true;
1201     context_scim->impl->use_preedit         = _on_the_spot;
1202     context_scim->impl->preedit_started     = false;
1203     context_scim->impl->need_commit_preedit = false;
1204
1205     if (!_ic_list)
1206         context_scim->next = NULL;
1207     else
1208         context_scim->next = _ic_list;
1209     _ic_list = context_scim;
1210
1211     context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1212
1213     g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1214     set_ic_capabilities (context_scim);
1215     SCIM_DEBUG_FRONTEND (2) << "input context created: id = " << context_scim->id << "\n";
1216 }
1217
1218 void
1219 isf_wsc_context_del (WSCContextISF *wsc_ctx)
1220 {
1221     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1222     LOGD ("");
1223
1224     if (!_ic_list) return;
1225
1226     WSCContextISF *context_scim = wsc_ctx;
1227     if (!context_scim) return;
1228
1229     if (context_scim->selection_text_fd_read_handler) {
1230         int fd = ecore_main_fd_handler_fd_get (context_scim->selection_text_fd_read_handler);
1231         close (fd);
1232         ecore_main_fd_handler_del (context_scim->selection_text_fd_read_handler);
1233         context_scim->selection_text_fd_read_handler = NULL;
1234     }
1235
1236     if (context_scim->selection_text) {
1237         free (context_scim->selection_text);
1238         context_scim->selection_text = NULL;
1239     }
1240
1241     if (context_scim->surrounding_text_fd_read_handler) {
1242         int fd = ecore_main_fd_handler_fd_get (context_scim->surrounding_text_fd_read_handler);
1243         close (fd);
1244         ecore_main_fd_handler_del (context_scim->surrounding_text_fd_read_handler);
1245         context_scim->surrounding_text_fd_read_handler = NULL;
1246     }
1247
1248     if (context_scim->remote_surrounding_text_fd_read_handler) {
1249         int fd = ecore_main_fd_handler_fd_get (context_scim->remote_surrounding_text_fd_read_handler);
1250         close (fd);
1251         ecore_main_fd_handler_del (context_scim->remote_surrounding_text_fd_read_handler);
1252         context_scim->remote_surrounding_text_fd_read_handler = NULL;
1253     }
1254
1255     if (context_scim->surrounding_text) {
1256         free (context_scim->surrounding_text);
1257         context_scim->surrounding_text = NULL;
1258     }
1259
1260     if (context_scim->remote_surrounding_text) {
1261         free (context_scim->remote_surrounding_text);
1262         context_scim->remote_surrounding_text = NULL;
1263     }
1264
1265     if (context_scim->id != _ic_list->id) {
1266         WSCContextISF * pre = _ic_list;
1267         WSCContextISF * cur = _ic_list->next;
1268         while (cur != NULL) {
1269             if (cur->id == context_scim->id) {
1270                 pre->next = cur->next;
1271                 break;
1272             }
1273             pre = cur;
1274             cur = cur->next;
1275         }
1276     } else {
1277         _ic_list = _ic_list->next;
1278     }
1279
1280     if (context_scim->impl) {
1281         // Delete the instance.
1282         // FIXME:
1283         // In case the instance send out some helper event,
1284         // and this context has been focused out,
1285         // we need set the focused_ic to this context temporary.
1286         WSCContextISF* old_focused = _focused_ic;
1287         _focused_ic = context_scim;
1288         _focused_ic = old_focused;
1289
1290         if (context_scim == _focused_ic) {
1291             g_info_manager->socket_turn_off ();
1292             g_info_manager->focus_out (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1293         }
1294
1295         g_info_manager->remove_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1296
1297         if (context_scim->impl) {
1298             delete_ic_impl (context_scim->impl);
1299             context_scim->impl = 0;
1300         }
1301     }
1302
1303     if (context_scim == _focused_ic)
1304         _focused_ic = 0;
1305 }
1306
1307 void
1308 isf_wsc_context_focus_in (WSCContextISF *wsc_ctx)
1309 {
1310     WSCContextISF* context_scim = wsc_ctx;
1311     LOGD ("");
1312
1313     if (!context_scim)
1314         return;
1315
1316     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
1317
1318     if (_focused_ic) {
1319         if (_focused_ic == context_scim) {
1320             SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
1321             return;
1322         }
1323         SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
1324         isf_wsc_context_focus_out (_focused_ic);
1325     }
1326
1327     if (_change_keyboard_mode_by_focus_move) {
1328         //if h/w keyboard mode, keyboard mode will be changed to s/w mode when the entry get the focus.
1329         LOGD ("Keyboard mode is changed H/W->S/W because of focus_in.\n");
1330         isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_HELPER_MODE);
1331     }
1332
1333     if (context_scim && context_scim->impl) {
1334         _focused_ic = context_scim;
1335
1336         context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1337         context_scim->impl->surrounding_text.clear ();
1338         context_scim->impl->preedit_string.clear ();
1339         context_scim->impl->preedit_attrlist.clear ();
1340         context_scim->impl->commit_string.clear ();
1341         context_scim->impl->preedit_caret = 0;
1342         context_scim->impl->preedit_started = false;
1343
1344         g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1345
1346         set_ic_capabilities (context_scim);
1347
1348         //FIXME: modify the parameter ic->impl->si->get_factory_uuid ()
1349         g_info_manager->focus_in (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1350         if (context_scim->impl->is_on) {
1351             g_info_manager->socket_turn_on ();
1352             //            _panel_client.hide_preedit_string (context_scim->id);
1353             //            _panel_client.hide_aux_string (context_scim->id);
1354             //            _panel_client.hide_lookup_table (context_scim->id);
1355             //FIXME
1356             #if 0 //REMOVE_SCIM_LAUNCHER
1357             context_scim->impl->si->set_layout (wsc_context_input_panel_layout_get (wsc_ctx));
1358             context_scim->impl->si->set_prediction_allow (context_scim->impl->prediction_allow);
1359
1360             if (context_scim->impl->imdata)
1361                 context_scim->impl->si->set_imdata ((const char*)context_scim->impl->imdata, context_scim->impl->imdata_size);
1362             #endif
1363             LOGD ("set autocapital type : %d\n", context_scim->impl->autocapital_type);
1364             g_info_manager->set_autocapital_type ((int)context_scim->impl->autocapital_type);
1365         } else {
1366             g_info_manager->socket_turn_off ();
1367         }
1368
1369         g_info_manager->get_active_helper_option (WAYLAND_MODULE_CLIENT_ID, _active_helper_option);
1370
1371         if (_TV)
1372             g_info_manager->remoteinput_callback_focus_in ();
1373
1374         context_scim->impl->init_remote_entry_metadata = false;
1375         context_scim->impl->init_remote_surrounding_text = false;
1376         context_scim->impl->block_input_resource = false;
1377         context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1378     }
1379
1380     LOGD ("ctx : %p\n", wsc_ctx);
1381 }
1382
1383 void
1384 isf_wsc_context_focus_out (WSCContextISF *wsc_ctx)
1385 {
1386     WSCContextISF* context_scim = wsc_ctx;
1387     LOGD ("");
1388
1389     if (!context_scim) return;
1390
1391     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1392
1393     if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1394         LOGD ("ctx : %p\n", wsc_ctx);
1395
1396         if (context_scim->impl->need_commit_preedit) {
1397             _hide_preedit_string (context_scim->id, false);
1398
1399             wsc_context_commit_preedit_string (context_scim);
1400             g_info_manager->socket_reset_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1401         }
1402
1403         context_scim->impl->cursor_pos = -1;
1404 //          if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1405         g_info_manager->focus_out (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1406
1407         _focused_ic = 0;
1408
1409         if (_TV)
1410         g_info_manager->remoteinput_callback_focus_out ();
1411
1412         context_scim->impl->surrounding_text.clear ();
1413         context_scim->impl->preedit_string.clear ();
1414         context_scim->impl->preedit_attrlist.clear ();
1415         context_scim->impl->commit_string.clear ();
1416         context_scim->impl->preedit_caret = 0;
1417         context_scim->impl->preedit_started = false;
1418         context_scim->impl->need_commit_preedit = false;
1419
1420         context_scim->impl->init_remote_entry_metadata = true;
1421         context_scim->impl->init_remote_surrounding_text = true;
1422         context_scim->impl->block_input_resource = true;
1423         context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1424     }
1425     _x_key_event_is_valid = false;
1426 }
1427
1428 void
1429 isf_wsc_context_preedit_string_get (WSCContextISF *wsc_ctx, char** str, int *cursor_pos)
1430 {
1431     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1432     LOGD ("");
1433     WSCContextISF* context_scim = wsc_ctx;
1434
1435     if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1436         String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1437
1438         if (str) {
1439             if (mbs.length ())
1440                 *str = strdup (mbs.c_str ());
1441             else
1442                 *str = strdup ("");
1443         }
1444
1445         if (cursor_pos) {
1446             //*cursor_pos = context_scim->impl->preedit_caret;
1447             mbs = utf8_wcstombs (
1448                 context_scim->impl->preedit_string.substr (0, context_scim->impl->preedit_caret));
1449             *cursor_pos = mbs.length ();
1450         }
1451     } else {
1452         if (str)
1453             *str = strdup ("");
1454
1455         if (cursor_pos)
1456             *cursor_pos = 0;
1457     }
1458 }
1459
1460 void
1461 isf_wsc_context_autocapital_type_set (WSCContextISF* wsc_ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1462 {
1463     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1464     LOGD ("autocapital_type: %d", autocapital_type);
1465     WSCContextISF* context_scim = wsc_ctx;
1466
1467     if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1468         context_scim->impl->autocapital_type = autocapital_type;
1469         LOGD ("ctx : %p. set autocapital type : %d\n", wsc_ctx, autocapital_type);
1470
1471         if (context_scim == _focused_ic) {
1472             LOGD ("ctx : %p. set autocapital type : %d\n", wsc_ctx, autocapital_type);
1473             g_info_manager->set_autocapital_type ((int)autocapital_type);
1474         }
1475     }
1476 }
1477
1478 void
1479 isf_wsc_context_bidi_direction_set (WSCContextISF* wsc_ctx, Ecore_IMF_BiDi_Direction direction)
1480 {
1481     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1482
1483     WSCContextISF *context_scim = wsc_ctx;
1484
1485     if (context_scim && context_scim->impl) {
1486         if (context_scim->impl->bidi_direction != direction) {
1487             context_scim->impl->bidi_direction = direction;
1488
1489             if (context_scim == _focused_ic) {
1490                 LOGD ("ctx : %p, bidi direction : %#x\n", wsc_ctx, direction);
1491                 panel_req_update_bidi_direction (context_scim, direction);
1492             }
1493         }
1494     }
1495 }
1496
1497 void
1498 isf_wsc_context_send_surrounding_text (WSCContextISF* wsc_ctx, const char *text, int cursor)
1499 {
1500     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1501
1502     WSCContextISF *context_scim = wsc_ctx;
1503
1504     if (!context_scim || !context_scim->impl)
1505         return;
1506
1507     char *conv_text = strdup (utf8_wcstombs (context_scim->impl->surrounding_text).c_str ());
1508     if (!conv_text)
1509         return;
1510
1511     if (!context_scim->impl->init_remote_surrounding_text || strcmp (conv_text, text) != 0 || context_scim->impl->cursor_pos != cursor) {
1512         SECURE_LOGD("remote surrounding text : \"%s\"\n", text);
1513         context_scim->impl->surrounding_text = utf8_mbstowcs (String (text));
1514         context_scim->impl->cursor_pos = cursor;
1515
1516         if (_TV) {
1517             if (context_scim->input_panel_shown && context_scim->impl->input_resource != INPUT_RESOURCE_REMOTE) {
1518                 String _text(text);
1519                 if (context_scim->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD) {
1520                     const unsigned char pw_char[5] = { 0xE2, 0x80, 0xA2, 0x2A, 0x00 };    // â€¢ U+2022 * U+002A
1521                     if (_text.find_first_not_of((char *)pw_char) != String::npos) {
1522                         g_info_manager->remoteinput_callback_surrounding_text (_text, context_scim->impl->cursor_pos);
1523                     }
1524                     else {
1525                         String empty("");
1526                         g_info_manager->remoteinput_callback_surrounding_text (empty, 0);
1527                     }
1528                 }
1529                 else {
1530                     g_info_manager->remoteinput_callback_surrounding_text (_text, context_scim->impl->cursor_pos);
1531                 }
1532                 context_scim->impl->init_remote_surrounding_text = true;
1533             }
1534         }
1535         else {
1536             context_scim->impl->init_remote_surrounding_text = true;
1537         }
1538     }
1539     free (conv_text);
1540 }
1541
1542 void
1543 isf_wsc_context_send_entry_metadata (WSCContextISF* wsc_ctx, Ecore_IMF_Input_Hints hint,
1544                                      Ecore_IMF_Input_Panel_Layout layout, int variation,
1545                                      Ecore_IMF_Autocapital_Type type, int return_key_disabled)
1546 {
1547     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1548
1549     WSCContextISF *context_scim = wsc_ctx;
1550
1551     if (context_scim && context_scim->impl) {
1552         if (!context_scim->impl->init_remote_entry_metadata || (context_scim->impl->input_hint != hint || context_scim->impl->panel_layout != layout ||
1553             context_scim->impl->variation != variation || context_scim->impl->autocapital_type != type ||
1554             context_scim->impl->return_key_disabled != return_key_disabled)) {
1555             if (context_scim->impl->panel_layout != layout || context_scim->impl->variation != variation) {
1556                 if (context_scim->impl->input_resource == INPUT_RESOURCE_REMOTE)
1557                     context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1558             }
1559
1560             context_scim->impl->input_hint = hint;
1561             context_scim->impl->panel_layout = layout;
1562             context_scim->impl->variation = variation;
1563             context_scim->impl->autocapital_type = type;
1564             context_scim->impl->return_key_disabled = return_key_disabled;
1565
1566             if (_TV)
1567                 g_info_manager->remoteinput_callback_entry_metadata (context_scim->impl->input_hint, context_scim->impl->panel_layout,
1568                         context_scim->impl->variation, context_scim->impl->autocapital_type, context_scim->impl->return_key_disabled);
1569
1570             context_scim->impl->init_remote_entry_metadata = true;
1571
1572             if (_TV)
1573                 remote_surrounding_get (wsc_ctx);
1574         }
1575     }
1576 }
1577
1578 #if ENABLE_GRAB_KEYBOARD
1579 static
1580 bool is_number_key (const char *str)
1581 {
1582     if (!str) return false;
1583
1584     int result = atoi (str);
1585
1586     if (result == 0) {
1587         if (!strcmp (str, "0"))
1588             return true;
1589         else
1590             return false;
1591     }
1592     else
1593         return true;
1594 }
1595
1596 void
1597 isf_wsc_context_filter_key_event (WSCContextISF* wsc_ctx,
1598                                   uint32_t serial,
1599                                   uint32_t timestamp, uint32_t keycode, uint32_t symcode,
1600                                   char *keyname,
1601                                   enum wl_keyboard_key_state state)
1602
1603 {
1604     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1605     LOGD ("");
1606
1607     if (!wsc_ctx) return;
1608
1609     KeyEvent key(symcode, wsc_ctx->modifiers);
1610
1611     bool ignore_key = filter_keys (keyname, SCIM_CONFIG_HOTKEYS_FRONTEND_IGNORE_KEY);
1612
1613     if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
1614         key.mask = SCIM_KEY_ReleaseMask;
1615     } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1616         if (!ignore_key) {
1617             /* Hardware input detect code */
1618             if (get_keyboard_mode () == TOOLBAR_HELPER_MODE &&
1619                 timestamp > 1 &&
1620                 _support_hw_keyboard_mode &&
1621                 strncmp (keyname, "XF86", 4)) {
1622                 bool hw_key_detect = false;
1623
1624                 if (_TV) {
1625                     if (strcmp (keyname, "Down") &&
1626                         strcmp (keyname, "KP_Down") &&
1627                         strcmp (keyname, "Up") &&
1628                         strcmp (keyname, "KP_Up") &&
1629                         strcmp (keyname, "Right") &&
1630                         strcmp (keyname, "KP_Right") &&
1631                         strcmp (keyname, "Left") &&
1632                         strcmp (keyname, "KP_Left") &&
1633                         strcmp (keyname, "Return") &&
1634                         strcmp (keyname, "Pause") &&
1635                         strcmp (keyname, "NoSymbol") &&
1636                         !is_number_key (keyname)) {
1637                         hw_key_detect = true;
1638                     }
1639                 } else {
1640                     if (key.code != 0x1008ff26 && key.code != 0xFF69) {
1641                         /* XF86back, Cancel (Power + Volume down) key */
1642                         hw_key_detect = true;
1643                     }
1644                 }
1645
1646                 if (hw_key_detect) {
1647                     isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_KEYBOARD_MODE);
1648                     ISF_SAVE_LOG ("Changed keyboard mode from S/W to H/W (code: %x, name: %s)\n", key.code, keyname);
1649                     LOGD ("Hardware keyboard mode, active helper option: %d\n", _active_helper_option);
1650                 }
1651             }
1652         }
1653     }
1654
1655     if (!ignore_key) {
1656         if (!_focused_ic || !_focused_ic->impl || !_focused_ic->impl->is_on) {
1657             LOGD ("ic is off");
1658         } else {
1659             static uint32 _serial = 0;
1660             g_info_manager->process_key_event (key, ++_serial);
1661         }
1662     } else {
1663         send_wl_key_event (wsc_ctx, key, false);
1664     }
1665 }
1666 #else
1667 void
1668 isf_wsc_context_filter_key_event (WSCContextISF* wsc_ctx,
1669                                   uint32_t serial,
1670                                   uint32_t timestamp, const char *keysym,
1671                                   bool press, uint32_t modifiers,
1672                                   const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
1673 {
1674     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1675     LOGD ("");
1676
1677     if (!wsc_ctx) return;
1678
1679     if (!keysym) {
1680         LOGD("key is NULL\n");
1681         return;
1682     }
1683
1684     String _key(keysym);
1685     KeyEvent key;
1686
1687     if (!scim_string_to_key (key, _key)) {
1688         xkb_keysym_t code = xkb_keysym_from_name(keysym, XKB_KEYSYM_NO_FLAGS);
1689         if (code == XKB_KEY_NoSymbol) {
1690             code = xkb_keysym_from_name(keysym, XKB_KEYSYM_CASE_INSENSITIVE);
1691         }
1692         key.code = code;
1693     }
1694     scim_set_device_info (key, dev_name ? dev_name : "", dev_class, dev_subclass);
1695
1696     bool ignore_key = filter_keys (keysym, SCIM_CONFIG_HOTKEYS_FRONTEND_IGNORE_KEY);
1697
1698     if (modifiers & MOD_SHIFT_MASK)
1699         key.mask |= SCIM_KEY_ShiftMask;
1700     if (modifiers & MOD_ALT_MASK)
1701         key.mask |= SCIM_KEY_AltMask;
1702     if (modifiers & MOD_CONTROL_MASK)
1703         key.mask |= SCIM_KEY_ControlMask;
1704
1705     if (modifiers & MOD_CAPS_MASK)
1706         key.mask |= SCIM_KEY_CapsLockMask;
1707     if (modifiers & MOD_NUM_MASK)
1708         key.mask |= SCIM_KEY_NumLockMask;
1709
1710     if (!press) {
1711         key.mask |= SCIM_KEY_ReleaseMask;
1712     } else {
1713         if (!ignore_key) {
1714             /* Hardware input detect code */
1715             if (get_keyboard_mode () == TOOLBAR_HELPER_MODE &&
1716                 timestamp > 1 &&
1717                 _support_hw_keyboard_mode &&
1718                 strncmp (keysym, "XF86", 4)) {
1719                 bool hw_key_detect = false;
1720
1721                 if (_TV) {
1722                     if (strcmp (keysym, "Down") &&
1723                         strcmp (keysym, "KP_Down") &&
1724                         strcmp (keysym, "Up") &&
1725                         strcmp (keysym, "KP_Up") &&
1726                         strcmp (keysym, "Right") &&
1727                         strcmp (keysym, "KP_Right") &&
1728                         strcmp (keysym, "Left") &&
1729                         strcmp (keysym, "KP_Left") &&
1730                         strcmp (keysym, "Return") &&
1731                         strcmp (keysym, "Pause") &&
1732                         strcmp (keysym, "NoSymbol") &&
1733                         key.dev_subclass != ECORE_DEVICE_SUBCLASS_REMOCON) {
1734                         hw_key_detect = true;
1735                     }
1736                 } else {
1737                     if (key.code != 0x1008ff26 && key.code != 0xFF69) {
1738                         /* XF86back, Cancel (Power + Volume down) key */
1739                         hw_key_detect = true;
1740                     }
1741                 }
1742
1743                 if (hw_key_detect) {
1744                     isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_KEYBOARD_MODE);
1745                     ISF_SAVE_LOG ("Changed keyboard mode from S/W to H/W (code: %x, key : %s)\n", key.code, keysym);
1746                     LOGD ("Hardware keyboard mode, active helper option: %d\n", _active_helper_option);
1747                 }
1748             }
1749         }
1750     }
1751
1752     if (!ignore_key) {
1753         if (!_focused_ic || !_focused_ic->impl || !_focused_ic->impl->is_on) {
1754             LOGD ("ic is off");
1755         } else if (g_info_manager->process_key_event (key, serial)){
1756             return;
1757         }
1758     }
1759
1760     if (!instance.null ())
1761         instance->process_key_event_done (WAYLAND_MODULE_CLIENT_ID, wsc_ctx->id, key, EINA_FALSE, serial);
1762 }
1763 #endif
1764
1765 static void
1766 wsc_commit_preedit (WSCContextISF* wsc_ctx)
1767 {
1768     LOGD ("");
1769     char* surrounding_text;
1770
1771     if (!wsc_ctx || !wsc_ctx->preedit_str ||
1772         strlen (wsc_ctx->preedit_str) == 0)
1773         return;
1774
1775     wl_input_method_context_cursor_position (wsc_ctx->im_ctx,
1776                                              0, 0);
1777
1778     if (strlen (wsc_ctx->preedit_str) > MAX_PREEDIT_BUFSIZE) {
1779         char str_buffer[MAX_PREEDIT_BUFSIZE];
1780
1781         memcpy (str_buffer, wsc_ctx->preedit_str, MAX_PREEDIT_BUFSIZE - 1);
1782         str_buffer[MAX_PREEDIT_BUFSIZE - 1] = '\0';
1783         char *old_preedit_str = wsc_ctx->preedit_str;
1784         wsc_ctx->preedit_str = (char*)realloc (wsc_ctx->preedit_str, sizeof(char) * MAX_PREEDIT_BUFSIZE);
1785         if (wsc_ctx->preedit_str) {
1786             memcpy (wsc_ctx->preedit_str, str_buffer, strlen(str_buffer));
1787             wsc_ctx->preedit_str[MAX_PREEDIT_BUFSIZE - 1] = '\0';
1788         } else {
1789             free (old_preedit_str);
1790             LOGE ("realloc failed");
1791             return;
1792         }
1793     }
1794
1795     wl_input_method_context_commit_string (wsc_ctx->im_ctx,
1796                                            wsc_ctx->serial,
1797                                            wsc_ctx->preedit_str);
1798
1799     if (wsc_ctx->surrounding_text) {
1800         surrounding_text = insert_text (wsc_ctx->surrounding_text,
1801                                         wsc_ctx->surrounding_cursor,
1802                                         wsc_ctx->preedit_str);
1803
1804         free (wsc_ctx->surrounding_text);
1805         wsc_ctx->surrounding_text = surrounding_text;
1806         wsc_ctx->surrounding_cursor += strlen (wsc_ctx->preedit_str);
1807         LOGD ("wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
1808     } else {
1809         wsc_ctx->surrounding_text = strdup (wsc_ctx->preedit_str);
1810         wsc_ctx->surrounding_cursor = strlen (wsc_ctx->preedit_str);
1811         LOGD ("wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
1812     }
1813
1814     if (wsc_ctx->preedit_str)
1815         free (wsc_ctx->preedit_str);
1816
1817     wsc_ctx->preedit_str = strdup ("");
1818 }
1819
1820 static void
1821 wsc_send_preedit_style (WSCContextISF* wsc_ctx)
1822 {
1823     LOGD ("");
1824
1825     if (!wsc_ctx) return;
1826     if (wsc_ctx->impl && wsc_ctx->impl->is_on) {
1827         String mbs = utf8_wcstombs (wsc_ctx->impl->preedit_string);
1828
1829         if (!wsc_ctx->impl->preedit_attrlist.empty ()) {
1830             if (mbs.length ()) {
1831                 uint32_t preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT;
1832                 int start_index, end_index;
1833                 int wlen = wsc_ctx->impl->preedit_string.length ();
1834                 AttributeList::const_iterator i;
1835                 bool *attrs_flag = new bool [mbs.length ()];
1836                 if (attrs_flag) {
1837                     memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1838                     for (i = wsc_ctx->impl->preedit_attrlist.begin ();
1839                          i != wsc_ctx->impl->preedit_attrlist.end (); ++i) {
1840                         start_index = i->get_start ();
1841                         end_index = i->get_end ();
1842                         if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1843                             start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1844                             end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1845                             if (i->get_type () == SCIM_ATTR_DECORATE) {
1846                                 switch (i->get_value ())
1847                                 {
1848                                     case SCIM_ATTR_DECORATE_UNDERLINE:
1849                                         preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE;
1850                                         break;
1851                                     case SCIM_ATTR_DECORATE_REVERSE:
1852                                         preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION;
1853                                         break;
1854                                     case SCIM_ATTR_DECORATE_HIGHLIGHT:
1855                                         preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT;
1856                                         break;
1857                                     case SCIM_ATTR_DECORATE_BGCOLOR1:
1858                                     case SCIM_ATTR_DECORATE_BGCOLOR2:
1859                                     case SCIM_ATTR_DECORATE_BGCOLOR3:
1860                                     case SCIM_ATTR_DECORATE_BGCOLOR4:
1861                                     default:
1862                                         preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT;
1863                                         break;
1864                                 }
1865
1866                                 if (preedit_style)
1867                                   wl_input_method_context_preedit_styling (wsc_ctx->im_ctx,
1868                                                                            start_index,
1869                                                                            end_index,
1870                                                                            preedit_style);
1871                                 switch (i->get_value ())
1872                                 {
1873                                     case SCIM_ATTR_DECORATE_UNDERLINE:
1874                                     case SCIM_ATTR_DECORATE_REVERSE:
1875                                     case SCIM_ATTR_DECORATE_HIGHLIGHT:
1876                                     case SCIM_ATTR_DECORATE_BGCOLOR1:
1877                                     case SCIM_ATTR_DECORATE_BGCOLOR2:
1878                                     case SCIM_ATTR_DECORATE_BGCOLOR3:
1879                                     case SCIM_ATTR_DECORATE_BGCOLOR4:
1880                                         // Record which character has attribute.
1881                                         for (int pos = start_index; pos < end_index; ++pos)
1882                                             attrs_flag [pos] = 1;
1883                                         break;
1884                                     default:
1885                                         break;
1886                                 }
1887                             } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1888                                 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1889                             } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1890                                 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1891                             }
1892                         }
1893                     }
1894                     // Add underline for all characters which don't have attribute.
1895                     for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1896                         if (!attrs_flag [pos]) {
1897                             int begin_pos = pos;
1898                             while (pos < mbs.length () && !attrs_flag [pos])
1899                                 ++pos;
1900                             // use REVERSE style as default
1901                             preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE;
1902                             start_index = begin_pos;
1903                             end_index = pos;
1904
1905                             wl_input_method_context_preedit_styling (wsc_ctx->im_ctx,
1906                                                                      start_index,
1907                                                                      end_index,
1908                                                                      preedit_style);
1909                         }
1910                     }
1911                     delete [] attrs_flag;
1912                 }
1913             }
1914         }
1915     } else {
1916         if (!wsc_ctx->impl->preedit_attrlist.empty ())
1917             wsc_ctx->impl->preedit_attrlist.clear ();
1918     }
1919 }
1920
1921 static void
1922 wsc_send_preedit (WSCContextISF* wsc_ctx, int32_t cursor)
1923 {
1924     LOGD ("");
1925
1926     if (!wsc_ctx) return;
1927
1928     uint32_t index = strlen (wsc_ctx->preedit_str);
1929
1930     wsc_send_preedit_style (wsc_ctx);
1931
1932     if (cursor > 0)
1933         index = cursor;
1934
1935     /* Note : Since the current wayland_immodule implementation does not call
1936      * PREEDIT_CHANGED callback even when preedit_cursor gets updated, for now
1937      * we must update preedit_string also whenever preedit_cursor is updated.
1938      * So the below 2 lines cannot be called separately. */
1939     wl_input_method_context_preedit_cursor (wsc_ctx->im_ctx, index);
1940     wl_input_method_context_preedit_string (wsc_ctx->im_ctx,
1941                                             wsc_ctx->serial,
1942                                             wsc_ctx->preedit_str,
1943                                             utf8_wcstombs (wsc_ctx->impl->commit_string).c_str ());
1944 }
1945
1946 bool wsc_context_surrounding_get (WSCContextISF *wsc_ctx, char **text, int *cursor_pos)
1947 {
1948     if (!wsc_ctx)
1949         return false;
1950
1951     if (text) {
1952         if (wsc_ctx->surrounding_text)
1953             *text = strdup (wsc_ctx->surrounding_text);
1954         else
1955             *text = strdup ("");
1956     }
1957
1958     if (cursor_pos)
1959         *cursor_pos = wsc_ctx->surrounding_cursor;
1960
1961     return true;
1962 }
1963
1964 static Eina_Bool
1965 remote_surrounding_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
1966     if (fd_handler == NULL || data == NULL)
1967         return ECORE_CALLBACK_RENEW;
1968
1969     WSCContextISF* wsc_ctx = (WSCContextISF*)data;
1970
1971     int fd = ecore_main_fd_handler_fd_get (fd_handler);
1972     char buff[512];
1973     int len = read (fd, buff, sizeof (buff) - 1);
1974
1975     if (len == 0) {
1976         SECURE_LOGD ("remote_surrounding_text : %s, surrounding_cursor : %d\n", wsc_ctx->remote_surrounding_text, wsc_ctx->surrounding_cursor);
1977         isf_wsc_context_send_surrounding_text (wsc_ctx, wsc_ctx->remote_surrounding_text ? wsc_ctx->remote_surrounding_text : "", wsc_ctx->surrounding_cursor);
1978     } else if (len < 0) {
1979         LOGW ("failed");
1980     } else {
1981         buff[len] = '\0';
1982         if (wsc_ctx->remote_surrounding_text == NULL) {
1983             if (len >= (int)sizeof(int)) {
1984                 /* Add one byte for terminating NULL character and subtract <int> byte for cursor position */
1985                 wsc_ctx->remote_surrounding_text = (char*)malloc (len + 1 - sizeof(int));
1986                 if (wsc_ctx->remote_surrounding_text) {
1987                     memcpy(&(wsc_ctx->surrounding_cursor), buff, sizeof(int));
1988                     memcpy (wsc_ctx->remote_surrounding_text, buff + sizeof(int), len - sizeof(int));
1989                     wsc_ctx->remote_surrounding_text[len - sizeof(int)] = '\0';
1990                     return ECORE_CALLBACK_RENEW;
1991                 } else {
1992                     LOGE ("malloc failed");
1993                 }
1994             }
1995         } else {
1996             int old_len = strlen (wsc_ctx->remote_surrounding_text);
1997             void * _new = realloc (wsc_ctx->remote_surrounding_text, len + old_len + 1);
1998             if (_new) {
1999                 wsc_ctx->remote_surrounding_text = (char*)_new;
2000                 memcpy (wsc_ctx->remote_surrounding_text + old_len, buff, len);
2001                 wsc_ctx->remote_surrounding_text[old_len + len] = '\0';
2002                 return ECORE_CALLBACK_RENEW;
2003             } else {
2004                 LOGE ("realloc failed");
2005             }
2006         }
2007     }
2008
2009     if (wsc_ctx->remote_surrounding_text_fd_read_handler) {
2010         close (fd);
2011         ecore_main_fd_handler_del (wsc_ctx->remote_surrounding_text_fd_read_handler);
2012         wsc_ctx->remote_surrounding_text_fd_read_handler = NULL;
2013     }
2014
2015     if (wsc_ctx->remote_surrounding_text) {
2016         free (wsc_ctx->remote_surrounding_text);
2017         wsc_ctx->remote_surrounding_text = NULL;
2018     }
2019
2020     return ECORE_CALLBACK_CANCEL;
2021 }
2022
2023 static void
2024 remote_surrounding_get (WSCContextISF *wsc_ctx)
2025 {
2026     if (wsc_ctx && wsc_ctx->im_ctx && wsc_ctx->remote_surrounding_text_fd_read_handler)
2027         return;
2028
2029     int filedes[2];
2030     if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) == -1) {
2031         LOGW ("create pipe failed");
2032         return;
2033     } else {
2034         LOGD("%d,%d", filedes[0], filedes[1]);
2035         if (wsc_ctx && wsc_ctx->im_ctx) {
2036             wl_input_method_context_get_surrounding_text (wsc_ctx->im_ctx, UINT_MAX, UINT_MAX, filedes[1]);
2037             ecore_wl_flush ();
2038         }
2039         close (filedes[1]);
2040
2041         if (wsc_ctx && wsc_ctx->im_ctx) {
2042             if (wsc_ctx->remote_surrounding_text) {
2043                 free (wsc_ctx->remote_surrounding_text);
2044                 wsc_ctx->remote_surrounding_text = NULL;
2045             }
2046
2047             wsc_ctx->remote_surrounding_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, remote_surrounding_text_fd_read_func, wsc_ctx, NULL, NULL);
2048         }
2049     }
2050 }
2051
2052 Ecore_IMF_Input_Panel_Layout wsc_context_input_panel_layout_get (WSCContextISF *wsc_ctx)
2053 {
2054     Ecore_IMF_Input_Panel_Layout layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2055
2056     if (!wsc_ctx)
2057         return layout;
2058
2059     switch (wsc_ctx->content_purpose) {
2060         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
2061         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED:
2062         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL:
2063         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL:
2064             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
2065             break;
2066         case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
2067             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER;
2068             break;
2069         case WL_TEXT_INPUT_CONTENT_PURPOSE_DATE:
2070             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH;
2071             break;
2072         case WL_TEXT_INPUT_CONTENT_PURPOSE_TIME:
2073         case WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME:
2074             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME;
2075             break;
2076         case WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE:
2077             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
2078             break;
2079         case WL_TEXT_INPUT_CONTENT_PURPOSE_URL:
2080             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
2081             break;
2082         case WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL:
2083             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
2084             break;
2085         case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
2086         case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS:
2087             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
2088             break;
2089         case WL_TEXT_INPUT_CONTENT_PURPOSE_HEX:
2090             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_HEX;
2091             break;
2092         case WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL:
2093             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL;
2094             break;
2095         case WL_TEXT_INPUT_CONTENT_PURPOSE_IP:
2096             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_IP;
2097             break;
2098         case WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON:
2099             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON;
2100             break;
2101         case WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE:
2102             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE;
2103             break;
2104         case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
2105         case WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME:
2106         case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
2107         default:
2108             layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2109             break;
2110     }
2111
2112     return layout;
2113 }
2114
2115 int wsc_context_input_panel_layout_variation_get (WSCContextISF *wsc_ctx)
2116 {
2117     int layout_variation = 0;
2118
2119     if (!wsc_ctx)
2120         return layout_variation;
2121
2122     switch (wsc_ctx->content_purpose) {
2123         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
2124             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_NORMAL;
2125             break;
2126         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED:
2127             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED;
2128             break;
2129         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL:
2130             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL;
2131             break;
2132         case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL:
2133             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL;
2134             break;
2135         case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
2136             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NORMAL;
2137             break;
2138         case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS:
2139             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY;
2140             break;
2141         case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
2142             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_NORMAL;
2143             break;
2144         case WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME:
2145             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME;
2146             break;
2147         case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
2148             layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME;
2149             break;
2150         default:
2151             layout_variation = 0;
2152             break;
2153     }
2154
2155     return layout_variation;
2156 }
2157
2158 Ecore_IMF_Autocapital_Type wsc_context_autocapital_type_get (WSCContextISF *wsc_ctx)
2159 {
2160     Ecore_IMF_Autocapital_Type autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
2161
2162     if (!wsc_ctx)
2163         return autocapital_type;
2164
2165     if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION)
2166         autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE;
2167     else if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION)
2168         autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_WORD;
2169     else if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
2170         autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER;
2171     else
2172         autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
2173
2174     return autocapital_type;
2175 }
2176
2177 bool wsc_context_input_panel_caps_lock_mode_get (WSCContextISF *wsc_ctx)
2178 {
2179     if (!wsc_ctx)
2180         return false;
2181
2182     if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
2183         return true;
2184
2185     return false;
2186 }
2187
2188 Ecore_IMF_Input_Panel_Lang wsc_context_input_panel_language_get (WSCContextISF *wsc_ctx)
2189 {
2190     Ecore_IMF_Input_Panel_Lang language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
2191
2192     if (!wsc_ctx)
2193         return language;
2194
2195     if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_LATIN)
2196         language = ECORE_IMF_INPUT_PANEL_LANG_ALPHABET;
2197     else
2198         language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
2199
2200     return language;
2201 }
2202
2203 bool wsc_context_input_panel_password_mode_get (WSCContextISF *wsc_ctx)
2204 {
2205     if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_PASSWORD)
2206         return true;
2207
2208     if (wsc_context_input_panel_layout_get (wsc_ctx) == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
2209         return true;
2210
2211     return false;
2212 }
2213
2214 Ecore_IMF_Input_Hints wsc_context_input_hint_get (WSCContextISF *wsc_ctx)
2215 {
2216     int input_hint = ECORE_IMF_INPUT_HINT_NONE;
2217
2218     if (!wsc_ctx)
2219         return (Ecore_IMF_Input_Hints)input_hint;
2220
2221     if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA)
2222         input_hint |= ECORE_IMF_INPUT_HINT_SENSITIVE_DATA;
2223     else
2224         input_hint &= ~ECORE_IMF_INPUT_HINT_SENSITIVE_DATA;
2225
2226     if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION)
2227         input_hint |= ECORE_IMF_INPUT_HINT_AUTO_COMPLETE;
2228     else
2229         input_hint &= ~ECORE_IMF_INPUT_HINT_AUTO_COMPLETE;
2230
2231     if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_MULTILINE)
2232         input_hint |= ECORE_IMF_INPUT_HINT_MULTILINE;
2233     else
2234         input_hint &= ~ECORE_IMF_INPUT_HINT_MULTILINE;
2235
2236     return (Ecore_IMF_Input_Hints)input_hint;
2237 }
2238
2239 Eina_Bool wsc_context_prediction_allow_get (WSCContextISF *wsc_ctx)
2240 {
2241     LOGD ("");
2242
2243     if (!wsc_ctx)
2244         return EINA_FALSE;
2245
2246     if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION)
2247         return EINA_TRUE;
2248     else
2249         return EINA_FALSE;
2250 }
2251
2252 Ecore_IMF_BiDi_Direction wsc_context_bidi_direction_get (WSCContextISF *wsc_ctx)
2253 {
2254     return (Ecore_IMF_BiDi_Direction)wsc_ctx->bidi_direction;
2255 }
2256
2257 void wsc_context_delete_surrounding (WSCContextISF *wsc_ctx, int offset, int len)
2258 {
2259     LOGD ("offset = %d, len = %d", offset, len);
2260
2261     if (!wsc_ctx)
2262         return;
2263
2264     wl_input_method_context_delete_surrounding_text (wsc_ctx->im_ctx, offset, len);
2265 }
2266
2267 void wsc_context_set_selection (WSCContextISF *wsc_ctx, int start, int end)
2268 {
2269     LOGD ("");
2270
2271     if (!wsc_ctx)
2272         return;
2273
2274     wl_input_method_context_selection_region (wsc_ctx->im_ctx, wsc_ctx->serial, start, end);
2275 }
2276
2277 void wsc_context_commit_string (WSCContextISF *wsc_ctx, const char *str)
2278 {
2279     LOGD ("");
2280
2281     if (!wsc_ctx)
2282         return;
2283
2284     if (wsc_ctx->preedit_str) {
2285         free (wsc_ctx->preedit_str);
2286         wsc_ctx->preedit_str = NULL;
2287     }
2288
2289     wsc_ctx->preedit_str = strdup (str);
2290     wsc_commit_preedit (wsc_ctx);
2291 }
2292
2293 void wsc_context_commit_preedit_string (WSCContextISF *wsc_ctx)
2294 {
2295     LOGD ("");
2296     char* preedit_str = NULL;
2297     int cursor_pos = 0;
2298
2299     if (!wsc_ctx)
2300         return;
2301
2302     isf_wsc_context_preedit_string_get (wsc_ctx, &preedit_str, &cursor_pos);
2303
2304     if (wsc_ctx->preedit_str) {
2305         free (wsc_ctx->preedit_str);
2306         wsc_ctx->preedit_str = NULL;
2307     }
2308
2309     wsc_ctx->preedit_str = preedit_str;
2310     wsc_commit_preedit (wsc_ctx);
2311 }
2312
2313 void wsc_context_send_preedit_string (WSCContextISF *wsc_ctx)
2314 {
2315     LOGD ("");
2316     char* preedit_str = NULL;
2317     int cursor_pos = 0;
2318
2319     if (!wsc_ctx)
2320         return;
2321
2322     isf_wsc_context_preedit_string_get (wsc_ctx, &preedit_str, &cursor_pos);
2323
2324     if (wsc_ctx->preedit_str) {
2325         free (wsc_ctx->preedit_str);
2326         wsc_ctx->preedit_str = NULL;
2327     }
2328
2329     wsc_ctx->preedit_str = preedit_str;
2330     wsc_send_preedit (wsc_ctx, cursor_pos);
2331 }
2332
2333 void wsc_context_send_key (WSCContextISF *wsc_ctx, uint32_t keysym, uint32_t modifiers, uint32_t time, bool press)
2334 {
2335     LOGD ("");
2336
2337     if (!wsc_ctx || !wsc_ctx->im_ctx)
2338         return;
2339
2340     wl_input_method_context_keysym (wsc_ctx->im_ctx, wsc_ctx->serial, time,
2341             keysym, press ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, modifiers);
2342 }
2343
2344 static void
2345 set_ic_capabilities (WSCContextISF *ic)
2346 {
2347     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2348     LOGD ("");
2349 #if 0 //FIXME
2350     if (ic && ic->impl) {
2351         unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2352
2353         if (!_on_the_spot || !ic->impl->use_preedit)
2354             cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2355
2356         //FIXME:add this interface
2357         //_info_manager->update_client_capabilities (cap);
2358     }
2359 #endif
2360 }
2361
2362 //useless
2363 #if 0
2364 /* Panel Requestion functions. */
2365 static void
2366 panel_req_show_help (WSCContextISF *ic)
2367 {
2368     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2369
2370     String help;
2371
2372     help =  String (_("Smart Common Input Method platform ")) +
2373             String (SCIM_VERSION) +
2374             String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2375
2376     if (ic && ic->impl && ic->impl->si) {
2377         IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2378         if (sf) {
2379             help += utf8_wcstombs (sf->get_name ());
2380             help += String (_(":\n\n"));
2381
2382             help += utf8_wcstombs (sf->get_help ());
2383             help += String (_("\n\n"));
2384
2385             help += utf8_wcstombs (sf->get_credits ());
2386         }
2387
2388         g_info_manager->socket_show_help (help);
2389     }
2390
2391     g_info_manager->remoteinput_callback_focus_out ();
2392     LOGD("Remote control button click");
2393 }
2394 #endif
2395
2396 static void
2397 panel_req_update_bidi_direction   (WSCContextISF *ic, int direction)
2398 {
2399     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2400
2401     if (ic)
2402         g_info_manager->update_ise_bidi_direction (WAYLAND_MODULE_CLIENT_ID, direction);
2403 }
2404
2405 static bool
2406 filter_keys (const char *keyname, const char *config_path)
2407 {
2408     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2409     LOGD ("");
2410
2411     if (!keyname)
2412         return false;
2413
2414     std::vector <String> keys;
2415     scim_split_string_list (keys, _config->read (String (config_path), String ("")), ',');
2416
2417     for (unsigned int i = 0; i < keys.size (); ++i) {
2418         if (!strcmp (keyname, keys [i].c_str ())) {
2419             return true;
2420         }
2421     }
2422
2423     return false;
2424 }
2425
2426 static void
2427 panel_initialize (void)
2428 {
2429     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2430     LOGD ("");
2431     String display_name;
2432     {
2433         const char *p = getenv ("DISPLAY");
2434         if (p) display_name = String (p);
2435     }
2436     g_info_manager->add_client (WAYLAND_MODULE_CLIENT_ID, 2, FRONTEND_CLIENT);
2437     _panel_client_id = WAYLAND_MODULE_CLIENT_ID;
2438     g_info_manager->register_panel_client (_panel_client_id, _panel_client_id);
2439     WSCContextISF* context_scim = _ic_list;
2440
2441     while (context_scim != NULL) {
2442         //FIXME:modify the parameter
2443         g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
2444
2445         context_scim = context_scim->next;
2446     }
2447
2448     if (_focused_ic) {
2449         _focused_ic = 0;
2450     }
2451 }
2452
2453 static void
2454 panel_finalize (void)
2455 {
2456     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2457     LOGD ("");
2458     g_info_manager->del_client (WAYLAND_MODULE_CLIENT_ID);
2459 }
2460
2461 static void
2462 panel_slot_update_preedit_caret (int context, int caret)
2463 {
2464     LOGD ("");
2465     WSCContextISF* ic = find_ic (context);
2466     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
2467
2468     if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
2469         ic->impl->preedit_caret = caret;
2470         if (ic->impl->use_preedit) {
2471             if (!ic->impl->preedit_started) {
2472                 if (check_valid_ic (ic))
2473                     ic->impl->preedit_started = true;
2474             }
2475             wsc_send_preedit (ic, caret);
2476         } else {
2477             g_info_manager->socket_update_preedit_caret (caret);
2478         }
2479     }
2480 }
2481
2482 static void
2483 panel_slot_process_key_event (int context, const KeyEvent &key)
2484 {
2485     WSCContextISF* ic = find_ic (context);
2486     SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2487
2488     if (!(ic && ic->impl))
2489         return;
2490
2491     if ((_focused_ic != NULL) && (_focused_ic != ic))
2492         return;
2493
2494     send_wl_key_event (ic, key, false);
2495 }
2496
2497 static void
2498 panel_slot_commit_string (int context, const WideString &wstr, bool remote_mode)
2499 {
2500     LOGD ("");
2501     WSCContextISF* ic = find_ic (context);
2502     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2503
2504     if (ic && ic->impl) {
2505         if (_focused_ic != ic)
2506             return;
2507
2508         if (remote_mode) {
2509             if (ic->impl->block_input_resource) {
2510                 LOGW ("block remote input\n");
2511                 return;
2512             }
2513             check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2514
2515             if (ic->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_URL)
2516                 wsc_context_delete_surrounding (ic, INT_MIN/2, INT_MAX);
2517
2518             wsc_context_commit_string (ic, utf8_wcstombs (wstr).c_str ());
2519             ic->impl->need_commit_preedit = false;
2520             ic->impl->preedit_string.clear ();
2521         } else {
2522             check_input_resource (ic, INPUT_RESOURCE_LOCAL);
2523             wsc_context_commit_string (ic, utf8_wcstombs (wstr).c_str ());
2524         }
2525     }
2526 }
2527
2528 static void
2529 panel_slot_forward_key_event (int context, const KeyEvent &key, bool remote_mode)
2530 {
2531     LOGD ("");
2532     WSCContextISF* ic = find_ic (context);
2533     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2534
2535     if (!(ic && ic->impl))
2536         return;
2537
2538     if ((_focused_ic != NULL) && (_focused_ic != ic))
2539         return;
2540
2541     if (remote_mode) {
2542         if (ic->impl->block_input_resource) {
2543             LOGW ("block remote input\n");
2544             return;
2545         }
2546         check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2547     } else {
2548         check_input_resource (ic, INPUT_RESOURCE_LOCAL);
2549     }
2550
2551     if (key.get_key_string ().length () >= 116)
2552         return;
2553
2554     send_wl_key_event (ic, key, true);
2555 }
2556
2557 static void
2558 panel_slot_update_preedit_string (int context, const WideString str, const WideString commit, const AttributeList &attrs, int caret, bool remote_mode)
2559 {
2560     LOGD ("");
2561     WSCContextISF* ic = find_ic (context);
2562     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
2563
2564     if (ic && ic->impl && _focused_ic == ic) {
2565         if (remote_mode) {
2566             if (ic->impl->block_input_resource) {
2567                 LOGW ("block remote input\n");
2568                 return;
2569             }
2570             check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2571         }
2572
2573         if (!ic->impl->is_on)
2574             ic->impl->is_on = true;
2575
2576         if (ic->impl->preedit_string != str || str.length ()) {
2577             ic->impl->preedit_string   = str;
2578             ic->impl->preedit_attrlist = attrs;
2579             ic->impl->commit_string = commit;
2580
2581             if (ic->impl->use_preedit) {
2582                 if (!ic->impl->preedit_started) {
2583                     if (!check_valid_ic (ic))
2584                         return;
2585
2586                     ic->impl->preedit_started = true;
2587                     ic->impl->need_commit_preedit = true;
2588                 }
2589                 if (caret >= 0 && caret <= (int)str.length ())
2590                     ic->impl->preedit_caret    = caret;
2591                 else
2592                     ic->impl->preedit_caret    = str.length ();
2593
2594                 if (ic->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_URL)
2595                     wsc_context_delete_surrounding (ic, INT_MIN/2, INT_MAX);
2596
2597                 wsc_context_send_preedit_string (ic);
2598             } else {
2599                 String _str = utf8_wcstombs (str);
2600                 g_info_manager->socket_update_preedit_string (_str, attrs, (uint32)caret);
2601             }
2602         }
2603     }
2604 }
2605
2606 static void
2607 _show_preedit_string (int context)
2608 {
2609     LOGD ("");
2610     WSCContextISF* ic = find_ic (context);
2611     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << "\n";
2612
2613     if (ic && ic->impl && _focused_ic == ic) {
2614         if (!ic->impl->is_on)
2615             ic->impl->is_on = true;
2616
2617         if (ic->impl->use_preedit) {
2618             if (!ic->impl->preedit_started) {
2619                 if (check_valid_ic (ic)) {
2620                     ic->impl->preedit_started     = true;
2621                     ic->impl->need_commit_preedit = true;
2622                 }
2623             }
2624         } else {
2625             g_info_manager->socket_show_preedit_string ();
2626         }
2627     }
2628 }
2629
2630 static void
2631 _hide_preedit_string (int context, bool update_preedit)
2632 {
2633     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2634     LOGD ("");
2635     WSCContextISF* ic = find_ic (context);
2636
2637     if (ic && ic->impl && _focused_ic == ic) {
2638         if (!ic->impl->is_on)
2639             ic->impl->is_on = true;
2640
2641         bool emit = false;
2642         if (ic->impl->preedit_string.length ()) {
2643             ic->impl->preedit_string = WideString ();
2644             ic->impl->preedit_caret  = 0;
2645             ic->impl->preedit_attrlist.clear ();
2646             emit = true;
2647         }
2648         ic->impl->commit_string = WideString ();
2649         if (ic->impl->use_preedit) {
2650             if (update_preedit && emit) {
2651                 if (!check_valid_ic (ic))
2652                     return;
2653             }
2654             if (ic->impl->preedit_started) {
2655                 if (check_valid_ic (ic)) {
2656                     ic->impl->preedit_started     = false;
2657                     ic->impl->need_commit_preedit = false;
2658                 }
2659             }
2660             wsc_context_send_preedit_string (ic);
2661         } else {
2662             g_info_manager->socket_hide_preedit_string ();
2663         }
2664     }
2665 }
2666
2667 void
2668 initialize (void)
2669 {
2670     LOGD ("Initializing Wayland ISF IMModule...\n");
2671
2672     // Get system language.
2673     _language = scim_get_locale_language (scim_get_current_locale ());
2674
2675     panel_initialize ();
2676 }
2677
2678 static void
2679 finalize (void)
2680 {
2681     LOGD ("Finalizing Ecore ISF IMModule...\n");
2682
2683     SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2684     while (_used_ic_impl_list) {
2685         // In case in "shared input method" mode,
2686         // all contexts share only one instance,
2687         // so we need point the reference pointer correctly before finalizing.
2688         #if 0 //REMOVE
2689         if (_used_ic_impl_list->si) {
2690             _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2691         }
2692         #endif
2693         if (_used_ic_impl_list->parent && _used_ic_impl_list->parent->ctx) {
2694             isf_wsc_context_del (_used_ic_impl_list->parent);
2695         }
2696     }
2697
2698     delete_all_ic_impl ();
2699
2700     SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2701     _config.reset ();
2702     _focused_ic = NULL;
2703     _ic_list = NULL;
2704
2705     _scim_initialized = false;
2706     panel_finalize ();
2707 }
2708
2709 static uint32_t _keyname_to_keysym (uint32_t keyname, uint32_t *modifiers)
2710 {
2711     if (!modifiers)
2712         return keyname;
2713
2714     if ((keyname >= '0' && keyname <= '9') ||
2715         (keyname >= 'a' && keyname <= 'z')) {
2716         return keyname;
2717     } else if (keyname >= 'A' && keyname <= 'Z') {
2718         *modifiers |= MOD_SHIFT_MASK;
2719         return keyname + 32;
2720     }
2721
2722     switch (keyname) {
2723         case '!':
2724             *modifiers |= MOD_SHIFT_MASK;
2725             return '1';
2726         case '@':
2727             *modifiers |= MOD_SHIFT_MASK;
2728             return '2';
2729         case '#':
2730             *modifiers |= MOD_SHIFT_MASK;
2731             return '3';
2732         case '$':
2733             *modifiers |= MOD_SHIFT_MASK;
2734             return '4';
2735         case '%':
2736             *modifiers |= MOD_SHIFT_MASK;
2737             return '5';
2738         case '^':
2739             *modifiers |= MOD_SHIFT_MASK;
2740             return '6';
2741         case '&':
2742             *modifiers |= MOD_SHIFT_MASK;
2743             return '7';
2744         case '*':
2745             *modifiers |= MOD_SHIFT_MASK;
2746             return '8';
2747         case '(':
2748             *modifiers |= MOD_SHIFT_MASK;
2749             return '9';
2750         case ')':
2751             *modifiers |= MOD_SHIFT_MASK;
2752             return '0';
2753         case '_':
2754             *modifiers |= MOD_SHIFT_MASK;
2755             return '-';
2756         case '+':
2757             *modifiers |= MOD_SHIFT_MASK;
2758             return '=';
2759         case '{':
2760             *modifiers |= MOD_SHIFT_MASK;
2761             return '[';
2762         case '}':
2763             *modifiers |= MOD_SHIFT_MASK;
2764             return ']';
2765         case '|':
2766             *modifiers |= MOD_SHIFT_MASK;
2767             return '\\';
2768         case ':':
2769             *modifiers |= MOD_SHIFT_MASK;
2770             return ';';
2771         case '\"':
2772             *modifiers |= MOD_SHIFT_MASK;
2773             return '\'';
2774         case '<':
2775             *modifiers |= MOD_SHIFT_MASK;
2776             return ',';
2777         case '>':
2778             *modifiers |= MOD_SHIFT_MASK;
2779             return '.';
2780         case '?':
2781             *modifiers |= MOD_SHIFT_MASK;
2782             return '/';
2783         default:
2784             return keyname;
2785     }
2786 }
2787
2788 static void send_wl_key_event (WSCContextISF *ic, const KeyEvent &key, bool fake)
2789 {
2790     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2791     LOGD ("");
2792     uint32_t time = 0;
2793     uint32_t modifiers = 0;
2794
2795     if (!fake) {
2796         time = get_time ();
2797     } else {
2798         modifiers     |= MOD_Mod5_MASK;
2799     }
2800
2801     if (key.is_shift_down ())
2802         modifiers |= MOD_SHIFT_MASK;
2803     if (key.is_alt_down ())
2804         modifiers |= MOD_ALT_MASK;
2805     if (key.is_control_down ())
2806         modifiers |= MOD_CONTROL_MASK;
2807
2808     _keyname_to_keysym (key.code, &modifiers);
2809
2810     if (ic)
2811         wsc_context_send_key (ic, key.code, modifiers, time, key.is_key_press ());
2812 }
2813
2814 static void
2815 reload_config_callback (const ConfigPointer &config)
2816 {
2817     SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2818     LOGD ("");
2819     //FIXME:_frontend_hotkey_matcher and _imengine_hotkey_matcher should be added
2820     //_frontend_hotkey_matcher.load_hotkeys (config);
2821     //_imengine_hotkey_matcher.load_hotkeys (config);
2822
2823     KeyEvent key;
2824     scim_string_to_key (key,
2825                         config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
2826                                       String ("Shift+Control+Alt+Lock")));
2827
2828     _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
2829     _valid_key_mask |= SCIM_KEY_ReleaseMask;
2830     // Special treatment for two backslash keys on jp106 keyboard.
2831     _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
2832
2833     _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
2834     //_shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
2835     _change_keyboard_mode_by_focus_move = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_CHANGE_KEYBOARD_MODE_BY_FOCUS_MOVE), _change_keyboard_mode_by_focus_move);
2836     _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
2837
2838     // Get keyboard layout setting
2839     // Flush the global config first, in order to load the new configs from disk.
2840     scim_global_config_flush ();
2841
2842     _keyboard_layout = scim_get_default_keyboard_layout ();
2843 }
2844
2845 class WaylandPanelAgent: public PanelAgentBase
2846 {
2847     Connection _config_connection;
2848
2849 public:
2850     WaylandPanelAgent ()
2851         : PanelAgentBase ("wayland") {
2852     }
2853     ~WaylandPanelAgent () {
2854         stop ();
2855     }
2856     bool initialize (InfoManager* info_manager, const String& display, bool resident) {
2857         LOGD ("");
2858         g_info_manager = info_manager;
2859         isf_wsc_context_init ();
2860
2861         if (!_wsc_setup (&_wsc)) {
2862             return false;
2863         }
2864
2865         _config_connection = _config->signal_connect_reload (slot (reload_config_callback));
2866
2867         _wl_im_ctx = new _wl_im;
2868         if (!_wl_im_ctx) {
2869             LOGW ("Can not create wl_im_ctx\n");
2870             return false;
2871         }
2872
2873         return true;
2874     }
2875     bool valid (void) const {
2876         return true;
2877     }
2878
2879     void stop (void) {
2880         if (_need_wl_im_init)
2881             wl_im_destroy ();
2882
2883         if (_wl_im_ctx) {
2884             delete _wl_im_ctx;
2885             _wl_im_ctx = NULL;
2886         }
2887
2888         _config_connection.disconnect ();
2889         isf_wsc_context_shutdown ();
2890     }
2891
2892 public:
2893     void
2894     exit (int id, uint32 contextid) {
2895         LOGD ("client id:%d", id);
2896         finalize ();
2897     }
2898
2899     void
2900     update_preedit_caret (int id, uint32 context_id, uint32 caret) {
2901         LOGD ("client id:%d", id);
2902         panel_slot_update_preedit_caret (context_id, caret);
2903     }
2904
2905     void
2906     socket_helper_key_event (int id, uint32 context_id,  int cmd , KeyEvent& key) {
2907         LOGD ("client id:%d", id);
2908
2909         if (cmd == SCIM_TRANS_CMD_PROCESS_KEY_EVENT)
2910             panel_slot_process_key_event (context_id, key);
2911         else
2912             panel_slot_forward_key_event (context_id, key, false);
2913     }
2914
2915     void
2916     commit_string (int id, uint32 context_id, const WideString& wstr) {
2917         LOGD ("client id:%d", id);
2918         panel_slot_commit_string (context_id, wstr, false);
2919     }
2920
2921     void
2922     forward_key_event (int id, uint32 context_id, const KeyEvent &key) {
2923         LOGD ("client id:%d", id);
2924         panel_slot_forward_key_event (context_id, key, false);
2925     }
2926
2927     void
2928     remote_commit_string (int id, uint32 context_id, const WideString& wstr) {
2929         LOGD ("client id:%d", id);
2930         panel_slot_commit_string (context_id, wstr, true);
2931     }
2932
2933     void
2934     remote_update_preedit_string (int id, uint32 context_id, const WideString str, const WideString commit, const AttributeList &attrs, uint32 caret) {
2935         LOGD ("client id:%d", id);
2936         panel_slot_update_preedit_string (context_id, str, commit, attrs, caret, true);
2937     }
2938
2939     void
2940     remote_forward_key_event (int id, uint32 context_id, const KeyEvent &key) {
2941         LOGD ("client id:%d", id);
2942         panel_slot_forward_key_event (context_id, key, true);
2943     }
2944
2945     void
2946     remote_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len) {
2947         LOGD ("client id:%d", id);
2948
2949         if (_focused_ic) {
2950             if (_focused_ic->impl->block_input_resource)
2951                 return;
2952
2953             check_input_resource (_focused_ic, INPUT_RESOURCE_REMOTE);
2954             wsc_context_delete_surrounding (_focused_ic, offset, len);
2955         }
2956     }
2957
2958     void
2959     update_ise_input_context (int client, uint32 context, uint32 type, uint32 value) {
2960         if (!_focused_ic || !_focused_ic->im_ctx)
2961             return;
2962
2963         wl_input_method_context_input_panel_event (_focused_ic->im_ctx, _focused_ic->serial, type, value);
2964     }
2965
2966 #if 0
2967     void
2968     request_help (int id, uint32 context_id) {
2969         LOGD ("client id:%d", id);
2970         panel_slot_request_help (context_id);
2971     }
2972
2973
2974     void
2975     request_factory_menu (int id, uint32 context_id) {
2976         LOGD ("client id:%d", id);
2977         panel_slot_request_factory_menu (context_id);
2978     }
2979
2980     void
2981     change_factory (int id, uint32 context_id, const String& uuid) {
2982         LOGD ("client id:%d", id);
2983         panel_slot_change_factory (context_id, uuid);
2984     }
2985
2986
2987     void
2988     reset_keyboard_ise (int id, uint32 context_id) {
2989         LOGD ("client id:%d", id);
2990         panel_slot_reset_keyboard_ise (context_id);
2991     }
2992
2993
2994     void
2995     update_keyboard_ise (int id, uint32 context_id) {
2996         LOGD ("client id:%d", id);
2997         panel_slot_update_keyboard_ise (context_id);
2998     }
2999 #endif
3000
3001     void
3002     show_preedit_string (int id, uint32 context_id) {
3003         LOGD ("client id:%d", id);
3004         _show_preedit_string (context_id);
3005     }
3006
3007     void
3008     hide_preedit_string (int id, uint32 context_id) {
3009         LOGD ("client id:%d", id);
3010         _hide_preedit_string (context_id, true);
3011     }
3012
3013     void
3014     update_preedit_string (int id, uint32 context_id, WideString preedit, WideString commit, AttributeList& attrs, uint32 caret) {
3015         LOGD ("client id:%d", id);
3016         SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
3017         WSCContextISF* ic = find_ic (context_id);
3018
3019         if (ic && ic->impl && _focused_ic == ic) {
3020             if (!ic->impl->is_on)
3021                 ic->impl->is_on = true;
3022
3023             check_input_resource (ic, INPUT_RESOURCE_LOCAL);
3024
3025             ic->impl->preedit_string   = preedit;
3026             ic->impl->preedit_attrlist = attrs;
3027             ic->impl->commit_string   = commit;
3028
3029             if (ic->impl->use_preedit) {
3030                 if (!ic->impl->preedit_started) {
3031                     if (!check_valid_ic (ic))
3032                         return;
3033
3034                     ic->impl->preedit_started = true;
3035                     ic->impl->need_commit_preedit = true;
3036                 }
3037                 if (caret <= preedit.length ())
3038                     ic->impl->preedit_caret    = caret;
3039                 else
3040                     ic->impl->preedit_caret    = preedit.length ();
3041                 wsc_context_send_preedit_string (ic);
3042             } else {
3043                 String _str = utf8_wcstombs (preedit);
3044                 g_info_manager->socket_update_preedit_string (_str, attrs, (uint32)caret);
3045             }
3046         }
3047     }
3048
3049     void
3050     recapture_string (int id, uint32 context_id, int offset, int len, WideString preedit, WideString commit, AttributeList& attrs) {
3051         LOGD ("client id:%d", id);
3052         SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
3053         WSCContextISF* ic = find_ic (context_id);
3054         String preedit_str = utf8_wcstombs (preedit);
3055         String commit_str = utf8_wcstombs (commit);
3056
3057         if (ic && ic->impl && _focused_ic == ic) {
3058             if (!ic->impl->is_on)
3059                 ic->impl->is_on = true;
3060
3061             check_input_resource (ic, INPUT_RESOURCE_LOCAL);
3062
3063             ic->impl->preedit_string   = preedit;
3064             ic->impl->preedit_attrlist = attrs;
3065             ic->impl->commit_string   = commit;
3066
3067             if (ic->impl->use_preedit) {
3068                 if (!ic->impl->preedit_started) {
3069                     if (!check_valid_ic (ic))
3070                         return;
3071
3072                     ic->impl->preedit_started = true;
3073                     ic->impl->need_commit_preedit = true;
3074                 }
3075                 ic->impl->preedit_caret    = preedit.length ();
3076
3077                 wl_input_method_context_preedit_cursor (ic->im_ctx, strlen(preedit_str.c_str()));
3078                 wsc_send_preedit_style (ic);
3079
3080                 wl_input_method_context_recapture_string (ic->im_ctx, ic->serial,
3081                                                           offset, len, preedit_str.c_str(), preedit_str.c_str(), commit_str.c_str());
3082             } else {
3083                 g_info_manager->socket_recapture_string (offset, len, preedit_str, commit_str, attrs);
3084             }
3085         }
3086     }
3087
3088     static Eina_Bool
3089     surrounding_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
3090         if (fd_handler == NULL || data == NULL)
3091             return ECORE_CALLBACK_RENEW;
3092
3093         WSCContextISF* wsc_ctx = (WSCContextISF*)data;
3094
3095         int fd = ecore_main_fd_handler_fd_get (fd_handler);
3096         if (fd < 0)
3097             return ECORE_CALLBACK_RENEW;
3098
3099         char buff[512];
3100         int len = read (fd, buff, sizeof (buff) - 1);
3101         if (len == 0) {
3102             LOGD ("update, wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
3103             g_info_manager->socket_update_surrounding_text (wsc_ctx->surrounding_text ? wsc_ctx->surrounding_text : "", wsc_ctx->surrounding_cursor);
3104         } else if (len < 0) {
3105             LOGW ("failed");
3106         } else {
3107             buff[len] = '\0';
3108             if (wsc_ctx->surrounding_text == NULL) {
3109                 if (len >= (int)sizeof(int)) {
3110                     /* Add one byte for terminating NULL character and subtract <int> byte for cursor position */
3111                     wsc_ctx->surrounding_text = (char*)malloc (len + 1 - sizeof(int));
3112                     if (wsc_ctx->surrounding_text) {
3113                         memcpy(&(wsc_ctx->surrounding_cursor), buff, sizeof(int));
3114                         memcpy (wsc_ctx->surrounding_text, buff + sizeof(int), len - sizeof(int));
3115                         wsc_ctx->surrounding_text[len - sizeof(int)] = '\0';
3116                         return ECORE_CALLBACK_RENEW;
3117                     } else {
3118                         LOGE ("malloc failed");
3119                     }
3120                 }
3121             } else {
3122                 int old_len = strlen (wsc_ctx->surrounding_text);
3123                 void * _new = realloc (wsc_ctx->surrounding_text, len + old_len + 1);
3124                 if (_new) {
3125                     wsc_ctx->surrounding_text = (char*)_new;
3126                     memcpy (wsc_ctx->surrounding_text + old_len, buff, len);
3127                     wsc_ctx->surrounding_text[old_len + len] = '\0';
3128                     return ECORE_CALLBACK_RENEW;
3129                 } else {
3130                     LOGE ("realloc failed");
3131                 }
3132             }
3133         }
3134
3135         if (wsc_ctx->surrounding_text_fd_read_handler) {
3136             close (fd);
3137             ecore_main_fd_handler_del (wsc_ctx->surrounding_text_fd_read_handler);
3138             wsc_ctx->surrounding_text_fd_read_handler = NULL;
3139         }
3140
3141         if (wsc_ctx->surrounding_text) {
3142             free (wsc_ctx->surrounding_text);
3143             wsc_ctx->surrounding_text = NULL;
3144         }
3145
3146         return ECORE_CALLBACK_RENEW;
3147     }
3148
3149     void
3150     socket_helper_get_surrounding_text (int id, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after) {
3151         LOGD ("client id:%d", id);
3152
3153         int filedes[2];
3154         if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) == -1) {
3155             LOGW ("create pipe failed");
3156             return;
3157         }
3158         LOGD("%d,%d", filedes[0], filedes[1]);
3159         WSCContextISF* ic = find_ic (context_id);
3160         if (!ic) return;
3161
3162         if (ic->im_ctx)
3163             wl_input_method_context_get_surrounding_text (ic->im_ctx, maxlen_before, maxlen_after, filedes[1]);
3164
3165         ecore_wl_flush ();
3166         close (filedes[1]);
3167
3168         if (ic->surrounding_text_fd_read_handler) {
3169             int fd = ecore_main_fd_handler_fd_get (ic->surrounding_text_fd_read_handler);
3170             close (fd);
3171             ecore_main_fd_handler_del (ic->surrounding_text_fd_read_handler);
3172             ic->surrounding_text_fd_read_handler = NULL;
3173         }
3174
3175         if (ic->surrounding_text) {
3176             free (ic->surrounding_text);
3177             ic->surrounding_text = NULL;
3178         }
3179
3180         ic->surrounding_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, surrounding_text_fd_read_func, ic, NULL, NULL);
3181     }
3182
3183     void
3184     socket_helper_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len) {
3185         LOGD ("client id:%d", id);
3186         //panel_slot_delete_surrounding_text (context_id, offset, len);
3187         if (_focused_ic) {
3188             check_input_resource (_focused_ic, INPUT_RESOURCE_LOCAL);
3189             wsc_context_delete_surrounding (_focused_ic, offset, len);
3190         }
3191     }
3192
3193     void
3194     socket_helper_set_selection (int id, uint32 context_id, uint32 start, uint32 end) {
3195         LOGD ("client id:%d", id);
3196         if (_focused_ic)
3197             wsc_context_set_selection (_focused_ic, start, end);
3198     }
3199
3200     void
3201     send_private_command (int id, uint32 context_id, const String& command) {
3202         LOGD ("client id:%d", id);
3203         //panel_slot_send_private_command (context_id, command);
3204         if (_focused_ic && _focused_ic->im_ctx)
3205             wl_input_method_context_private_command (_focused_ic->im_ctx, _focused_ic->serial, command.c_str ());
3206     }
3207
3208     void
3209     commit_content (int id, uint32 context_id, const String& content, const String& description, const String& mime_types) {
3210         LOGD ("client id:%d", id);
3211         if (_focused_ic && _focused_ic->im_ctx)
3212             wl_input_method_context_commit_content (_focused_ic->im_ctx, _focused_ic->serial, content.c_str (), description.c_str (), mime_types.c_str ());
3213     }
3214
3215     void
3216     hide_helper_ise (int id, uint32 context_id)
3217     {
3218         LOGD ("client id:%d", id);
3219         WSCContextISF* ic = find_ic (context_id);
3220
3221         if (ic) {
3222             wl_input_method_context_hide_input_panel (ic->im_ctx, ic->serial);
3223         }
3224     }
3225
3226     static Eina_Bool
3227     selection_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
3228         if (fd_handler == NULL || data == NULL)
3229             return ECORE_CALLBACK_RENEW;
3230
3231         WSCContextISF* wsc_ctx = (WSCContextISF*)data;
3232         LOGD("");
3233         int fd = ecore_main_fd_handler_fd_get (fd_handler);
3234         if (fd < 0)
3235             return ECORE_CALLBACK_RENEW;
3236
3237         char buff[512];
3238         int len = read (fd, buff, sizeof (buff) - 1);
3239         if (len == 0) {
3240             LOGD ("update");
3241             g_info_manager->socket_update_selection (wsc_ctx->selection_text ? wsc_ctx->selection_text : "");
3242         } else if (len < 0) {
3243             LOGW ("failed");
3244         } else {
3245             buff[len] = '\0';
3246             if (wsc_ctx->selection_text == NULL) {
3247                 wsc_ctx->selection_text = (char*)malloc (len + 1);
3248                 if (wsc_ctx->selection_text) {
3249                     memcpy (wsc_ctx->selection_text, buff, len);
3250                     wsc_ctx->selection_text[len] = '\0';
3251                     return ECORE_CALLBACK_RENEW;
3252                 } else {
3253                     LOGE ("malloc failed");
3254                 }
3255             } else {
3256                 int old_len = strlen (wsc_ctx->selection_text);
3257                 void * _new = realloc (wsc_ctx->selection_text, len + old_len + 1);
3258                 if (_new) {
3259                     wsc_ctx->selection_text = (char*)_new;
3260                     memcpy (wsc_ctx->selection_text + old_len, buff, len);
3261                     wsc_ctx->selection_text[old_len + len] = '\0';
3262                     return ECORE_CALLBACK_RENEW;
3263                 } else {
3264                     LOGE ("realloc failed");
3265                 }
3266             }
3267         }
3268
3269         if (wsc_ctx->selection_text_fd_read_handler) {
3270             close (fd);
3271             ecore_main_fd_handler_del (wsc_ctx->selection_text_fd_read_handler);
3272             wsc_ctx->selection_text_fd_read_handler = NULL;
3273         }
3274
3275         if (wsc_ctx->selection_text) {
3276             free (wsc_ctx->selection_text);
3277             wsc_ctx->selection_text = NULL;
3278         }
3279
3280         return ECORE_CALLBACK_RENEW;
3281     }
3282
3283     void
3284     socket_helper_get_selection (int id, uint32 context_id) {
3285         LOGD ("client id:%d", id);
3286
3287         int filedes[2];
3288         if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) ==-1 ) {
3289             LOGW ("create pipe failed");
3290             return;
3291         }
3292         LOGD("%d,%d", filedes[0], filedes[1]);
3293
3294         WSCContextISF* ic = find_ic (context_id);
3295         if (!ic) return;
3296
3297         wl_input_method_context_get_selection_text (ic->im_ctx, filedes[1]);
3298         ecore_wl_flush ();
3299         close (filedes[1]);
3300
3301         if (ic->selection_text_fd_read_handler) {
3302             int fd = ecore_main_fd_handler_fd_get (ic->selection_text_fd_read_handler);
3303             if (fd >= 0)
3304                 close (fd);
3305
3306             ecore_main_fd_handler_del (ic->selection_text_fd_read_handler);
3307             ic->selection_text_fd_read_handler = NULL;
3308         }
3309
3310         if (ic->selection_text) {
3311             free (ic->selection_text);
3312             ic->selection_text = NULL;
3313         }
3314
3315         ic->selection_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, selection_text_fd_read_func, ic, NULL, NULL);
3316     }
3317
3318     void process_key_event_done (int id, uint32 context_id, KeyEvent &key, uint32 ret, uint32 serial) {
3319         LOGD ("client id:%d", id);
3320         WSCContextISF* ic = find_ic (context_id);
3321         if (!ic) return;
3322
3323 #if ENABLE_GRAB_KEYBOARD
3324         if (ret == EINA_FALSE) {
3325             send_wl_key_event (ic, key, false);
3326         }
3327 #else
3328         wl_input_method_context_filter_key_event_done (ic->im_ctx, serial, ret);
3329 #endif
3330     }
3331
3332     void request_ise_hide (int id, uint32 context_id) {
3333         LOGD ("client id:%d", id);
3334         WSCContextISF* ic = find_ic (context_id);
3335         if (!ic) return;
3336
3337         wl_input_method_context_hide_input_panel (ic->im_ctx, ic->serial);
3338     }
3339
3340     void
3341     update_ise_geometry (int id, uint32 context_id, uint32 x, uint32 y, uint32 width, uint32 height) {
3342         LOGD ("client id:%d", id);
3343
3344         if (_focused_ic && _focused_ic->im_ctx) {
3345             wl_input_method_context_update_ise_geometry (_focused_ic->im_ctx, _focused_ic->serial, x, y, width, height);
3346         }
3347     }
3348
3349     void helper_candidate_show(int id, uint32 context_id, const String&  uuid)
3350     {
3351         WSCContextISF* ic = find_ic(context_id);
3352         if (!ic) return;
3353
3354         if (ic->im_ctx) {
3355             wl_input_method_context_update_candidate_state(ic->im_ctx, 1);
3356         }
3357     }
3358
3359     void helper_candidate_hide(int id, uint32 context_id, const String&  uuid)
3360     {
3361         WSCContextISF* ic = find_ic(context_id);
3362         if (!ic) return;
3363
3364         if (ic->im_ctx) {
3365             wl_input_method_context_update_candidate_state(ic->im_ctx, 0);
3366         }
3367     }
3368 };
3369
3370 extern "C" {
3371
3372     EXAPI void scim_module_init (void)
3373     {
3374         LOGD ("");
3375     }
3376
3377     EXAPI void scim_module_exit (void)
3378     {
3379         LOGD ("");
3380         instance.reset ();
3381     }
3382
3383     EXAPI void scim_panel_agent_module_init (const scim::ConfigPointer& config)
3384     {
3385         LOGD ("");
3386         _config = config;
3387     }
3388
3389     EXAPI scim::PanelAgentPointer scim_panel_agent_module_get_instance ()
3390     {
3391         scim::PanelAgentBase* _instance = NULL;
3392         if (instance.null ()) {
3393             try {
3394                 _instance = new WaylandPanelAgent ();
3395             } catch (...) {
3396                 delete _instance;
3397                 _instance = NULL;
3398             }
3399
3400             if (_instance)
3401                 instance = _instance;
3402         }
3403         return instance;
3404     }
3405 }
3406
3407 /*
3408 vi:ts=4:nowrap:expandtab
3409 */