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