2 * ISF(Input Service Framework)
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.
8 * Contact: Jihoon Kim <jihoon48.kim@samsung.com>, Li Zhang <li2012.zhang@samsung.com>
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)
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.
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
26 #define Uses_SCIM_PANEL_CLIENT
27 #define Uses_SCIM_CONFIG_PATH
28 #define Uses_SCIM_PANEL_AGENT
30 #include <sys/types.h>
33 #include <sys/times.h>
49 #include <Ecore_Wayland.h>
51 #include <vconf-keys.h>
52 #include <input-method-client-protocol.h>
53 #include <text-client-protocol.h>
55 #include "scim_private.h"
57 #include "isf_wsc_context.h"
58 #include "isf_wsc_control_ui.h"
59 #include "tizen_profile.h"
61 #include <linux/input.h>
63 #if ENABLE_GRAB_KEYBOARD
64 #include <xkbcommon/xkbcommon.h>
68 #include "isf_debug.h"
74 #define LOG_TAG "ISF_WAYLAND_MODULE"
78 struct _WSCContextISFImpl {
79 WSCContextISF *parent;
80 Ecore_Wl_Window *client_window;
81 Ecore_IMF_Input_Mode input_mode;
82 WideString surrounding_text;
83 WideString preedit_string;
84 AttributeList preedit_attrlist;
85 WideString commit_string;
86 Ecore_IMF_Autocapital_Type autocapital_type;
87 Ecore_IMF_Input_Hints input_hint;
88 Ecore_IMF_BiDi_Direction bidi_direction;
89 Ecore_IMF_Input_Panel_Layout panel_layout;
99 int return_key_disabled;
102 bool preedit_started;
103 bool need_commit_preedit;
104 bool init_remote_entry_metadata;
105 bool init_remote_surrounding_text;
106 bool block_input_resource;
107 Input_Resource input_resource;
109 WSCContextISFImpl *next;
112 _WSCContextISFImpl() : parent(NULL),
114 input_mode(ECORE_IMF_INPUT_MODE_FULL),
115 autocapital_type(ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE),
116 input_hint(ECORE_IMF_INPUT_HINT_NONE),
117 bidi_direction(ECORE_IMF_BIDI_DIRECTION_NEUTRAL),
118 panel_layout(ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL),
127 return_key_disabled(0),
130 preedit_started(false),
131 need_commit_preedit(false),
132 init_remote_entry_metadata(true),
133 init_remote_surrounding_text(true),
134 block_input_resource(false),
135 input_resource(INPUT_RESOURCE_NONE),
141 /* private functions */
143 static void panel_slot_update_preedit_caret (int context,
145 static void panel_slot_process_key_event (int context,
146 const KeyEvent &key);
147 static void panel_slot_commit_string (int context,
148 const WideString &wstr,
150 static void panel_slot_forward_key_event (int context,
153 static void panel_slot_update_preedit_string (int context,
154 const WideString str,
155 const WideString commit,
156 const AttributeList &attrs,
159 static void _show_preedit_string (int context);
161 static void panel_req_update_bidi_direction (WSCContextISF *ic, int direction);
163 static void remote_surrounding_get (WSCContextISF *wsc_ctx);
165 static void wl_im_destroy (void);
167 /* Panel iochannel handler*/
168 static void panel_initialize (void);
169 static void panel_finalize (void);
171 /* utility functions */
173 static bool filter_keys (const char *keyname,
174 const char *config_path);
175 static void set_ic_capabilities (WSCContextISF *ic);
177 static void initialize (void);
178 static void finalize (void);
180 static void send_wl_key_event (WSCContextISF *ic, const KeyEvent &key, bool fake);
181 static void _hide_preedit_string (int context, bool update_preedit);
183 /* Local variables declaration */
184 static String _language;
185 static WSCContextISFImpl *_used_ic_impl_list = 0;
186 static WSCContextISFImpl *_free_ic_impl_list = 0;
187 static WSCContextISF *_ic_list = 0;
189 static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
190 static int _valid_key_mask = SCIM_KEY_AllMasks;
192 static ConfigPointer _config;
194 static WSCContextISF *_focused_ic = 0;
196 static bool _scim_initialized = false;
198 static int _panel_client_id = 0;
199 static uint32 _active_helper_option = 0;
201 static bool _on_the_spot = true;
202 static bool _change_keyboard_mode_by_focus_move = false;
203 static bool _support_hw_keyboard_mode = false;
205 static bool _x_key_event_is_valid = false;
207 static Ecore_Timer *_resource_check_timer = NULL;
209 static bool _need_wl_im_init = false;
210 static struct _wl_im *_wl_im_ctx = NULL;
211 static int _ecore_wl_init_count = 0;
213 #define WAYLAND_MODULE_CLIENT_ID (0)
214 #define MAX_PREEDIT_BUFSIZE 4000
216 #define MOD_SHIFT_MASK 0x01
217 #define MOD_CAPS_MASK 0x02
218 #define MOD_CONTROL_MASK 0x04
219 #define MOD_ALT_MASK 0x08
220 #define MOD_NUM_MASK 0x100
221 #define MOD_Mod5_MASK 0x80
223 //////////////////////////////wayland_panel_agent_module begin//////////////////////////////////////////////////
225 #define scim_module_init wayland_LTX_scim_module_init
226 #define scim_module_exit wayland_LTX_scim_module_exit
227 #define scim_panel_agent_module_init wayland_LTX_scim_panel_agent_module_init
228 #define scim_panel_agent_module_get_instance wayland_LTX_scim_panel_agent_module_get_instance
230 static struct weescim _wsc = {0};
232 InfoManager* g_info_manager = NULL;
233 static scim::PanelAgentPointer instance;
236 /////////////////////////////////////////////////////////////////////////////
237 // Implementation of Wayland Input Method functions.
238 /////////////////////////////////////////////////////////////////////////////
241 _wsc_im_ctx_reset (void *data, struct wl_input_method_context *im_ctx)
243 WSCContextISF *context_scim = (WSCContextISF*)data;
245 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
246 g_info_manager->socket_reset_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
251 _wsc_im_ctx_content_type (void *data, struct wl_input_method_context *im_ctx, uint32_t hint, uint32_t purpose)
253 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
254 if (!wsc_ctx) return;
256 LOGD ("im_context = %p hint = %04x purpose = %d\n", im_ctx, hint, purpose);
259 if (wsc_ctx->content_purpose != purpose || !wsc_ctx->layout_initialized) {
260 wsc_ctx->layout_initialized = EINA_TRUE;
261 wsc_ctx->content_purpose = purpose;
262 isf_wsc_context_input_panel_layout_set (wsc_ctx, wsc_context_input_panel_layout_get (wsc_ctx));
265 if (wsc_ctx->content_hint != hint) {
266 uint32_t hint_copy, old_hintbit, new_hintbit;
267 const uint32_t autocap_type = WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
268 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
269 WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
271 hint_copy = wsc_ctx->content_hint;
272 wsc_ctx->content_hint = hint;
274 // Set prediction allow
275 old_hintbit = hint_copy & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
276 new_hintbit = hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
277 if (old_hintbit != new_hintbit || !wsc_ctx->prediction_allow_initialized) {
278 wsc_ctx->prediction_allow_initialized = EINA_TRUE;
279 g_info_manager->set_prediction_allow (WAYLAND_MODULE_CLIENT_ID, wsc_context_prediction_allow_get (wsc_ctx));
282 // Set autocapital type
283 old_hintbit = hint_copy & autocap_type;
284 new_hintbit = hint & autocap_type;
285 if (old_hintbit != new_hintbit || !wsc_ctx->autocapital_type_initialized) {
286 wsc_ctx->autocapital_type_initialized = EINA_TRUE;
287 isf_wsc_context_autocapital_type_set (wsc_ctx, wsc_context_autocapital_type_get (wsc_ctx));
291 old_hintbit = hint_copy & WL_TEXT_INPUT_CONTENT_HINT_LATIN;
292 new_hintbit = hint & WL_TEXT_INPUT_CONTENT_HINT_LATIN;
293 if (old_hintbit != new_hintbit || !wsc_ctx->language_initialized) {
294 wsc_ctx->language_initialized = EINA_TRUE;
295 isf_wsc_context_input_panel_language_set (wsc_ctx, wsc_context_input_panel_language_get (wsc_ctx));
300 isf_wsc_context_send_entry_metadata (wsc_ctx, wsc_context_input_hint_get (wsc_ctx), wsc_context_input_panel_layout_get (wsc_ctx),
301 wsc_context_input_panel_layout_variation_get (wsc_ctx), wsc_context_autocapital_type_get (wsc_ctx), wsc_ctx->return_key_disabled);
306 _wsc_im_ctx_invoke_action (void *data, struct wl_input_method_context *im_ctx, uint32_t button, uint32_t index)
308 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
309 if (!wsc_ctx) return;
311 LOGD ("invoke action. button : %d\n", button);
313 if (button != BTN_LEFT)
316 wsc_context_send_preedit_string (wsc_ctx);
320 _wsc_im_ctx_commit_state (void *data, struct wl_input_method_context *im_ctx, uint32_t serial)
322 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
323 if (!wsc_ctx) return;
325 wsc_ctx->serial = serial;
327 if (wsc_ctx->language)
328 wl_input_method_context_language (im_ctx, wsc_ctx->serial, wsc_ctx->language);
332 _wsc_im_ctx_preferred_language (void *data, struct wl_input_method_context *im_ctx, const char *language)
334 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
335 if (!wsc_ctx) return;
337 if (language && wsc_ctx->language && !strcmp (language, wsc_ctx->language))
340 if (wsc_ctx->language) {
341 free (wsc_ctx->language);
342 wsc_ctx->language = NULL;
346 wsc_ctx->language = strdup (language);
347 LOGD ("Language changed, new: '%s'\n", language);
352 _wsc_im_ctx_return_key_type (void *data, struct wl_input_method_context *im_ctx, uint32_t return_key_type)
354 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
356 LOGD ("im_context = %p return key type = %d\n", im_ctx, return_key_type);
357 if (!wsc_ctx) return;
359 if (wsc_ctx->return_key_type != return_key_type) {
360 wsc_ctx->return_key_type = return_key_type;
361 isf_wsc_context_input_panel_return_key_type_set (wsc_ctx, (Ecore_IMF_Input_Panel_Return_Key_Type)wsc_ctx->return_key_type);
366 _wsc_im_ctx_return_key_disabled (void *data, struct wl_input_method_context *im_ctx, uint32_t disabled)
368 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
369 Eina_Bool return_key_disabled = !!disabled;
371 LOGD ("im_context = %p return key disabled = %d\n", im_ctx, return_key_disabled);
372 if (!wsc_ctx) return;
374 if (wsc_ctx->return_key_disabled != return_key_disabled) {
375 wsc_ctx->return_key_disabled = return_key_disabled;
376 isf_wsc_context_input_panel_return_key_disabled_set (wsc_ctx, wsc_ctx->return_key_disabled);
378 isf_wsc_context_send_entry_metadata (wsc_ctx, wsc_context_input_hint_get (wsc_ctx), wsc_context_input_panel_layout_get (wsc_ctx),
379 wsc_context_input_panel_layout_variation_get (wsc_ctx), wsc_context_autocapital_type_get (wsc_ctx), wsc_ctx->return_key_disabled);
384 _wsc_im_ctx_input_panel_data (void *data, struct wl_input_method_context *im_ctx, const char *input_panel_data, uint32_t input_panel_data_length)
386 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
387 LOGD ("im_context = %p input panel data = %s len = %d\n", im_ctx, input_panel_data, input_panel_data_length);
388 if (!wsc_ctx) return;
391 if (wsc_ctx->impl->imdata) {
392 free(wsc_ctx->impl->imdata);
395 wsc_ctx->impl->imdata = calloc(1, input_panel_data_length);
396 if (wsc_ctx->impl->imdata)
397 memcpy(wsc_ctx->impl->imdata, input_panel_data, input_panel_data_length);
399 wsc_ctx->impl->imdata_size = input_panel_data_length;
402 isf_wsc_context_input_panel_imdata_set (wsc_ctx, (void *)input_panel_data, input_panel_data_length);
406 _wsc_im_ctx_bidi_direction (void *data, struct wl_input_method_context *im_ctx, uint32_t bidi_direction)
408 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
410 LOGD ("im_context = %p bidi_direction = %d\n", im_ctx, bidi_direction);
411 if (!wsc_ctx) return;
413 if (wsc_ctx->bidi_direction != bidi_direction) {
414 wsc_ctx->bidi_direction = bidi_direction;
416 isf_wsc_context_bidi_direction_set (wsc_ctx, (Ecore_IMF_BiDi_Direction)wsc_ctx->bidi_direction);
421 _wsc_im_ctx_cursor_position (void *data, struct wl_input_method_context *im_ctx, uint32_t cursor_pos)
423 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
425 LOGD ("im_context = %p cursor_pos = %d\n", im_ctx, cursor_pos);
426 if (!wsc_ctx || !wsc_ctx->impl) return;
427 wsc_ctx->impl->cursor_pos = cursor_pos;
428 wsc_ctx->surrounding_cursor = cursor_pos;
429 LOGD ("wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
430 g_info_manager->socket_update_cursor_position (cursor_pos);
433 remote_surrounding_get (wsc_ctx);
437 _wsc_im_ctx_process_input_device_event (void *data, struct wl_input_method_context *im_ctx, uint32_t type, const char *input_data, uint32_t input_data_len)
439 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
441 LOGD("im_context = %p type = %d, data = (%p) %d\n", im_ctx, type, input_data, input_data_len);
442 if (!wsc_ctx) return;
444 isf_wsc_context_process_input_device_event (wsc_ctx, type, input_data, input_data_len);
448 _wsc_im_ctx_filter_key_event (void *data, struct wl_input_method_context *im_ctx, uint32_t serial, uint32_t time, const char *keyname, uint32_t state, uint32_t modifiers, const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
450 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
451 if (!wsc_ctx) return;
453 #if !(ENABLE_GRAB_KEYBOARD)
454 isf_wsc_context_filter_key_event (wsc_ctx, serial, time, keyname,
455 ((wl_keyboard_key_state)state) == WL_KEYBOARD_KEY_STATE_PRESSED, modifiers, dev_name, dev_class, dev_subclass);
460 _wsc_im_ctx_captial_mode (void *data, struct wl_input_method_context *im_ctx, uint32_t mode)
462 LOGD ("capital mode %d", mode);
463 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
464 if (!wsc_ctx) return;
465 wsc_ctx->caps_mode = mode;
466 isf_wsc_context_input_panel_caps_mode_set (wsc_ctx, mode);
470 _wsc_im_ctx_prediction_hint (void *data, struct wl_input_method_context *im_ctx, const char *prediction_hint)
472 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
474 LOGD ("im_context = %p, prediction hint = %s\n", im_ctx, prediction_hint);
475 if (!wsc_ctx) return;
477 isf_wsc_context_input_panel_prediction_hint_set (wsc_ctx, prediction_hint);
481 _wsc_im_ctx_mime_type (void *data, struct wl_input_method_context *im_ctx, const char *mime_type)
483 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
485 LOGD ("im_context = %p, mime_type = %s\n", im_ctx, mime_type);
486 if (!wsc_ctx) return;
489 wsc_ctx->impl->mime_type = strdup (mime_type);
492 isf_wsc_context_input_panel_mime_type_accept_set (wsc_ctx, mime_type);
495 static const struct wl_input_method_context_listener wsc_im_context_listener = {
497 _wsc_im_ctx_content_type,
498 _wsc_im_ctx_invoke_action,
499 _wsc_im_ctx_commit_state,
500 _wsc_im_ctx_preferred_language,
501 _wsc_im_ctx_return_key_type,
502 _wsc_im_ctx_return_key_disabled,
503 _wsc_im_ctx_input_panel_data,
504 _wsc_im_ctx_bidi_direction,
505 _wsc_im_ctx_cursor_position,
506 _wsc_im_ctx_process_input_device_event,
507 _wsc_im_ctx_filter_key_event,
508 _wsc_im_ctx_captial_mode,
509 _wsc_im_ctx_prediction_hint,
510 _wsc_im_ctx_mime_type
513 #if ENABLE_GRAB_KEYBOARD
515 _init_keysym2keycode (WSCContextISF *wsc_ctx)
520 const xkb_keysym_t *syms;
522 if (!wsc_ctx || !wsc_ctx->state)
525 for (i = 0; i < 256; i++) {
527 num_syms = xkb_key_get_syms (wsc_ctx->state, code, &syms);
530 wsc_ctx->_keysym2keycode[syms[0]] = i;
535 _fini_keysym2keycode (WSCContextISF *wsc_ctx)
537 wsc_ctx->_keysym2keycode.clear ();
541 _wsc_im_keyboard_keymap (void *data,
542 struct wl_keyboard *wl_keyboard,
547 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
555 _fini_keysym2keycode (wsc_ctx);
557 if (wsc_ctx->state) {
558 xkb_state_unref (wsc_ctx->state);
559 wsc_ctx->state = NULL;
562 if (wsc_ctx->keymap) {
563 xkb_map_unref (wsc_ctx->keymap);
564 wsc_ctx->keymap = NULL;
567 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
572 map_str = (char*)mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
573 if (map_str == MAP_FAILED) {
579 xkb_map_new_from_string (wsc_ctx->xkb_context,
581 XKB_KEYMAP_FORMAT_TEXT_V1,
582 (xkb_keymap_compile_flags)0);
584 munmap (map_str, size);
587 if (!wsc_ctx->keymap) {
588 LOGW ("failed to compile keymap\n");
592 wsc_ctx->state = xkb_state_new (wsc_ctx->keymap);
593 if (!wsc_ctx->state) {
594 LOGW ("failed to create XKB state\n");
595 xkb_map_unref (wsc_ctx->keymap);
599 wsc_ctx->control_mask =
600 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Control");
602 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Mod1");
603 wsc_ctx->shift_mask =
604 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Shift");
606 LOGD ("create _keysym2keycode\n");
607 _init_keysym2keycode (wsc_ctx);
611 _wsc_im_keyboard_key (void *data,
612 struct wl_keyboard *wl_keyboard,
618 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
621 const xkb_keysym_t *syms;
623 char keyname[64] = {0};
624 enum wl_keyboard_key_state state = (wl_keyboard_key_state)state_w;
626 if (!wsc_ctx || !wsc_ctx->state)
630 num_syms = xkb_key_get_syms (wsc_ctx->state, code, &syms);
632 sym = XKB_KEY_NoSymbol;
635 xkb_keysym_get_name (sym, keyname, 64);
638 isf_wsc_context_filter_key_event (wsc_ctx, serial, time, code, sym, keyname,
643 _wsc_im_keyboard_modifiers (void *data,
644 struct wl_keyboard *wl_keyboard,
646 uint32_t mods_depressed,
647 uint32_t mods_latched,
648 uint32_t mods_locked,
651 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
652 if (!wsc_ctx || !wsc_ctx->state)
655 struct wl_input_method_context *context = wsc_ctx->im_ctx;
658 xkb_state_update_mask (wsc_ctx->state, mods_depressed,
659 mods_latched, mods_locked, 0, 0, group);
660 mask = xkb_state_serialize_mods (wsc_ctx->state,
661 (xkb_state_component)(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED));
663 wsc_ctx->modifiers = 0;
664 if (mask & wsc_ctx->control_mask)
665 wsc_ctx->modifiers |= SCIM_KEY_ControlMask;
666 if (mask & wsc_ctx->alt_mask)
667 wsc_ctx->modifiers |= SCIM_KEY_AltMask;
668 if (mask & wsc_ctx->shift_mask)
669 wsc_ctx->modifiers |= SCIM_KEY_ShiftMask;
671 wl_input_method_context_modifiers (context, serial,
672 mods_depressed, mods_depressed,
673 mods_latched, group);
676 static const struct wl_keyboard_listener wsc_im_keyboard_listener = {
677 _wsc_im_keyboard_keymap,
680 _wsc_im_keyboard_key,
681 _wsc_im_keyboard_modifiers
688 if (!_wl_im_ctx || !_wl_im_ctx->wsc || !_wl_im_ctx->wsc->wsc_ctx)
691 WSCContextISF *wsc_ctx = _wl_im_ctx->wsc->wsc_ctx;
693 if (_wl_im_ctx->need_focus_event)
694 isf_wsc_context_focus_out (wsc_ctx);
696 #if ENABLE_GRAB_KEYBOARD
697 if (wsc_ctx->keyboard) {
698 wl_keyboard_destroy (wsc_ctx->keyboard);
699 wsc_ctx->keyboard = NULL;
702 _fini_keysym2keycode (wsc_ctx);
704 if (wsc_ctx->state) {
705 xkb_state_unref (wsc_ctx->state);
706 wsc_ctx->state = NULL;
709 if (wsc_ctx->keymap) {
710 xkb_map_unref (wsc_ctx->keymap);
711 wsc_ctx->keymap = NULL;
714 if (wsc_ctx->xkb_context) {
715 xkb_context_unref (wsc_ctx->xkb_context);
716 wsc_ctx->xkb_context = NULL;
720 if (wsc_ctx->im_ctx) {
721 wl_input_method_context_destroy (wsc_ctx->im_ctx);
722 wsc_ctx->im_ctx = NULL;
725 if (wsc_ctx->preedit_str) {
726 free (wsc_ctx->preedit_str);
727 wsc_ctx->preedit_str = NULL;
730 if (wsc_ctx->surrounding_text) {
731 free (wsc_ctx->surrounding_text);
732 wsc_ctx->surrounding_text = NULL;
735 if (wsc_ctx->remote_surrounding_text) {
736 free (wsc_ctx->remote_surrounding_text);
737 wsc_ctx->remote_surrounding_text = NULL;
740 if (wsc_ctx->language) {
741 free (wsc_ctx->language);
742 wsc_ctx->language = NULL;
745 wsc_ctx->layout_initialized = EINA_FALSE;
746 wsc_ctx->prediction_allow_initialized = EINA_FALSE;
747 wsc_ctx->autocapital_type_initialized = EINA_FALSE;
748 wsc_ctx->language_initialized = EINA_FALSE;
750 if (_resource_check_timer)
751 ecore_timer_del (_resource_check_timer);
752 _resource_check_timer = NULL;
754 isf_wsc_context_del (wsc_ctx);
756 _wl_im_ctx->wsc->wsc_ctx = NULL;
757 _wl_im_ctx->input_method = NULL;
758 _wl_im_ctx->im_ctx = NULL;
759 _wl_im_ctx->need_focus_event = EINA_FALSE;
760 _need_wl_im_init = false;
764 _wsc_im_activate (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx, uint32_t text_input_id, uint32_t focus_in_event)
766 struct weescim *wsc = (weescim*)data;
769 WSCContextISF *wsc_ctx = new WSCContextISF;
774 if (_need_wl_im_init)
777 #if ENABLE_GRAB_KEYBOARD
778 wsc_ctx->xkb_context = xkb_context_new ((xkb_context_flags)0);
779 if (wsc_ctx->xkb_context == NULL) {
780 LOGW ("Failed to create XKB context\n");
784 wsc_ctx->state = NULL;
785 wsc_ctx->keymap = NULL;
786 wsc_ctx->modifiers = 0;
789 wsc_ctx->id = text_input_id;
790 wsc->wsc_ctx = wsc_ctx;
792 wsc_ctx->surrounding_text = NULL;
793 wsc_ctx->remote_surrounding_text = NULL;
794 wsc_ctx->surrounding_cursor = 0;
795 LOGD ("wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
797 get_language (&wsc_ctx->language);
799 wsc_ctx->preedit_str = strdup ("");
800 wsc_ctx->content_hint = WL_TEXT_INPUT_CONTENT_HINT_NONE;
801 wsc_ctx->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
803 wsc_ctx->im_ctx = im_ctx;
804 wl_input_method_context_add_listener (im_ctx, &wsc_im_context_listener, wsc_ctx);
806 #if ENABLE_GRAB_KEYBOARD
807 wsc_ctx->keyboard = wl_input_method_context_grab_keyboard (im_ctx);
808 if (wsc_ctx->keyboard)
809 wl_keyboard_add_listener (wsc_ctx->keyboard, &wsc_im_keyboard_listener, wsc_ctx);
812 if (wsc_ctx->language)
813 wl_input_method_context_language (im_ctx, wsc_ctx->serial, wsc_ctx->language);
815 isf_wsc_context_add (wsc_ctx);
817 if (focus_in_event) {
818 isf_wsc_context_focus_in (wsc_ctx);
819 _wl_im_ctx->need_focus_event = EINA_TRUE;
824 _wsc_im_deactivate (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx, uint32_t focus_out_event)
826 struct weescim *wsc = (weescim*)data;
827 if (!wsc || !wsc->wsc_ctx) return;
829 /* When the focus_in/input_panel_shutdown event is called,
830 * it is not possible to know the information of wl_input_method to destroy */
831 _wl_im_ctx->wsc = wsc;
832 _wl_im_ctx->input_method = input_method;
833 _wl_im_ctx->im_ctx = im_ctx;
834 _need_wl_im_init = true;
836 if (focus_out_event) {
837 isf_wsc_context_focus_out (wsc->wsc_ctx);
838 _wl_im_ctx->need_focus_event = EINA_FALSE;
843 _wsc_im_show_input_panel (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
845 struct weescim *wsc = (weescim*)data;
846 if (!wsc || !wsc->wsc_ctx) return;
848 isf_wsc_context_input_panel_show (wsc->wsc_ctx);
849 wsc->wsc_ctx->input_panel_shown = true;
852 remote_surrounding_get (wsc->wsc_ctx);
856 _wsc_im_hide_input_panel (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
858 struct weescim *wsc = (weescim*)data;
859 if (!wsc || !wsc->wsc_ctx) return;
861 isf_wsc_context_input_panel_hide (wsc->wsc_ctx);
862 wsc->wsc_ctx->input_panel_shown = false;
865 static const struct wl_input_method_listener wsc_im_listener = {
868 _wsc_im_show_input_panel,
869 _wsc_im_hide_input_panel
873 _wsc_setup (struct weescim *wsc)
875 Eina_Inlist *globals;
876 struct wl_registry *registry;
877 Ecore_Wl_Global *global;
879 if (!wsc) return false;
881 if (!(registry = ecore_wl_registry_get ())) {
882 LOGW ("failed to get wl_registry");
886 if (!(globals = ecore_wl_globals_get ())) {
887 LOGW ("failed to get wl_globals");
891 EINA_INLIST_FOREACH(globals, global) {
892 if (strcmp (global->interface, "wl_input_method") == 0)
893 wsc->im = (wl_input_method*)wl_registry_bind (registry, global->id, &wl_input_method_interface, 1);
896 if (wsc->im == NULL) {
897 LOGW ("Failed because wl_input_method is null\n");
901 /* Input method listener */
902 LOGD ("Adding wl_input_method listener\n");
905 wl_input_method_add_listener (wsc->im, &wsc_im_listener, wsc);
907 LOGW ("Couldn't get wayland input method interface\n");
915 //////////////////////////////wayland_panel_agent_module end//////////////////////////////////////////////////
924 get_panel_client_id (void)
926 return _panel_client_id;
930 get_language (char **language)
932 *language = strdup (_language.c_str ());
940 struct timezone tz; /* is not used since ages */
941 gettimeofday (&tv, &tz);
942 tint = (unsigned int)(tv.tv_sec * 1000);
943 tint = tint / 1000 * 1000;
944 tint = (unsigned int)(tint + tv.tv_usec / 1000);
948 /* Function Implementations */
949 static WSCContextISFImpl *
950 new_ic_impl (WSCContextISF *parent)
952 WSCContextISFImpl *impl = NULL;
954 if (_free_ic_impl_list != NULL) {
955 impl = _free_ic_impl_list;
956 _free_ic_impl_list = _free_ic_impl_list->next;
958 impl = new WSCContextISFImpl;
963 impl->next = _used_ic_impl_list;
964 _used_ic_impl_list = impl;
966 impl->parent = parent;
972 delete_ic_impl (WSCContextISFImpl *impl)
974 WSCContextISFImpl *rec = _used_ic_impl_list, *last = 0;
976 for (; rec != 0; last = rec, rec = rec->next) {
979 last->next = rec->next;
981 _used_ic_impl_list = rec->next;
983 rec->next = _free_ic_impl_list;
984 _free_ic_impl_list = rec;
991 rec->imdata_size = 0;
993 rec->client_window = 0;
994 rec->mime_type = String ();
995 rec->surrounding_text = WideString ();
996 rec->preedit_string = WideString ();
997 rec->preedit_attrlist.clear ();
998 rec->commit_string = WideString ();
999 rec->block_input_resource = true;
1006 delete_all_ic_impl (void)
1008 WSCContextISFImpl *it = _used_ic_impl_list;
1011 _used_ic_impl_list = it->next;
1013 it = _used_ic_impl_list;
1016 it = _free_ic_impl_list;
1018 _free_ic_impl_list = it->next;
1020 it = _free_ic_impl_list;
1024 static WSCContextISF *
1027 WSCContextISFImpl *rec = _used_ic_impl_list;
1030 if (rec->parent && rec->parent->id == id)
1039 check_valid_ic (WSCContextISF * ic)
1041 if (ic && ic->impl && ic->ctx)
1047 void context_scim_imdata_get (WSCContextISF *wsc_ctx, void* data, int* length)
1049 WSCContextISF* context_scim = wsc_ctx;
1051 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1053 if (context_scim && context_scim->impl) {
1054 if (data && context_scim->impl->imdata)
1055 memcpy (data, context_scim->impl->imdata, context_scim->impl->imdata_size);
1058 *length = context_scim->impl->imdata_size;
1062 void context_scim_mime_type_get (WSCContextISF *wsc_ctx, const char *mime_type)
1064 WSCContextISF* context_scim = wsc_ctx;
1066 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1068 if (context_scim && context_scim->impl) {
1069 if (!(context_scim->impl->mime_type).empty ())
1070 memcpy ((void *)mime_type ,(context_scim->impl->mime_type).c_str (),
1071 strlen ((context_scim->impl->mime_type).c_str ()));
1076 insert_text (const char *text, uint32_t offset, const char *insert)
1078 uint32_t tlen = strlen (text), ilen = strlen (insert);
1079 char *new_text = (char*)malloc (tlen + ilen + 1);
1081 if ((unsigned int) tlen < offset)
1083 memcpy (new_text, text, offset);
1084 memcpy (new_text + offset, insert, ilen);
1085 memcpy (new_text + offset + ilen, text + offset, tlen - offset);
1086 new_text[tlen + ilen] = '\0';
1093 change_block_status_timer_cb (void *data)
1095 WSCContextISF* context_scim = static_cast<WSCContextISF*>(data);
1096 if (context_scim && context_scim->impl)
1097 context_scim->impl->block_input_resource = false;
1099 _resource_check_timer = NULL;
1101 return ECORE_CALLBACK_CANCEL;
1105 check_input_resource (WSCContextISF* wsc_ctx, Input_Resource input_res)
1107 WSCContextISF* context_scim = wsc_ctx;
1108 LOGD ("Input resource : %d\n", input_res);
1109 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1111 if (context_scim && context_scim->impl) {
1112 if (context_scim->impl->input_resource == input_res)
1116 if (context_scim->impl->input_resource != input_res && input_res != INPUT_RESOURCE_NONE)
1117 g_info_manager->remoteinput_callback_input_resource (input_res);
1119 if (context_scim->impl->input_resource == INPUT_RESOURCE_REMOTE && input_res == INPUT_RESOURCE_LOCAL) {
1120 if (context_scim->impl->need_commit_preedit) {
1121 WideString wstr = context_scim->impl->preedit_string;
1122 _hide_preedit_string (context_scim->id, false);
1123 wsc_context_commit_string (context_scim, utf8_wcstombs (wstr).c_str ());
1125 context_scim->impl->need_commit_preedit = false;
1126 context_scim->impl->preedit_string.clear ();
1129 if (_resource_check_timer)
1130 ecore_timer_del (_resource_check_timer);
1131 _resource_check_timer = ecore_timer_add (2.0, change_block_status_timer_cb, context_scim);
1132 context_scim->impl->block_input_resource = true;
1134 context_scim->impl->input_resource = input_res;
1138 /* Public functions */
1140 isf_wsc_context_init (void)
1142 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1145 if (!_scim_initialized) {
1146 _ecore_wl_init_count = ecore_wl_init (NULL);
1148 _scim_initialized = true;
1149 isf_wsc_input_panel_init ();
1150 //isf_wsc_context_set_hardware_keyboard_mode(context_scim);
1155 isf_wsc_context_shutdown (void)
1158 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1160 if (_scim_initialized) {
1161 _scim_initialized = false;
1163 isf_wsc_input_panel_shutdown ();
1166 if (_ecore_wl_init_count > 0) {
1167 ecore_wl_shutdown ();
1168 _ecore_wl_init_count = 0;
1174 isf_wsc_context_add (WSCContextISF *wsc_ctx)
1176 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1178 WSCContextISF* context_scim = wsc_ctx;
1180 if (!context_scim) return;
1181 context_scim->surrounding_text_fd_read_handler = NULL;
1182 context_scim->selection_text_fd_read_handler = NULL;
1183 context_scim->remote_surrounding_text_fd_read_handler = NULL;
1184 context_scim->surrounding_text = NULL;
1185 context_scim->remote_surrounding_text = NULL;
1186 context_scim->selection_text = NULL;
1188 context_scim->impl = new_ic_impl (context_scim);
1189 if (context_scim->impl == NULL) {
1190 std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
1194 context_scim->impl->client_window = 0;
1195 context_scim->impl->preedit_caret = 0;
1196 context_scim->impl->cursor_x = 0;
1197 context_scim->impl->cursor_y = 0;
1198 context_scim->impl->cursor_pos = -1;
1199 context_scim->impl->cursor_top_y = 0;
1200 context_scim->impl->is_on = true;
1201 context_scim->impl->use_preedit = _on_the_spot;
1202 context_scim->impl->preedit_started = false;
1203 context_scim->impl->need_commit_preedit = false;
1206 context_scim->next = NULL;
1208 context_scim->next = _ic_list;
1209 _ic_list = context_scim;
1211 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1213 g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1214 set_ic_capabilities (context_scim);
1215 SCIM_DEBUG_FRONTEND (2) << "input context created: id = " << context_scim->id << "\n";
1219 isf_wsc_context_del (WSCContextISF *wsc_ctx)
1221 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1224 if (!_ic_list) return;
1226 WSCContextISF *context_scim = wsc_ctx;
1227 if (!context_scim) return;
1229 if (context_scim->selection_text_fd_read_handler) {
1230 int fd = ecore_main_fd_handler_fd_get (context_scim->selection_text_fd_read_handler);
1232 ecore_main_fd_handler_del (context_scim->selection_text_fd_read_handler);
1233 context_scim->selection_text_fd_read_handler = NULL;
1236 if (context_scim->selection_text) {
1237 free (context_scim->selection_text);
1238 context_scim->selection_text = NULL;
1241 if (context_scim->surrounding_text_fd_read_handler) {
1242 int fd = ecore_main_fd_handler_fd_get (context_scim->surrounding_text_fd_read_handler);
1244 ecore_main_fd_handler_del (context_scim->surrounding_text_fd_read_handler);
1245 context_scim->surrounding_text_fd_read_handler = NULL;
1248 if (context_scim->remote_surrounding_text_fd_read_handler) {
1249 int fd = ecore_main_fd_handler_fd_get (context_scim->remote_surrounding_text_fd_read_handler);
1251 ecore_main_fd_handler_del (context_scim->remote_surrounding_text_fd_read_handler);
1252 context_scim->remote_surrounding_text_fd_read_handler = NULL;
1255 if (context_scim->surrounding_text) {
1256 free (context_scim->surrounding_text);
1257 context_scim->surrounding_text = NULL;
1260 if (context_scim->remote_surrounding_text) {
1261 free (context_scim->remote_surrounding_text);
1262 context_scim->remote_surrounding_text = NULL;
1265 if (context_scim->id != _ic_list->id) {
1266 WSCContextISF * pre = _ic_list;
1267 WSCContextISF * cur = _ic_list->next;
1268 while (cur != NULL) {
1269 if (cur->id == context_scim->id) {
1270 pre->next = cur->next;
1277 _ic_list = _ic_list->next;
1280 if (context_scim->impl) {
1281 // Delete the instance.
1283 // In case the instance send out some helper event,
1284 // and this context has been focused out,
1285 // we need set the focused_ic to this context temporary.
1286 WSCContextISF* old_focused = _focused_ic;
1287 _focused_ic = context_scim;
1288 _focused_ic = old_focused;
1290 if (context_scim == _focused_ic) {
1291 g_info_manager->socket_turn_off ();
1292 g_info_manager->focus_out (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1295 g_info_manager->remove_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1297 if (context_scim->impl) {
1298 delete_ic_impl (context_scim->impl);
1299 context_scim->impl = 0;
1303 if (context_scim == _focused_ic)
1308 isf_wsc_context_focus_in (WSCContextISF *wsc_ctx)
1310 WSCContextISF* context_scim = wsc_ctx;
1316 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
1319 if (_focused_ic == context_scim) {
1320 SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
1323 SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
1324 isf_wsc_context_focus_out (_focused_ic);
1327 if (_change_keyboard_mode_by_focus_move) {
1328 //if h/w keyboard mode, keyboard mode will be changed to s/w mode when the entry get the focus.
1329 LOGD ("Keyboard mode is changed H/W->S/W because of focus_in.\n");
1330 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_HELPER_MODE);
1333 if (context_scim && context_scim->impl) {
1334 _focused_ic = context_scim;
1336 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1337 context_scim->impl->surrounding_text.clear ();
1338 context_scim->impl->preedit_string.clear ();
1339 context_scim->impl->preedit_attrlist.clear ();
1340 context_scim->impl->commit_string.clear ();
1341 context_scim->impl->preedit_caret = 0;
1342 context_scim->impl->preedit_started = false;
1344 g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1346 set_ic_capabilities (context_scim);
1348 //FIXME: modify the parameter ic->impl->si->get_factory_uuid ()
1349 g_info_manager->focus_in (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1350 if (context_scim->impl->is_on) {
1351 g_info_manager->socket_turn_on ();
1352 // _panel_client.hide_preedit_string (context_scim->id);
1353 // _panel_client.hide_aux_string (context_scim->id);
1354 // _panel_client.hide_lookup_table (context_scim->id);
1356 #if 0 //REMOVE_SCIM_LAUNCHER
1357 context_scim->impl->si->set_layout (wsc_context_input_panel_layout_get (wsc_ctx));
1358 context_scim->impl->si->set_prediction_allow (context_scim->impl->prediction_allow);
1360 if (context_scim->impl->imdata)
1361 context_scim->impl->si->set_imdata ((const char*)context_scim->impl->imdata, context_scim->impl->imdata_size);
1363 LOGD ("set autocapital type : %d\n", context_scim->impl->autocapital_type);
1364 g_info_manager->set_autocapital_type ((int)context_scim->impl->autocapital_type);
1366 g_info_manager->socket_turn_off ();
1369 g_info_manager->get_active_helper_option (WAYLAND_MODULE_CLIENT_ID, _active_helper_option);
1372 g_info_manager->remoteinput_callback_focus_in ();
1374 context_scim->impl->init_remote_entry_metadata = false;
1375 context_scim->impl->init_remote_surrounding_text = false;
1376 context_scim->impl->block_input_resource = false;
1377 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1380 LOGD ("ctx : %p\n", wsc_ctx);
1384 isf_wsc_context_focus_out (WSCContextISF *wsc_ctx)
1386 WSCContextISF* context_scim = wsc_ctx;
1389 if (!context_scim) return;
1391 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1393 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1394 LOGD ("ctx : %p\n", wsc_ctx);
1396 if (context_scim->impl->need_commit_preedit) {
1397 _hide_preedit_string (context_scim->id, false);
1399 wsc_context_commit_preedit_string (context_scim);
1400 g_info_manager->socket_reset_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1403 context_scim->impl->cursor_pos = -1;
1404 // if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1405 g_info_manager->focus_out (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1410 g_info_manager->remoteinput_callback_focus_out ();
1412 context_scim->impl->surrounding_text.clear ();
1413 context_scim->impl->preedit_string.clear ();
1414 context_scim->impl->preedit_attrlist.clear ();
1415 context_scim->impl->commit_string.clear ();
1416 context_scim->impl->preedit_caret = 0;
1417 context_scim->impl->preedit_started = false;
1418 context_scim->impl->need_commit_preedit = false;
1420 context_scim->impl->init_remote_entry_metadata = true;
1421 context_scim->impl->init_remote_surrounding_text = true;
1422 context_scim->impl->block_input_resource = true;
1423 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1425 _x_key_event_is_valid = false;
1429 isf_wsc_context_preedit_string_get (WSCContextISF *wsc_ctx, char** str, int *cursor_pos)
1431 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1433 WSCContextISF* context_scim = wsc_ctx;
1435 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1436 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1440 *str = strdup (mbs.c_str ());
1446 //*cursor_pos = context_scim->impl->preedit_caret;
1447 mbs = utf8_wcstombs (
1448 context_scim->impl->preedit_string.substr (0, context_scim->impl->preedit_caret));
1449 *cursor_pos = mbs.length ();
1461 isf_wsc_context_autocapital_type_set (WSCContextISF* wsc_ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1463 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1464 LOGD ("autocapital_type: %d", autocapital_type);
1465 WSCContextISF* context_scim = wsc_ctx;
1467 if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1468 context_scim->impl->autocapital_type = autocapital_type;
1469 LOGD ("ctx : %p. set autocapital type : %d\n", wsc_ctx, autocapital_type);
1471 if (context_scim == _focused_ic) {
1472 LOGD ("ctx : %p. set autocapital type : %d\n", wsc_ctx, autocapital_type);
1473 g_info_manager->set_autocapital_type ((int)autocapital_type);
1479 isf_wsc_context_bidi_direction_set (WSCContextISF* wsc_ctx, Ecore_IMF_BiDi_Direction direction)
1481 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1483 WSCContextISF *context_scim = wsc_ctx;
1485 if (context_scim && context_scim->impl) {
1486 if (context_scim->impl->bidi_direction != direction) {
1487 context_scim->impl->bidi_direction = direction;
1489 if (context_scim == _focused_ic) {
1490 LOGD ("ctx : %p, bidi direction : %#x\n", wsc_ctx, direction);
1491 panel_req_update_bidi_direction (context_scim, direction);
1498 isf_wsc_context_send_surrounding_text (WSCContextISF* wsc_ctx, const char *text, int cursor)
1500 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1502 WSCContextISF *context_scim = wsc_ctx;
1504 if (!context_scim || !context_scim->impl)
1507 char *conv_text = strdup (utf8_wcstombs (context_scim->impl->surrounding_text).c_str ());
1511 if (!context_scim->impl->init_remote_surrounding_text || strcmp (conv_text, text) != 0 || context_scim->impl->cursor_pos != cursor) {
1512 SECURE_LOGD("remote surrounding text : \"%s\"\n", text);
1513 context_scim->impl->surrounding_text = utf8_mbstowcs (String (text));
1514 context_scim->impl->cursor_pos = cursor;
1517 if (context_scim->input_panel_shown && context_scim->impl->input_resource != INPUT_RESOURCE_REMOTE) {
1519 if (context_scim->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD) {
1520 const unsigned char pw_char[5] = { 0xE2, 0x80, 0xA2, 0x2A, 0x00 }; // • U+2022 * U+002A
1521 if (_text.find_first_not_of((char *)pw_char) != String::npos) {
1522 g_info_manager->remoteinput_callback_surrounding_text (_text, context_scim->impl->cursor_pos);
1526 g_info_manager->remoteinput_callback_surrounding_text (empty, 0);
1530 g_info_manager->remoteinput_callback_surrounding_text (_text, context_scim->impl->cursor_pos);
1532 context_scim->impl->init_remote_surrounding_text = true;
1536 context_scim->impl->init_remote_surrounding_text = true;
1543 isf_wsc_context_send_entry_metadata (WSCContextISF* wsc_ctx, Ecore_IMF_Input_Hints hint,
1544 Ecore_IMF_Input_Panel_Layout layout, int variation,
1545 Ecore_IMF_Autocapital_Type type, int return_key_disabled)
1547 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1549 WSCContextISF *context_scim = wsc_ctx;
1551 if (context_scim && context_scim->impl) {
1552 if (!context_scim->impl->init_remote_entry_metadata || (context_scim->impl->input_hint != hint || context_scim->impl->panel_layout != layout ||
1553 context_scim->impl->variation != variation || context_scim->impl->autocapital_type != type ||
1554 context_scim->impl->return_key_disabled != return_key_disabled)) {
1555 if (context_scim->impl->panel_layout != layout || context_scim->impl->variation != variation) {
1556 if (context_scim->impl->input_resource == INPUT_RESOURCE_REMOTE)
1557 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1560 context_scim->impl->input_hint = hint;
1561 context_scim->impl->panel_layout = layout;
1562 context_scim->impl->variation = variation;
1563 context_scim->impl->autocapital_type = type;
1564 context_scim->impl->return_key_disabled = return_key_disabled;
1567 g_info_manager->remoteinput_callback_entry_metadata (context_scim->impl->input_hint, context_scim->impl->panel_layout,
1568 context_scim->impl->variation, context_scim->impl->autocapital_type, context_scim->impl->return_key_disabled);
1570 context_scim->impl->init_remote_entry_metadata = true;
1573 remote_surrounding_get (wsc_ctx);
1578 #if ENABLE_GRAB_KEYBOARD
1580 bool is_number_key (const char *str)
1582 if (!str) return false;
1584 int result = atoi (str);
1587 if (!strcmp (str, "0"))
1597 isf_wsc_context_filter_key_event (WSCContextISF* wsc_ctx,
1599 uint32_t timestamp, uint32_t keycode, uint32_t symcode,
1601 enum wl_keyboard_key_state state)
1604 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1607 if (!wsc_ctx) return;
1609 KeyEvent key(symcode, wsc_ctx->modifiers);
1611 bool ignore_key = filter_keys (keyname, SCIM_CONFIG_HOTKEYS_FRONTEND_IGNORE_KEY);
1613 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
1614 key.mask = SCIM_KEY_ReleaseMask;
1615 } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1617 /* Hardware input detect code */
1618 if (get_keyboard_mode () == TOOLBAR_HELPER_MODE &&
1620 _support_hw_keyboard_mode &&
1621 strncmp (keyname, "XF86", 4)) {
1622 bool hw_key_detect = false;
1625 if (strcmp (keyname, "Down") &&
1626 strcmp (keyname, "KP_Down") &&
1627 strcmp (keyname, "Up") &&
1628 strcmp (keyname, "KP_Up") &&
1629 strcmp (keyname, "Right") &&
1630 strcmp (keyname, "KP_Right") &&
1631 strcmp (keyname, "Left") &&
1632 strcmp (keyname, "KP_Left") &&
1633 strcmp (keyname, "Return") &&
1634 strcmp (keyname, "Pause") &&
1635 strcmp (keyname, "NoSymbol") &&
1636 !is_number_key (keyname)) {
1637 hw_key_detect = true;
1640 if (key.code != 0x1008ff26 && key.code != 0xFF69) {
1641 /* XF86back, Cancel (Power + Volume down) key */
1642 hw_key_detect = true;
1646 if (hw_key_detect) {
1647 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_KEYBOARD_MODE);
1648 ISF_SAVE_LOG ("Changed keyboard mode from S/W to H/W (code: %x, name: %s)\n", key.code, keyname);
1649 LOGD ("Hardware keyboard mode, active helper option: %d\n", _active_helper_option);
1656 if (!_focused_ic || !_focused_ic->impl || !_focused_ic->impl->is_on) {
1659 static uint32 _serial = 0;
1660 g_info_manager->process_key_event (key, ++_serial);
1663 send_wl_key_event (wsc_ctx, key, false);
1668 isf_wsc_context_filter_key_event (WSCContextISF* wsc_ctx,
1670 uint32_t timestamp, const char *keysym,
1671 bool press, uint32_t modifiers,
1672 const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
1674 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1677 if (!wsc_ctx) return;
1680 LOGD("key is NULL\n");
1684 String _key(keysym);
1687 if (!scim_string_to_key (key, _key)) {
1688 xkb_keysym_t code = xkb_keysym_from_name(keysym, XKB_KEYSYM_NO_FLAGS);
1689 if (code == XKB_KEY_NoSymbol) {
1690 code = xkb_keysym_from_name(keysym, XKB_KEYSYM_CASE_INSENSITIVE);
1694 scim_set_device_info (key, dev_name ? dev_name : "", dev_class, dev_subclass);
1696 bool ignore_key = filter_keys (keysym, SCIM_CONFIG_HOTKEYS_FRONTEND_IGNORE_KEY);
1698 if (modifiers & MOD_SHIFT_MASK)
1699 key.mask |= SCIM_KEY_ShiftMask;
1700 if (modifiers & MOD_ALT_MASK)
1701 key.mask |= SCIM_KEY_AltMask;
1702 if (modifiers & MOD_CONTROL_MASK)
1703 key.mask |= SCIM_KEY_ControlMask;
1705 if (modifiers & MOD_CAPS_MASK)
1706 key.mask |= SCIM_KEY_CapsLockMask;
1707 if (modifiers & MOD_NUM_MASK)
1708 key.mask |= SCIM_KEY_NumLockMask;
1711 key.mask |= SCIM_KEY_ReleaseMask;
1714 /* Hardware input detect code */
1715 if (get_keyboard_mode () == TOOLBAR_HELPER_MODE &&
1717 _support_hw_keyboard_mode &&
1718 strncmp (keysym, "XF86", 4)) {
1719 bool hw_key_detect = false;
1722 if (strcmp (keysym, "Down") &&
1723 strcmp (keysym, "KP_Down") &&
1724 strcmp (keysym, "Up") &&
1725 strcmp (keysym, "KP_Up") &&
1726 strcmp (keysym, "Right") &&
1727 strcmp (keysym, "KP_Right") &&
1728 strcmp (keysym, "Left") &&
1729 strcmp (keysym, "KP_Left") &&
1730 strcmp (keysym, "Return") &&
1731 strcmp (keysym, "Pause") &&
1732 strcmp (keysym, "NoSymbol") &&
1733 key.dev_subclass != ECORE_DEVICE_SUBCLASS_REMOCON) {
1734 hw_key_detect = true;
1737 if (key.code != 0x1008ff26 && key.code != 0xFF69) {
1738 /* XF86back, Cancel (Power + Volume down) key */
1739 hw_key_detect = true;
1743 if (hw_key_detect) {
1744 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_KEYBOARD_MODE);
1745 ISF_SAVE_LOG ("Changed keyboard mode from S/W to H/W (code: %x, key : %s)\n", key.code, keysym);
1746 LOGD ("Hardware keyboard mode, active helper option: %d\n", _active_helper_option);
1753 if (!_focused_ic || !_focused_ic->impl || !_focused_ic->impl->is_on) {
1755 } else if (g_info_manager->process_key_event (key, serial)){
1760 if (!instance.null ())
1761 instance->process_key_event_done (WAYLAND_MODULE_CLIENT_ID, wsc_ctx->id, key, EINA_FALSE, serial);
1766 wsc_commit_preedit (WSCContextISF* wsc_ctx)
1769 char* surrounding_text;
1771 if (!wsc_ctx || !wsc_ctx->preedit_str ||
1772 strlen (wsc_ctx->preedit_str) == 0)
1775 wl_input_method_context_cursor_position (wsc_ctx->im_ctx,
1778 if (strlen (wsc_ctx->preedit_str) > MAX_PREEDIT_BUFSIZE) {
1779 char str_buffer[MAX_PREEDIT_BUFSIZE];
1781 memcpy (str_buffer, wsc_ctx->preedit_str, MAX_PREEDIT_BUFSIZE - 1);
1782 str_buffer[MAX_PREEDIT_BUFSIZE - 1] = '\0';
1783 char *old_preedit_str = wsc_ctx->preedit_str;
1784 wsc_ctx->preedit_str = (char*)realloc (wsc_ctx->preedit_str, sizeof(char) * MAX_PREEDIT_BUFSIZE);
1785 if (wsc_ctx->preedit_str) {
1786 memcpy (wsc_ctx->preedit_str, str_buffer, strlen(str_buffer));
1787 wsc_ctx->preedit_str[MAX_PREEDIT_BUFSIZE - 1] = '\0';
1789 free (old_preedit_str);
1790 LOGE ("realloc failed");
1795 wl_input_method_context_commit_string (wsc_ctx->im_ctx,
1797 wsc_ctx->preedit_str);
1799 if (wsc_ctx->surrounding_text) {
1800 surrounding_text = insert_text (wsc_ctx->surrounding_text,
1801 wsc_ctx->surrounding_cursor,
1802 wsc_ctx->preedit_str);
1804 free (wsc_ctx->surrounding_text);
1805 wsc_ctx->surrounding_text = surrounding_text;
1806 wsc_ctx->surrounding_cursor += strlen (wsc_ctx->preedit_str);
1807 LOGD ("wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
1809 wsc_ctx->surrounding_text = strdup (wsc_ctx->preedit_str);
1810 wsc_ctx->surrounding_cursor = strlen (wsc_ctx->preedit_str);
1811 LOGD ("wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
1814 if (wsc_ctx->preedit_str)
1815 free (wsc_ctx->preedit_str);
1817 wsc_ctx->preedit_str = strdup ("");
1821 wsc_send_preedit_style (WSCContextISF* wsc_ctx)
1825 if (!wsc_ctx) return;
1826 if (wsc_ctx->impl && wsc_ctx->impl->is_on) {
1827 String mbs = utf8_wcstombs (wsc_ctx->impl->preedit_string);
1829 if (!wsc_ctx->impl->preedit_attrlist.empty ()) {
1830 if (mbs.length ()) {
1831 uint32_t preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT;
1832 int start_index, end_index;
1833 int wlen = wsc_ctx->impl->preedit_string.length ();
1834 AttributeList::const_iterator i;
1835 bool *attrs_flag = new bool [mbs.length ()];
1837 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1838 for (i = wsc_ctx->impl->preedit_attrlist.begin ();
1839 i != wsc_ctx->impl->preedit_attrlist.end (); ++i) {
1840 start_index = i->get_start ();
1841 end_index = i->get_end ();
1842 if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1843 start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1844 end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1845 if (i->get_type () == SCIM_ATTR_DECORATE) {
1846 switch (i->get_value ())
1848 case SCIM_ATTR_DECORATE_UNDERLINE:
1849 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE;
1851 case SCIM_ATTR_DECORATE_REVERSE:
1852 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION;
1854 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1855 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT;
1857 case SCIM_ATTR_DECORATE_BGCOLOR1:
1858 case SCIM_ATTR_DECORATE_BGCOLOR2:
1859 case SCIM_ATTR_DECORATE_BGCOLOR3:
1860 case SCIM_ATTR_DECORATE_BGCOLOR4:
1862 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT;
1867 wl_input_method_context_preedit_styling (wsc_ctx->im_ctx,
1871 switch (i->get_value ())
1873 case SCIM_ATTR_DECORATE_UNDERLINE:
1874 case SCIM_ATTR_DECORATE_REVERSE:
1875 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1876 case SCIM_ATTR_DECORATE_BGCOLOR1:
1877 case SCIM_ATTR_DECORATE_BGCOLOR2:
1878 case SCIM_ATTR_DECORATE_BGCOLOR3:
1879 case SCIM_ATTR_DECORATE_BGCOLOR4:
1880 // Record which character has attribute.
1881 for (int pos = start_index; pos < end_index; ++pos)
1882 attrs_flag [pos] = 1;
1887 } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1888 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1889 } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1890 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1894 // Add underline for all characters which don't have attribute.
1895 for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1896 if (!attrs_flag [pos]) {
1897 int begin_pos = pos;
1898 while (pos < mbs.length () && !attrs_flag [pos])
1900 // use REVERSE style as default
1901 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE;
1902 start_index = begin_pos;
1905 wl_input_method_context_preedit_styling (wsc_ctx->im_ctx,
1911 delete [] attrs_flag;
1916 if (!wsc_ctx->impl->preedit_attrlist.empty ())
1917 wsc_ctx->impl->preedit_attrlist.clear ();
1922 wsc_send_preedit (WSCContextISF* wsc_ctx, int32_t cursor)
1926 if (!wsc_ctx) return;
1928 uint32_t index = strlen (wsc_ctx->preedit_str);
1930 wsc_send_preedit_style (wsc_ctx);
1935 /* Note : Since the current wayland_immodule implementation does not call
1936 * PREEDIT_CHANGED callback even when preedit_cursor gets updated, for now
1937 * we must update preedit_string also whenever preedit_cursor is updated.
1938 * So the below 2 lines cannot be called separately. */
1939 wl_input_method_context_preedit_cursor (wsc_ctx->im_ctx, index);
1940 wl_input_method_context_preedit_string (wsc_ctx->im_ctx,
1942 wsc_ctx->preedit_str,
1943 utf8_wcstombs (wsc_ctx->impl->commit_string).c_str ());
1946 bool wsc_context_surrounding_get (WSCContextISF *wsc_ctx, char **text, int *cursor_pos)
1952 if (wsc_ctx->surrounding_text)
1953 *text = strdup (wsc_ctx->surrounding_text);
1955 *text = strdup ("");
1959 *cursor_pos = wsc_ctx->surrounding_cursor;
1965 remote_surrounding_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
1966 if (fd_handler == NULL || data == NULL)
1967 return ECORE_CALLBACK_RENEW;
1969 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
1971 int fd = ecore_main_fd_handler_fd_get (fd_handler);
1973 int len = read (fd, buff, sizeof (buff) - 1);
1976 SECURE_LOGD ("remote_surrounding_text : %s, surrounding_cursor : %d\n", wsc_ctx->remote_surrounding_text, wsc_ctx->surrounding_cursor);
1977 isf_wsc_context_send_surrounding_text (wsc_ctx, wsc_ctx->remote_surrounding_text ? wsc_ctx->remote_surrounding_text : "", wsc_ctx->surrounding_cursor);
1978 } else if (len < 0) {
1982 if (wsc_ctx->remote_surrounding_text == NULL) {
1983 if (len >= (int)sizeof(int)) {
1984 /* Add one byte for terminating NULL character and subtract <int> byte for cursor position */
1985 wsc_ctx->remote_surrounding_text = (char*)malloc (len + 1 - sizeof(int));
1986 if (wsc_ctx->remote_surrounding_text) {
1987 memcpy(&(wsc_ctx->surrounding_cursor), buff, sizeof(int));
1988 memcpy (wsc_ctx->remote_surrounding_text, buff + sizeof(int), len - sizeof(int));
1989 wsc_ctx->remote_surrounding_text[len - sizeof(int)] = '\0';
1990 return ECORE_CALLBACK_RENEW;
1992 LOGE ("malloc failed");
1996 int old_len = strlen (wsc_ctx->remote_surrounding_text);
1997 void * _new = realloc (wsc_ctx->remote_surrounding_text, len + old_len + 1);
1999 wsc_ctx->remote_surrounding_text = (char*)_new;
2000 memcpy (wsc_ctx->remote_surrounding_text + old_len, buff, len);
2001 wsc_ctx->remote_surrounding_text[old_len + len] = '\0';
2002 return ECORE_CALLBACK_RENEW;
2004 LOGE ("realloc failed");
2009 if (wsc_ctx->remote_surrounding_text_fd_read_handler) {
2011 ecore_main_fd_handler_del (wsc_ctx->remote_surrounding_text_fd_read_handler);
2012 wsc_ctx->remote_surrounding_text_fd_read_handler = NULL;
2015 if (wsc_ctx->remote_surrounding_text) {
2016 free (wsc_ctx->remote_surrounding_text);
2017 wsc_ctx->remote_surrounding_text = NULL;
2020 return ECORE_CALLBACK_CANCEL;
2024 remote_surrounding_get (WSCContextISF *wsc_ctx)
2026 if (wsc_ctx && wsc_ctx->im_ctx && wsc_ctx->remote_surrounding_text_fd_read_handler)
2030 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) == -1) {
2031 LOGW ("create pipe failed");
2034 LOGD("%d,%d", filedes[0], filedes[1]);
2035 if (wsc_ctx && wsc_ctx->im_ctx) {
2036 wl_input_method_context_get_surrounding_text (wsc_ctx->im_ctx, UINT_MAX, UINT_MAX, filedes[1]);
2041 if (wsc_ctx && wsc_ctx->im_ctx) {
2042 if (wsc_ctx->remote_surrounding_text) {
2043 free (wsc_ctx->remote_surrounding_text);
2044 wsc_ctx->remote_surrounding_text = NULL;
2047 wsc_ctx->remote_surrounding_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, remote_surrounding_text_fd_read_func, wsc_ctx, NULL, NULL);
2052 Ecore_IMF_Input_Panel_Layout wsc_context_input_panel_layout_get (WSCContextISF *wsc_ctx)
2054 Ecore_IMF_Input_Panel_Layout layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2059 switch (wsc_ctx->content_purpose) {
2060 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
2061 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED:
2062 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL:
2063 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL:
2064 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
2066 case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
2067 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER;
2069 case WL_TEXT_INPUT_CONTENT_PURPOSE_DATE:
2070 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH;
2072 case WL_TEXT_INPUT_CONTENT_PURPOSE_TIME:
2073 case WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME:
2074 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME;
2076 case WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE:
2077 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
2079 case WL_TEXT_INPUT_CONTENT_PURPOSE_URL:
2080 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
2082 case WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL:
2083 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
2085 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
2086 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS:
2087 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
2089 case WL_TEXT_INPUT_CONTENT_PURPOSE_HEX:
2090 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_HEX;
2092 case WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL:
2093 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL;
2095 case WL_TEXT_INPUT_CONTENT_PURPOSE_IP:
2096 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_IP;
2098 case WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON:
2099 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON;
2101 case WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE:
2102 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE;
2104 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
2105 case WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME:
2106 case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
2108 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2115 int wsc_context_input_panel_layout_variation_get (WSCContextISF *wsc_ctx)
2117 int layout_variation = 0;
2120 return layout_variation;
2122 switch (wsc_ctx->content_purpose) {
2123 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
2124 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_NORMAL;
2126 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED:
2127 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED;
2129 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL:
2130 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL;
2132 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL:
2133 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL;
2135 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
2136 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NORMAL;
2138 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS:
2139 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY;
2141 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
2142 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_NORMAL;
2144 case WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME:
2145 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME;
2147 case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
2148 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME;
2151 layout_variation = 0;
2155 return layout_variation;
2158 Ecore_IMF_Autocapital_Type wsc_context_autocapital_type_get (WSCContextISF *wsc_ctx)
2160 Ecore_IMF_Autocapital_Type autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
2163 return autocapital_type;
2165 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION)
2166 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE;
2167 else if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION)
2168 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_WORD;
2169 else if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
2170 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER;
2172 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
2174 return autocapital_type;
2177 bool wsc_context_input_panel_caps_lock_mode_get (WSCContextISF *wsc_ctx)
2182 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
2188 Ecore_IMF_Input_Panel_Lang wsc_context_input_panel_language_get (WSCContextISF *wsc_ctx)
2190 Ecore_IMF_Input_Panel_Lang language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
2195 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_LATIN)
2196 language = ECORE_IMF_INPUT_PANEL_LANG_ALPHABET;
2198 language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
2203 bool wsc_context_input_panel_password_mode_get (WSCContextISF *wsc_ctx)
2205 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_PASSWORD)
2208 if (wsc_context_input_panel_layout_get (wsc_ctx) == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
2214 Ecore_IMF_Input_Hints wsc_context_input_hint_get (WSCContextISF *wsc_ctx)
2216 int input_hint = ECORE_IMF_INPUT_HINT_NONE;
2219 return (Ecore_IMF_Input_Hints)input_hint;
2221 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA)
2222 input_hint |= ECORE_IMF_INPUT_HINT_SENSITIVE_DATA;
2224 input_hint &= ~ECORE_IMF_INPUT_HINT_SENSITIVE_DATA;
2226 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION)
2227 input_hint |= ECORE_IMF_INPUT_HINT_AUTO_COMPLETE;
2229 input_hint &= ~ECORE_IMF_INPUT_HINT_AUTO_COMPLETE;
2231 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_MULTILINE)
2232 input_hint |= ECORE_IMF_INPUT_HINT_MULTILINE;
2234 input_hint &= ~ECORE_IMF_INPUT_HINT_MULTILINE;
2236 return (Ecore_IMF_Input_Hints)input_hint;
2239 Eina_Bool wsc_context_prediction_allow_get (WSCContextISF *wsc_ctx)
2246 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION)
2252 Ecore_IMF_BiDi_Direction wsc_context_bidi_direction_get (WSCContextISF *wsc_ctx)
2254 return (Ecore_IMF_BiDi_Direction)wsc_ctx->bidi_direction;
2257 void wsc_context_delete_surrounding (WSCContextISF *wsc_ctx, int offset, int len)
2259 LOGD ("offset = %d, len = %d", offset, len);
2264 wl_input_method_context_delete_surrounding_text (wsc_ctx->im_ctx, offset, len);
2267 void wsc_context_set_selection (WSCContextISF *wsc_ctx, int start, int end)
2274 wl_input_method_context_selection_region (wsc_ctx->im_ctx, wsc_ctx->serial, start, end);
2277 void wsc_context_commit_string (WSCContextISF *wsc_ctx, const char *str)
2284 if (wsc_ctx->preedit_str) {
2285 free (wsc_ctx->preedit_str);
2286 wsc_ctx->preedit_str = NULL;
2289 wsc_ctx->preedit_str = strdup (str);
2290 wsc_commit_preedit (wsc_ctx);
2293 void wsc_context_commit_preedit_string (WSCContextISF *wsc_ctx)
2296 char* preedit_str = NULL;
2302 isf_wsc_context_preedit_string_get (wsc_ctx, &preedit_str, &cursor_pos);
2304 if (wsc_ctx->preedit_str) {
2305 free (wsc_ctx->preedit_str);
2306 wsc_ctx->preedit_str = NULL;
2309 wsc_ctx->preedit_str = preedit_str;
2310 wsc_commit_preedit (wsc_ctx);
2313 void wsc_context_send_preedit_string (WSCContextISF *wsc_ctx)
2316 char* preedit_str = NULL;
2322 isf_wsc_context_preedit_string_get (wsc_ctx, &preedit_str, &cursor_pos);
2324 if (wsc_ctx->preedit_str) {
2325 free (wsc_ctx->preedit_str);
2326 wsc_ctx->preedit_str = NULL;
2329 wsc_ctx->preedit_str = preedit_str;
2330 wsc_send_preedit (wsc_ctx, cursor_pos);
2333 void wsc_context_send_key (WSCContextISF *wsc_ctx, uint32_t keysym, uint32_t modifiers, uint32_t time, bool press)
2337 if (!wsc_ctx || !wsc_ctx->im_ctx)
2340 wl_input_method_context_keysym (wsc_ctx->im_ctx, wsc_ctx->serial, time,
2341 keysym, press ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, modifiers);
2345 set_ic_capabilities (WSCContextISF *ic)
2347 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2350 if (ic && ic->impl) {
2351 unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2353 if (!_on_the_spot || !ic->impl->use_preedit)
2354 cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2356 //FIXME:add this interface
2357 //_info_manager->update_client_capabilities (cap);
2364 /* Panel Requestion functions. */
2366 panel_req_show_help (WSCContextISF *ic)
2368 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2372 help = String (_("Smart Common Input Method platform ")) +
2373 String (SCIM_VERSION) +
2374 String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2376 if (ic && ic->impl && ic->impl->si) {
2377 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2379 help += utf8_wcstombs (sf->get_name ());
2380 help += String (_(":\n\n"));
2382 help += utf8_wcstombs (sf->get_help ());
2383 help += String (_("\n\n"));
2385 help += utf8_wcstombs (sf->get_credits ());
2388 g_info_manager->socket_show_help (help);
2391 g_info_manager->remoteinput_callback_focus_out ();
2392 LOGD("Remote control button click");
2397 panel_req_update_bidi_direction (WSCContextISF *ic, int direction)
2399 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2402 g_info_manager->update_ise_bidi_direction (WAYLAND_MODULE_CLIENT_ID, direction);
2406 filter_keys (const char *keyname, const char *config_path)
2408 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2414 std::vector <String> keys;
2415 scim_split_string_list (keys, _config->read (String (config_path), String ("")), ',');
2417 for (unsigned int i = 0; i < keys.size (); ++i) {
2418 if (!strcmp (keyname, keys [i].c_str ())) {
2427 panel_initialize (void)
2429 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2431 String display_name;
2433 const char *p = getenv ("DISPLAY");
2434 if (p) display_name = String (p);
2436 g_info_manager->add_client (WAYLAND_MODULE_CLIENT_ID, 2, FRONTEND_CLIENT);
2437 _panel_client_id = WAYLAND_MODULE_CLIENT_ID;
2438 g_info_manager->register_panel_client (_panel_client_id, _panel_client_id);
2439 WSCContextISF* context_scim = _ic_list;
2441 while (context_scim != NULL) {
2442 //FIXME:modify the parameter
2443 g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
2445 context_scim = context_scim->next;
2454 panel_finalize (void)
2456 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2458 g_info_manager->del_client (WAYLAND_MODULE_CLIENT_ID);
2462 panel_slot_update_preedit_caret (int context, int caret)
2465 WSCContextISF* ic = find_ic (context);
2466 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
2468 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
2469 ic->impl->preedit_caret = caret;
2470 if (ic->impl->use_preedit) {
2471 if (!ic->impl->preedit_started) {
2472 if (check_valid_ic (ic))
2473 ic->impl->preedit_started = true;
2475 wsc_send_preedit (ic, caret);
2477 g_info_manager->socket_update_preedit_caret (caret);
2483 panel_slot_process_key_event (int context, const KeyEvent &key)
2485 WSCContextISF* ic = find_ic (context);
2486 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2488 if (!(ic && ic->impl))
2491 if ((_focused_ic != NULL) && (_focused_ic != ic))
2494 send_wl_key_event (ic, key, false);
2498 panel_slot_commit_string (int context, const WideString &wstr, bool remote_mode)
2501 WSCContextISF* ic = find_ic (context);
2502 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2504 if (ic && ic->impl) {
2505 if (_focused_ic != ic)
2509 if (ic->impl->block_input_resource) {
2510 LOGW ("block remote input\n");
2513 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2515 if (ic->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_URL)
2516 wsc_context_delete_surrounding (ic, INT_MIN/2, INT_MAX);
2518 wsc_context_commit_string (ic, utf8_wcstombs (wstr).c_str ());
2519 ic->impl->need_commit_preedit = false;
2520 ic->impl->preedit_string.clear ();
2522 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
2523 wsc_context_commit_string (ic, utf8_wcstombs (wstr).c_str ());
2529 panel_slot_forward_key_event (int context, const KeyEvent &key, bool remote_mode)
2532 WSCContextISF* ic = find_ic (context);
2533 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2535 if (!(ic && ic->impl))
2538 if ((_focused_ic != NULL) && (_focused_ic != ic))
2542 if (ic->impl->block_input_resource) {
2543 LOGW ("block remote input\n");
2546 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2548 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
2551 if (key.get_key_string ().length () >= 116)
2554 send_wl_key_event (ic, key, true);
2558 panel_slot_update_preedit_string (int context, const WideString str, const WideString commit, const AttributeList &attrs, int caret, bool remote_mode)
2561 WSCContextISF* ic = find_ic (context);
2562 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
2564 if (ic && ic->impl && _focused_ic == ic) {
2566 if (ic->impl->block_input_resource) {
2567 LOGW ("block remote input\n");
2570 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2573 if (!ic->impl->is_on)
2574 ic->impl->is_on = true;
2576 if (ic->impl->preedit_string != str || str.length ()) {
2577 ic->impl->preedit_string = str;
2578 ic->impl->preedit_attrlist = attrs;
2579 ic->impl->commit_string = commit;
2581 if (ic->impl->use_preedit) {
2582 if (!ic->impl->preedit_started) {
2583 if (!check_valid_ic (ic))
2586 ic->impl->preedit_started = true;
2587 ic->impl->need_commit_preedit = true;
2589 if (caret >= 0 && caret <= (int)str.length ())
2590 ic->impl->preedit_caret = caret;
2592 ic->impl->preedit_caret = str.length ();
2594 if (ic->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_URL)
2595 wsc_context_delete_surrounding (ic, INT_MIN/2, INT_MAX);
2597 wsc_context_send_preedit_string (ic);
2599 String _str = utf8_wcstombs (str);
2600 g_info_manager->socket_update_preedit_string (_str, attrs, (uint32)caret);
2607 _show_preedit_string (int context)
2610 WSCContextISF* ic = find_ic (context);
2611 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << "\n";
2613 if (ic && ic->impl && _focused_ic == ic) {
2614 if (!ic->impl->is_on)
2615 ic->impl->is_on = true;
2617 if (ic->impl->use_preedit) {
2618 if (!ic->impl->preedit_started) {
2619 if (check_valid_ic (ic)) {
2620 ic->impl->preedit_started = true;
2621 ic->impl->need_commit_preedit = true;
2625 g_info_manager->socket_show_preedit_string ();
2631 _hide_preedit_string (int context, bool update_preedit)
2633 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2635 WSCContextISF* ic = find_ic (context);
2637 if (ic && ic->impl && _focused_ic == ic) {
2638 if (!ic->impl->is_on)
2639 ic->impl->is_on = true;
2642 if (ic->impl->preedit_string.length ()) {
2643 ic->impl->preedit_string = WideString ();
2644 ic->impl->preedit_caret = 0;
2645 ic->impl->preedit_attrlist.clear ();
2648 ic->impl->commit_string = WideString ();
2649 if (ic->impl->use_preedit) {
2650 if (update_preedit && emit) {
2651 if (!check_valid_ic (ic))
2654 if (ic->impl->preedit_started) {
2655 if (check_valid_ic (ic)) {
2656 ic->impl->preedit_started = false;
2657 ic->impl->need_commit_preedit = false;
2660 wsc_context_send_preedit_string (ic);
2662 g_info_manager->socket_hide_preedit_string ();
2670 LOGD ("Initializing Wayland ISF IMModule...\n");
2672 // Get system language.
2673 _language = scim_get_locale_language (scim_get_current_locale ());
2675 panel_initialize ();
2681 LOGD ("Finalizing Ecore ISF IMModule...\n");
2683 SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2684 while (_used_ic_impl_list) {
2685 // In case in "shared input method" mode,
2686 // all contexts share only one instance,
2687 // so we need point the reference pointer correctly before finalizing.
2689 if (_used_ic_impl_list->si) {
2690 _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2693 if (_used_ic_impl_list->parent && _used_ic_impl_list->parent->ctx) {
2694 isf_wsc_context_del (_used_ic_impl_list->parent);
2698 delete_all_ic_impl ();
2700 SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2705 _scim_initialized = false;
2709 static uint32_t _keyname_to_keysym (uint32_t keyname, uint32_t *modifiers)
2714 if ((keyname >= '0' && keyname <= '9') ||
2715 (keyname >= 'a' && keyname <= 'z')) {
2717 } else if (keyname >= 'A' && keyname <= 'Z') {
2718 *modifiers |= MOD_SHIFT_MASK;
2719 return keyname + 32;
2724 *modifiers |= MOD_SHIFT_MASK;
2727 *modifiers |= MOD_SHIFT_MASK;
2730 *modifiers |= MOD_SHIFT_MASK;
2733 *modifiers |= MOD_SHIFT_MASK;
2736 *modifiers |= MOD_SHIFT_MASK;
2739 *modifiers |= MOD_SHIFT_MASK;
2742 *modifiers |= MOD_SHIFT_MASK;
2745 *modifiers |= MOD_SHIFT_MASK;
2748 *modifiers |= MOD_SHIFT_MASK;
2751 *modifiers |= MOD_SHIFT_MASK;
2754 *modifiers |= MOD_SHIFT_MASK;
2757 *modifiers |= MOD_SHIFT_MASK;
2760 *modifiers |= MOD_SHIFT_MASK;
2763 *modifiers |= MOD_SHIFT_MASK;
2766 *modifiers |= MOD_SHIFT_MASK;
2769 *modifiers |= MOD_SHIFT_MASK;
2772 *modifiers |= MOD_SHIFT_MASK;
2775 *modifiers |= MOD_SHIFT_MASK;
2778 *modifiers |= MOD_SHIFT_MASK;
2781 *modifiers |= MOD_SHIFT_MASK;
2788 static void send_wl_key_event (WSCContextISF *ic, const KeyEvent &key, bool fake)
2790 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2793 uint32_t modifiers = 0;
2798 modifiers |= MOD_Mod5_MASK;
2801 if (key.is_shift_down ())
2802 modifiers |= MOD_SHIFT_MASK;
2803 if (key.is_alt_down ())
2804 modifiers |= MOD_ALT_MASK;
2805 if (key.is_control_down ())
2806 modifiers |= MOD_CONTROL_MASK;
2808 _keyname_to_keysym (key.code, &modifiers);
2811 wsc_context_send_key (ic, key.code, modifiers, time, key.is_key_press ());
2815 reload_config_callback (const ConfigPointer &config)
2817 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2819 //FIXME:_frontend_hotkey_matcher and _imengine_hotkey_matcher should be added
2820 //_frontend_hotkey_matcher.load_hotkeys (config);
2821 //_imengine_hotkey_matcher.load_hotkeys (config);
2824 scim_string_to_key (key,
2825 config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
2826 String ("Shift+Control+Alt+Lock")));
2828 _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
2829 _valid_key_mask |= SCIM_KEY_ReleaseMask;
2830 // Special treatment for two backslash keys on jp106 keyboard.
2831 _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
2833 _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
2834 //_shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
2835 _change_keyboard_mode_by_focus_move = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_CHANGE_KEYBOARD_MODE_BY_FOCUS_MOVE), _change_keyboard_mode_by_focus_move);
2836 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
2838 // Get keyboard layout setting
2839 // Flush the global config first, in order to load the new configs from disk.
2840 scim_global_config_flush ();
2842 _keyboard_layout = scim_get_default_keyboard_layout ();
2845 class WaylandPanelAgent: public PanelAgentBase
2847 Connection _config_connection;
2850 WaylandPanelAgent ()
2851 : PanelAgentBase ("wayland") {
2853 ~WaylandPanelAgent () {
2856 bool initialize (InfoManager* info_manager, const String& display, bool resident) {
2858 g_info_manager = info_manager;
2859 isf_wsc_context_init ();
2861 if (!_wsc_setup (&_wsc)) {
2865 _config_connection = _config->signal_connect_reload (slot (reload_config_callback));
2867 _wl_im_ctx = new _wl_im;
2869 LOGW ("Can not create wl_im_ctx\n");
2875 bool valid (void) const {
2880 if (_need_wl_im_init)
2888 _config_connection.disconnect ();
2889 isf_wsc_context_shutdown ();
2894 exit (int id, uint32 contextid) {
2895 LOGD ("client id:%d", id);
2900 update_preedit_caret (int id, uint32 context_id, uint32 caret) {
2901 LOGD ("client id:%d", id);
2902 panel_slot_update_preedit_caret (context_id, caret);
2906 socket_helper_key_event (int id, uint32 context_id, int cmd , KeyEvent& key) {
2907 LOGD ("client id:%d", id);
2909 if (cmd == SCIM_TRANS_CMD_PROCESS_KEY_EVENT)
2910 panel_slot_process_key_event (context_id, key);
2912 panel_slot_forward_key_event (context_id, key, false);
2916 commit_string (int id, uint32 context_id, const WideString& wstr) {
2917 LOGD ("client id:%d", id);
2918 panel_slot_commit_string (context_id, wstr, false);
2922 forward_key_event (int id, uint32 context_id, const KeyEvent &key) {
2923 LOGD ("client id:%d", id);
2924 panel_slot_forward_key_event (context_id, key, false);
2928 remote_commit_string (int id, uint32 context_id, const WideString& wstr) {
2929 LOGD ("client id:%d", id);
2930 panel_slot_commit_string (context_id, wstr, true);
2934 remote_update_preedit_string (int id, uint32 context_id, const WideString str, const WideString commit, const AttributeList &attrs, uint32 caret) {
2935 LOGD ("client id:%d", id);
2936 panel_slot_update_preedit_string (context_id, str, commit, attrs, caret, true);
2940 remote_forward_key_event (int id, uint32 context_id, const KeyEvent &key) {
2941 LOGD ("client id:%d", id);
2942 panel_slot_forward_key_event (context_id, key, true);
2946 remote_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len) {
2947 LOGD ("client id:%d", id);
2950 if (_focused_ic->impl->block_input_resource)
2953 check_input_resource (_focused_ic, INPUT_RESOURCE_REMOTE);
2954 wsc_context_delete_surrounding (_focused_ic, offset, len);
2959 update_ise_input_context (int client, uint32 context, uint32 type, uint32 value) {
2960 if (!_focused_ic || !_focused_ic->im_ctx)
2963 wl_input_method_context_input_panel_event (_focused_ic->im_ctx, _focused_ic->serial, type, value);
2968 request_help (int id, uint32 context_id) {
2969 LOGD ("client id:%d", id);
2970 panel_slot_request_help (context_id);
2975 request_factory_menu (int id, uint32 context_id) {
2976 LOGD ("client id:%d", id);
2977 panel_slot_request_factory_menu (context_id);
2981 change_factory (int id, uint32 context_id, const String& uuid) {
2982 LOGD ("client id:%d", id);
2983 panel_slot_change_factory (context_id, uuid);
2988 reset_keyboard_ise (int id, uint32 context_id) {
2989 LOGD ("client id:%d", id);
2990 panel_slot_reset_keyboard_ise (context_id);
2995 update_keyboard_ise (int id, uint32 context_id) {
2996 LOGD ("client id:%d", id);
2997 panel_slot_update_keyboard_ise (context_id);
3002 show_preedit_string (int id, uint32 context_id) {
3003 LOGD ("client id:%d", id);
3004 _show_preedit_string (context_id);
3008 hide_preedit_string (int id, uint32 context_id) {
3009 LOGD ("client id:%d", id);
3010 _hide_preedit_string (context_id, true);
3014 update_preedit_string (int id, uint32 context_id, WideString preedit, WideString commit, AttributeList& attrs, uint32 caret) {
3015 LOGD ("client id:%d", id);
3016 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
3017 WSCContextISF* ic = find_ic (context_id);
3019 if (ic && ic->impl && _focused_ic == ic) {
3020 if (!ic->impl->is_on)
3021 ic->impl->is_on = true;
3023 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
3025 ic->impl->preedit_string = preedit;
3026 ic->impl->preedit_attrlist = attrs;
3027 ic->impl->commit_string = commit;
3029 if (ic->impl->use_preedit) {
3030 if (!ic->impl->preedit_started) {
3031 if (!check_valid_ic (ic))
3034 ic->impl->preedit_started = true;
3035 ic->impl->need_commit_preedit = true;
3037 if (caret <= preedit.length ())
3038 ic->impl->preedit_caret = caret;
3040 ic->impl->preedit_caret = preedit.length ();
3041 wsc_context_send_preedit_string (ic);
3043 String _str = utf8_wcstombs (preedit);
3044 g_info_manager->socket_update_preedit_string (_str, attrs, (uint32)caret);
3050 recapture_string (int id, uint32 context_id, int offset, int len, WideString preedit, WideString commit, AttributeList& attrs) {
3051 LOGD ("client id:%d", id);
3052 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
3053 WSCContextISF* ic = find_ic (context_id);
3054 String preedit_str = utf8_wcstombs (preedit);
3055 String commit_str = utf8_wcstombs (commit);
3057 if (ic && ic->impl && _focused_ic == ic) {
3058 if (!ic->impl->is_on)
3059 ic->impl->is_on = true;
3061 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
3063 ic->impl->preedit_string = preedit;
3064 ic->impl->preedit_attrlist = attrs;
3065 ic->impl->commit_string = commit;
3067 if (ic->impl->use_preedit) {
3068 if (!ic->impl->preedit_started) {
3069 if (!check_valid_ic (ic))
3072 ic->impl->preedit_started = true;
3073 ic->impl->need_commit_preedit = true;
3075 ic->impl->preedit_caret = preedit.length ();
3077 wl_input_method_context_preedit_cursor (ic->im_ctx, strlen(preedit_str.c_str()));
3078 wsc_send_preedit_style (ic);
3080 wl_input_method_context_recapture_string (ic->im_ctx, ic->serial,
3081 offset, len, preedit_str.c_str(), preedit_str.c_str(), commit_str.c_str());
3083 g_info_manager->socket_recapture_string (offset, len, preedit_str, commit_str, attrs);
3089 surrounding_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
3090 if (fd_handler == NULL || data == NULL)
3091 return ECORE_CALLBACK_RENEW;
3093 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
3095 int fd = ecore_main_fd_handler_fd_get (fd_handler);
3097 return ECORE_CALLBACK_RENEW;
3100 int len = read (fd, buff, sizeof (buff) - 1);
3102 LOGD ("update, wsc_ctx->surrounding_cursor = %d\n", wsc_ctx->surrounding_cursor);
3103 g_info_manager->socket_update_surrounding_text (wsc_ctx->surrounding_text ? wsc_ctx->surrounding_text : "", wsc_ctx->surrounding_cursor);
3104 } else if (len < 0) {
3108 if (wsc_ctx->surrounding_text == NULL) {
3109 if (len >= (int)sizeof(int)) {
3110 /* Add one byte for terminating NULL character and subtract <int> byte for cursor position */
3111 wsc_ctx->surrounding_text = (char*)malloc (len + 1 - sizeof(int));
3112 if (wsc_ctx->surrounding_text) {
3113 memcpy(&(wsc_ctx->surrounding_cursor), buff, sizeof(int));
3114 memcpy (wsc_ctx->surrounding_text, buff + sizeof(int), len - sizeof(int));
3115 wsc_ctx->surrounding_text[len - sizeof(int)] = '\0';
3116 return ECORE_CALLBACK_RENEW;
3118 LOGE ("malloc failed");
3122 int old_len = strlen (wsc_ctx->surrounding_text);
3123 void * _new = realloc (wsc_ctx->surrounding_text, len + old_len + 1);
3125 wsc_ctx->surrounding_text = (char*)_new;
3126 memcpy (wsc_ctx->surrounding_text + old_len, buff, len);
3127 wsc_ctx->surrounding_text[old_len + len] = '\0';
3128 return ECORE_CALLBACK_RENEW;
3130 LOGE ("realloc failed");
3135 if (wsc_ctx->surrounding_text_fd_read_handler) {
3137 ecore_main_fd_handler_del (wsc_ctx->surrounding_text_fd_read_handler);
3138 wsc_ctx->surrounding_text_fd_read_handler = NULL;
3141 if (wsc_ctx->surrounding_text) {
3142 free (wsc_ctx->surrounding_text);
3143 wsc_ctx->surrounding_text = NULL;
3146 return ECORE_CALLBACK_RENEW;
3150 socket_helper_get_surrounding_text (int id, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after) {
3151 LOGD ("client id:%d", id);
3154 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) == -1) {
3155 LOGW ("create pipe failed");
3158 LOGD("%d,%d", filedes[0], filedes[1]);
3159 WSCContextISF* ic = find_ic (context_id);
3163 wl_input_method_context_get_surrounding_text (ic->im_ctx, maxlen_before, maxlen_after, filedes[1]);
3168 if (ic->surrounding_text_fd_read_handler) {
3169 int fd = ecore_main_fd_handler_fd_get (ic->surrounding_text_fd_read_handler);
3171 ecore_main_fd_handler_del (ic->surrounding_text_fd_read_handler);
3172 ic->surrounding_text_fd_read_handler = NULL;
3175 if (ic->surrounding_text) {
3176 free (ic->surrounding_text);
3177 ic->surrounding_text = NULL;
3180 ic->surrounding_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, surrounding_text_fd_read_func, ic, NULL, NULL);
3184 socket_helper_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len) {
3185 LOGD ("client id:%d", id);
3186 //panel_slot_delete_surrounding_text (context_id, offset, len);
3188 check_input_resource (_focused_ic, INPUT_RESOURCE_LOCAL);
3189 wsc_context_delete_surrounding (_focused_ic, offset, len);
3194 socket_helper_set_selection (int id, uint32 context_id, uint32 start, uint32 end) {
3195 LOGD ("client id:%d", id);
3197 wsc_context_set_selection (_focused_ic, start, end);
3201 send_private_command (int id, uint32 context_id, const String& command) {
3202 LOGD ("client id:%d", id);
3203 //panel_slot_send_private_command (context_id, command);
3204 if (_focused_ic && _focused_ic->im_ctx)
3205 wl_input_method_context_private_command (_focused_ic->im_ctx, _focused_ic->serial, command.c_str ());
3209 commit_content (int id, uint32 context_id, const String& content, const String& description, const String& mime_types) {
3210 LOGD ("client id:%d", id);
3211 if (_focused_ic && _focused_ic->im_ctx)
3212 wl_input_method_context_commit_content (_focused_ic->im_ctx, _focused_ic->serial, content.c_str (), description.c_str (), mime_types.c_str ());
3216 hide_helper_ise (int id, uint32 context_id)
3218 LOGD ("client id:%d", id);
3219 WSCContextISF* ic = find_ic (context_id);
3222 wl_input_method_context_hide_input_panel (ic->im_ctx, ic->serial);
3227 selection_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
3228 if (fd_handler == NULL || data == NULL)
3229 return ECORE_CALLBACK_RENEW;
3231 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
3233 int fd = ecore_main_fd_handler_fd_get (fd_handler);
3235 return ECORE_CALLBACK_RENEW;
3238 int len = read (fd, buff, sizeof (buff) - 1);
3241 g_info_manager->socket_update_selection (wsc_ctx->selection_text ? wsc_ctx->selection_text : "");
3242 } else if (len < 0) {
3246 if (wsc_ctx->selection_text == NULL) {
3247 wsc_ctx->selection_text = (char*)malloc (len + 1);
3248 if (wsc_ctx->selection_text) {
3249 memcpy (wsc_ctx->selection_text, buff, len);
3250 wsc_ctx->selection_text[len] = '\0';
3251 return ECORE_CALLBACK_RENEW;
3253 LOGE ("malloc failed");
3256 int old_len = strlen (wsc_ctx->selection_text);
3257 void * _new = realloc (wsc_ctx->selection_text, len + old_len + 1);
3259 wsc_ctx->selection_text = (char*)_new;
3260 memcpy (wsc_ctx->selection_text + old_len, buff, len);
3261 wsc_ctx->selection_text[old_len + len] = '\0';
3262 return ECORE_CALLBACK_RENEW;
3264 LOGE ("realloc failed");
3269 if (wsc_ctx->selection_text_fd_read_handler) {
3271 ecore_main_fd_handler_del (wsc_ctx->selection_text_fd_read_handler);
3272 wsc_ctx->selection_text_fd_read_handler = NULL;
3275 if (wsc_ctx->selection_text) {
3276 free (wsc_ctx->selection_text);
3277 wsc_ctx->selection_text = NULL;
3280 return ECORE_CALLBACK_RENEW;
3284 socket_helper_get_selection (int id, uint32 context_id) {
3285 LOGD ("client id:%d", id);
3288 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) ==-1 ) {
3289 LOGW ("create pipe failed");
3292 LOGD("%d,%d", filedes[0], filedes[1]);
3294 WSCContextISF* ic = find_ic (context_id);
3297 wl_input_method_context_get_selection_text (ic->im_ctx, filedes[1]);
3301 if (ic->selection_text_fd_read_handler) {
3302 int fd = ecore_main_fd_handler_fd_get (ic->selection_text_fd_read_handler);
3306 ecore_main_fd_handler_del (ic->selection_text_fd_read_handler);
3307 ic->selection_text_fd_read_handler = NULL;
3310 if (ic->selection_text) {
3311 free (ic->selection_text);
3312 ic->selection_text = NULL;
3315 ic->selection_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, selection_text_fd_read_func, ic, NULL, NULL);
3318 void process_key_event_done (int id, uint32 context_id, KeyEvent &key, uint32 ret, uint32 serial) {
3319 LOGD ("client id:%d", id);
3320 WSCContextISF* ic = find_ic (context_id);
3323 #if ENABLE_GRAB_KEYBOARD
3324 if (ret == EINA_FALSE) {
3325 send_wl_key_event (ic, key, false);
3328 wl_input_method_context_filter_key_event_done (ic->im_ctx, serial, ret);
3332 void request_ise_hide (int id, uint32 context_id) {
3333 LOGD ("client id:%d", id);
3334 WSCContextISF* ic = find_ic (context_id);
3337 wl_input_method_context_hide_input_panel (ic->im_ctx, ic->serial);
3341 update_ise_geometry (int id, uint32 context_id, uint32 x, uint32 y, uint32 width, uint32 height) {
3342 LOGD ("client id:%d", id);
3344 if (_focused_ic && _focused_ic->im_ctx) {
3345 wl_input_method_context_update_ise_geometry (_focused_ic->im_ctx, _focused_ic->serial, x, y, width, height);
3349 void helper_candidate_show(int id, uint32 context_id, const String& uuid)
3351 WSCContextISF* ic = find_ic(context_id);
3355 wl_input_method_context_update_candidate_state(ic->im_ctx, 1);
3359 void helper_candidate_hide(int id, uint32 context_id, const String& uuid)
3361 WSCContextISF* ic = find_ic(context_id);
3365 wl_input_method_context_update_candidate_state(ic->im_ctx, 0);
3372 EXAPI void scim_module_init (void)
3377 EXAPI void scim_module_exit (void)
3383 EXAPI void scim_panel_agent_module_init (const scim::ConfigPointer& config)
3389 EXAPI scim::PanelAgentPointer scim_panel_agent_module_get_instance ()
3391 scim::PanelAgentBase* _instance = NULL;
3392 if (instance.null ()) {
3394 _instance = new WaylandPanelAgent ();
3401 instance = _instance;
3408 vi:ts=4:nowrap:expandtab