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