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