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