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 #define EFL_BETA_API_SUPPORT
50 #include <Ecore_Wl2.h>
52 #include <vconf-keys.h>
53 #include <input-method-client-protocol.h>
54 #include <text-client-protocol.h>
56 #include "scim_private.h"
58 #include "isf_wsc_context.h"
59 #include "isf_wsc_control_ui.h"
60 #include "tizen_profile.h"
62 #include <linux/input.h>
64 #if ENABLE_GRAB_KEYBOARD
65 #include <xkbcommon/xkbcommon.h>
69 #include "isf_debug.h"
75 #define LOG_TAG "ISF_WAYLAND_MODULE"
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;
100 int return_key_disabled;
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;
110 WSCContextISFImpl *next;
113 _WSCContextISFImpl() : parent(NULL),
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),
128 return_key_disabled(0),
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),
142 /* private functions */
144 static void panel_slot_update_preedit_caret (int context,
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,
151 static void panel_slot_forward_key_event (int context,
154 static void panel_slot_update_preedit_string (int context,
155 const WideString str,
156 const WideString commit,
157 const AttributeList &attrs,
160 static void _show_preedit_string (int context);
162 static void panel_req_update_bidi_direction (WSCContextISF *ic, int direction);
164 static void remote_surrounding_get (WSCContextISF *wsc_ctx);
166 static void wl_im_destroy (void);
168 /* Panel iochannel handler*/
169 static void panel_initialize (void);
170 static void panel_finalize (void);
172 /* utility functions */
174 static bool filter_keys (const char *keyname,
175 const char *config_path);
176 static void set_ic_capabilities (WSCContextISF *ic);
178 static void initialize (void);
179 static void finalize (void);
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);
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;
190 static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
191 static int _valid_key_mask = SCIM_KEY_AllMasks;
193 static ConfigPointer _config;
195 static WSCContextISF *_focused_ic = 0;
197 static bool _scim_initialized = false;
199 static int _panel_client_id = 0;
200 static uint32 _active_helper_option = 0;
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;
206 static bool _x_key_event_is_valid = false;
208 static Ecore_Timer *_resource_check_timer = NULL;
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;
214 #define WAYLAND_MODULE_CLIENT_ID (0)
215 #define MAX_PREEDIT_BUFSIZE 4000
217 #define MOD_SHIFT_MASK 0x01
218 #define MOD_CAPS_MASK 0x02
219 #define MOD_CONTROL_MASK 0x04
220 #define MOD_ALT_MASK 0x08
221 #define MOD_NUM_MASK 0x100
222 #define MOD_Mod5_MASK 0x80
224 #define WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_MASK 0xff0000
226 //////////////////////////////wayland_panel_agent_module begin//////////////////////////////////////////////////
228 #define scim_module_init wayland_LTX_scim_module_init
229 #define scim_module_exit wayland_LTX_scim_module_exit
230 #define scim_panel_agent_module_init wayland_LTX_scim_panel_agent_module_init
231 #define scim_panel_agent_module_get_instance wayland_LTX_scim_panel_agent_module_get_instance
233 static struct weescim _wsc = {0};
235 InfoManager* g_info_manager = NULL;
236 static scim::PanelAgentPointer instance;
239 /////////////////////////////////////////////////////////////////////////////
240 // Implementation of Wayland Input Method functions.
241 /////////////////////////////////////////////////////////////////////////////
244 _wsc_im_ctx_reset (void *data, struct wl_input_method_context *im_ctx)
246 WSCContextISF *context_scim = (WSCContextISF*)data;
248 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
249 g_info_manager->socket_reset_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
254 _wsc_im_ctx_content_type (void *data, struct wl_input_method_context *im_ctx, uint32_t hint, uint32_t purpose)
256 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
257 if (!wsc_ctx) return;
259 LOGD ("im_context = %p hint = %04x purpose = %d", im_ctx, hint, purpose);
262 if (wsc_ctx->content_purpose != purpose || !wsc_ctx->layout_initialized) {
263 wsc_ctx->layout_initialized = EINA_TRUE;
264 wsc_ctx->content_purpose = purpose;
265 isf_wsc_context_input_panel_layout_set (wsc_ctx, wsc_context_input_panel_layout_get (wsc_ctx));
268 if (wsc_ctx->content_hint != hint) {
269 uint32_t hint_copy, old_hintbit, new_hintbit;
270 const uint32_t autocap_type = WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
271 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
272 WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
274 hint_copy = wsc_ctx->content_hint;
275 wsc_ctx->content_hint = hint;
277 // Set prediction allow
278 old_hintbit = hint_copy & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
279 new_hintbit = hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
280 if (old_hintbit != new_hintbit || !wsc_ctx->prediction_allow_initialized) {
281 wsc_ctx->prediction_allow_initialized = EINA_TRUE;
282 g_info_manager->set_prediction_allow (WAYLAND_MODULE_CLIENT_ID, wsc_context_prediction_allow_get (wsc_ctx));
285 // Set autocapital type
286 old_hintbit = hint_copy & autocap_type;
287 new_hintbit = hint & autocap_type;
288 if (old_hintbit != new_hintbit || !wsc_ctx->autocapital_type_initialized) {
289 wsc_ctx->autocapital_type_initialized = EINA_TRUE;
290 isf_wsc_context_autocapital_type_set (wsc_ctx, wsc_context_autocapital_type_get (wsc_ctx));
294 old_hintbit = hint_copy & WL_TEXT_INPUT_CONTENT_HINT_LATIN;
295 new_hintbit = hint & WL_TEXT_INPUT_CONTENT_HINT_LATIN;
296 if (old_hintbit != new_hintbit || !wsc_ctx->language_initialized) {
297 wsc_ctx->language_initialized = EINA_TRUE;
298 isf_wsc_context_input_panel_language_set (wsc_ctx, wsc_context_input_panel_language_get (wsc_ctx));
301 isf_wsc_context_input_hint_set (wsc_ctx, wsc_context_input_hint_get (wsc_ctx));
305 isf_wsc_context_send_entry_metadata (wsc_ctx, wsc_context_input_hint_get (wsc_ctx), wsc_context_input_panel_layout_get (wsc_ctx),
306 wsc_context_input_panel_layout_variation_get (wsc_ctx), wsc_context_autocapital_type_get (wsc_ctx), wsc_ctx->return_key_disabled);
311 _wsc_im_ctx_invoke_action (void *data, struct wl_input_method_context *im_ctx, uint32_t button, uint32_t index)
313 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
314 if (!wsc_ctx) return;
316 LOGD ("invoke action. button : %d", button);
318 if (button != BTN_LEFT)
321 wsc_context_send_preedit_string (wsc_ctx);
325 _wsc_im_ctx_commit_state (void *data, struct wl_input_method_context *im_ctx, uint32_t serial)
327 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
328 if (!wsc_ctx) return;
330 wsc_ctx->serial = serial;
332 if (wsc_ctx->language)
333 wl_input_method_context_language (im_ctx, wsc_ctx->serial, wsc_ctx->language);
337 _wsc_im_ctx_preferred_language (void *data, struct wl_input_method_context *im_ctx, const char *language)
339 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
340 if (!wsc_ctx) return;
342 if (language && wsc_ctx->language && !strcmp (language, wsc_ctx->language))
345 if (wsc_ctx->language) {
346 free (wsc_ctx->language);
347 wsc_ctx->language = NULL;
351 wsc_ctx->language = strdup (language);
352 LOGD ("Language changed, new: '%s'", language);
357 _wsc_im_ctx_return_key_type (void *data, struct wl_input_method_context *im_ctx, uint32_t return_key_type)
359 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
361 LOGD ("im_context = %p return key type = %d", im_ctx, return_key_type);
362 if (!wsc_ctx) return;
364 if (wsc_ctx->return_key_type != return_key_type) {
365 wsc_ctx->return_key_type = return_key_type;
366 isf_wsc_context_input_panel_return_key_type_set (wsc_ctx, (Ecore_IMF_Input_Panel_Return_Key_Type)wsc_ctx->return_key_type);
371 _wsc_im_ctx_return_key_disabled (void *data, struct wl_input_method_context *im_ctx, uint32_t disabled)
373 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
374 Eina_Bool return_key_disabled = !!disabled;
376 LOGD ("im_context = %p return key disabled = %d", im_ctx, return_key_disabled);
377 if (!wsc_ctx) return;
379 if (wsc_ctx->return_key_disabled != return_key_disabled) {
380 wsc_ctx->return_key_disabled = return_key_disabled;
381 isf_wsc_context_input_panel_return_key_disabled_set (wsc_ctx, wsc_ctx->return_key_disabled);
383 isf_wsc_context_send_entry_metadata (wsc_ctx, wsc_context_input_hint_get (wsc_ctx), wsc_context_input_panel_layout_get (wsc_ctx),
384 wsc_context_input_panel_layout_variation_get (wsc_ctx), wsc_context_autocapital_type_get (wsc_ctx), wsc_ctx->return_key_disabled);
389 _wsc_im_ctx_input_panel_data (void *data, struct wl_input_method_context *im_ctx, const char *input_panel_data, uint32_t input_panel_data_length)
391 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
392 LOGD ("im_context = %p input panel data = %s len = %d", im_ctx, input_panel_data, input_panel_data_length);
393 if (!wsc_ctx) return;
396 if (wsc_ctx->impl->imdata) {
397 free(wsc_ctx->impl->imdata);
400 wsc_ctx->impl->imdata = calloc(1, input_panel_data_length);
401 if (wsc_ctx->impl->imdata)
402 memcpy(wsc_ctx->impl->imdata, input_panel_data, input_panel_data_length);
404 wsc_ctx->impl->imdata_size = input_panel_data_length;
407 isf_wsc_context_input_panel_imdata_set (wsc_ctx, (void *)input_panel_data, input_panel_data_length);
411 _wsc_im_ctx_bidi_direction (void *data, struct wl_input_method_context *im_ctx, uint32_t bidi_direction)
413 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
415 LOGD ("im_context = %p bidi_direction = %d", im_ctx, bidi_direction);
416 if (!wsc_ctx) return;
418 if (wsc_ctx->bidi_direction != bidi_direction) {
419 wsc_ctx->bidi_direction = bidi_direction;
421 isf_wsc_context_bidi_direction_set (wsc_ctx, (Ecore_IMF_BiDi_Direction)wsc_ctx->bidi_direction);
426 _wsc_im_ctx_cursor_position (void *data, struct wl_input_method_context *im_ctx, uint32_t cursor_pos)
428 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
430 LOGD ("im_context = %p cursor_pos = %d", im_ctx, cursor_pos);
431 if (!wsc_ctx || !wsc_ctx->impl) return;
432 wsc_ctx->impl->cursor_pos = cursor_pos;
433 wsc_ctx->surrounding_cursor = cursor_pos;
434 LOGD ("wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
435 g_info_manager->socket_update_cursor_position (cursor_pos);
438 remote_surrounding_get (wsc_ctx);
442 _wsc_im_ctx_process_input_device_event (void *data, struct wl_input_method_context *im_ctx, uint32_t type, const char *input_data, uint32_t input_data_len)
444 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
446 LOGD("im_context = %p type = %d, data = (%p) %d", im_ctx, type, input_data, input_data_len);
447 if (!wsc_ctx) return;
449 isf_wsc_context_process_input_device_event (wsc_ctx, type, input_data, input_data_len);
453 _wsc_im_ctx_filter_key_event (void *data, struct wl_input_method_context *im_ctx, uint32_t serial, uint32_t time, const char *keyname, uint32_t state, uint32_t modifiers, const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
455 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
456 if (!wsc_ctx) return;
458 #if !(ENABLE_GRAB_KEYBOARD)
459 isf_wsc_context_filter_key_event (wsc_ctx, serial, time, keyname,
460 ((wl_keyboard_key_state)state) == WL_KEYBOARD_KEY_STATE_PRESSED, modifiers, dev_name, dev_class, dev_subclass);
465 _wsc_im_ctx_capital_mode (void *data, struct wl_input_method_context *im_ctx, uint32_t mode)
467 LOGD ("capital mode %d", mode);
468 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
469 if (!wsc_ctx) return;
470 wsc_ctx->caps_mode = mode;
471 isf_wsc_context_input_panel_caps_mode_set (wsc_ctx, mode);
475 _wsc_im_ctx_prediction_hint (void *data, struct wl_input_method_context *im_ctx, const char *prediction_hint)
477 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
479 LOGD ("im_context = %p, prediction hint = %s", im_ctx, prediction_hint);
480 if (!wsc_ctx) return;
482 isf_wsc_context_input_panel_prediction_hint_set (wsc_ctx, prediction_hint);
486 _wsc_im_ctx_mime_type (void *data, struct wl_input_method_context *im_ctx, const char *mime_type)
488 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
490 LOGD ("im_context = %p, mime_type = %s", im_ctx, mime_type);
491 if (!wsc_ctx) return;
494 wsc_ctx->impl->mime_type = String (mime_type);
497 isf_wsc_context_input_panel_mime_type_accept_set (wsc_ctx, mime_type);
501 _wsc_im_ctx_finalized_content (void *data, struct wl_input_method_context *im_ctx, const char *text, uint32_t cursor_pos)
503 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
505 SECURE_LOGD ("im_context = %p, text = %s, cursor_pos = %d", im_ctx, text, cursor_pos);
506 if (!wsc_ctx) return;
508 isf_wsc_context_input_panel_finalize_content (wsc_ctx, text, cursor_pos);
512 _wsc_im_ctx_prediction_hint_data (void *data, struct wl_input_method_context *im_ctx, const char *key, const char * value)
514 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
515 if (!wsc_ctx) return;
517 isf_wsc_context_input_panel_prediction_hint_data_set (wsc_ctx, key, value);
520 static const struct wl_input_method_context_listener wsc_im_context_listener = {
522 _wsc_im_ctx_content_type,
523 _wsc_im_ctx_invoke_action,
524 _wsc_im_ctx_commit_state,
525 _wsc_im_ctx_preferred_language,
526 _wsc_im_ctx_return_key_type,
527 _wsc_im_ctx_return_key_disabled,
528 _wsc_im_ctx_input_panel_data,
529 _wsc_im_ctx_bidi_direction,
530 _wsc_im_ctx_cursor_position,
531 _wsc_im_ctx_process_input_device_event,
532 _wsc_im_ctx_filter_key_event,
533 _wsc_im_ctx_capital_mode,
534 _wsc_im_ctx_prediction_hint,
535 _wsc_im_ctx_mime_type,
536 _wsc_im_ctx_finalized_content,
537 _wsc_im_ctx_prediction_hint_data
540 #if ENABLE_GRAB_KEYBOARD
542 _init_keysym2keycode (WSCContextISF *wsc_ctx)
547 const xkb_keysym_t *syms;
549 if (!wsc_ctx || !wsc_ctx->state)
552 for (i = 0; i < 256; i++) {
554 num_syms = xkb_key_get_syms (wsc_ctx->state, code, &syms);
557 wsc_ctx->_keysym2keycode[syms[0]] = i;
562 _fini_keysym2keycode (WSCContextISF *wsc_ctx)
564 wsc_ctx->_keysym2keycode.clear ();
568 _wsc_im_keyboard_keymap (void *data,
569 struct wl_keyboard *wl_keyboard,
574 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
582 _fini_keysym2keycode (wsc_ctx);
584 if (wsc_ctx->state) {
585 xkb_state_unref (wsc_ctx->state);
586 wsc_ctx->state = NULL;
589 if (wsc_ctx->keymap) {
590 xkb_map_unref (wsc_ctx->keymap);
591 wsc_ctx->keymap = NULL;
594 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
599 map_str = (char*)mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
600 if (map_str == MAP_FAILED) {
606 xkb_map_new_from_string (wsc_ctx->xkb_context,
608 XKB_KEYMAP_FORMAT_TEXT_V1,
609 (xkb_keymap_compile_flags)0);
611 munmap (map_str, size);
614 if (!wsc_ctx->keymap) {
615 LOGW ("failed to compile keymap");
619 wsc_ctx->state = xkb_state_new (wsc_ctx->keymap);
620 if (!wsc_ctx->state) {
621 LOGW ("failed to create XKB state");
622 xkb_map_unref (wsc_ctx->keymap);
626 wsc_ctx->control_mask =
627 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Control");
629 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Mod1");
630 wsc_ctx->shift_mask =
631 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Shift");
633 LOGD ("create _keysym2keycode");
634 _init_keysym2keycode (wsc_ctx);
638 _wsc_im_keyboard_key (void *data,
639 struct wl_keyboard *wl_keyboard,
645 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
648 const xkb_keysym_t *syms;
650 char keyname[64] = {0};
651 enum wl_keyboard_key_state state = (wl_keyboard_key_state)state_w;
653 if (!wsc_ctx || !wsc_ctx->state)
657 num_syms = xkb_key_get_syms (wsc_ctx->state, code, &syms);
659 sym = XKB_KEY_NoSymbol;
662 xkb_keysym_get_name (sym, keyname, 64);
665 isf_wsc_context_filter_key_event (wsc_ctx, serial, time, code, sym, keyname,
670 _wsc_im_keyboard_modifiers (void *data,
671 struct wl_keyboard *wl_keyboard,
673 uint32_t mods_depressed,
674 uint32_t mods_latched,
675 uint32_t mods_locked,
678 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
679 if (!wsc_ctx || !wsc_ctx->state)
682 struct wl_input_method_context *context = wsc_ctx->im_ctx;
685 xkb_state_update_mask (wsc_ctx->state, mods_depressed,
686 mods_latched, mods_locked, 0, 0, group);
687 mask = xkb_state_serialize_mods (wsc_ctx->state,
688 (xkb_state_component)(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED));
690 wsc_ctx->modifiers = 0;
691 if (mask & wsc_ctx->control_mask)
692 wsc_ctx->modifiers |= SCIM_KEY_ControlMask;
693 if (mask & wsc_ctx->alt_mask)
694 wsc_ctx->modifiers |= SCIM_KEY_AltMask;
695 if (mask & wsc_ctx->shift_mask)
696 wsc_ctx->modifiers |= SCIM_KEY_ShiftMask;
698 wl_input_method_context_modifiers (context, serial,
699 mods_depressed, mods_depressed,
700 mods_latched, group);
703 static const struct wl_keyboard_listener wsc_im_keyboard_listener = {
704 _wsc_im_keyboard_keymap,
707 _wsc_im_keyboard_key,
708 _wsc_im_keyboard_modifiers
715 if (!_wl_im_ctx || !_wl_im_ctx->wsc || !_wl_im_ctx->wsc->wsc_ctx)
718 WSCContextISF *wsc_ctx = _wl_im_ctx->wsc->wsc_ctx;
720 if (_wl_im_ctx->need_focus_event)
721 isf_wsc_context_focus_out (wsc_ctx);
723 #if ENABLE_GRAB_KEYBOARD
724 if (wsc_ctx->keyboard) {
725 wl_keyboard_destroy (wsc_ctx->keyboard);
726 wsc_ctx->keyboard = NULL;
729 _fini_keysym2keycode (wsc_ctx);
731 if (wsc_ctx->state) {
732 xkb_state_unref (wsc_ctx->state);
733 wsc_ctx->state = NULL;
736 if (wsc_ctx->keymap) {
737 xkb_map_unref (wsc_ctx->keymap);
738 wsc_ctx->keymap = NULL;
741 if (wsc_ctx->xkb_context) {
742 xkb_context_unref (wsc_ctx->xkb_context);
743 wsc_ctx->xkb_context = NULL;
747 if (wsc_ctx->im_ctx) {
748 wl_input_method_context_destroy (wsc_ctx->im_ctx);
749 wsc_ctx->im_ctx = NULL;
752 if (wsc_ctx->preedit_str) {
753 free (wsc_ctx->preedit_str);
754 wsc_ctx->preedit_str = NULL;
757 if (wsc_ctx->surrounding_text) {
758 free (wsc_ctx->surrounding_text);
759 wsc_ctx->surrounding_text = NULL;
762 if (wsc_ctx->remote_surrounding_text) {
763 free (wsc_ctx->remote_surrounding_text);
764 wsc_ctx->remote_surrounding_text = NULL;
767 if (wsc_ctx->language) {
768 free (wsc_ctx->language);
769 wsc_ctx->language = NULL;
772 wsc_ctx->layout_initialized = EINA_FALSE;
773 wsc_ctx->prediction_allow_initialized = EINA_FALSE;
774 wsc_ctx->autocapital_type_initialized = EINA_FALSE;
775 wsc_ctx->language_initialized = EINA_FALSE;
777 if (_resource_check_timer)
778 ecore_timer_del (_resource_check_timer);
779 _resource_check_timer = NULL;
781 isf_wsc_context_del (wsc_ctx);
783 _wl_im_ctx->wsc->wsc_ctx = NULL;
784 _wl_im_ctx->input_method = NULL;
785 _wl_im_ctx->im_ctx = NULL;
786 _wl_im_ctx->need_focus_event = EINA_FALSE;
787 _need_wl_im_init = false;
791 _wsc_im_activate (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx, uint32_t text_input_id, uint32_t focus_in_event)
793 struct weescim *wsc = (weescim*)data;
796 WSCContextISF *wsc_ctx = new WSCContextISF;
801 if (_need_wl_im_init)
804 #if ENABLE_GRAB_KEYBOARD
805 wsc_ctx->xkb_context = xkb_context_new ((xkb_context_flags)0);
806 if (wsc_ctx->xkb_context == NULL) {
807 LOGW ("Failed to create XKB context");
811 wsc_ctx->state = NULL;
812 wsc_ctx->keymap = NULL;
813 wsc_ctx->modifiers = 0;
816 wsc_ctx->id = text_input_id;
817 wsc->wsc_ctx = wsc_ctx;
819 wsc_ctx->surrounding_text = NULL;
820 wsc_ctx->remote_surrounding_text = NULL;
821 wsc_ctx->surrounding_cursor = 0;
822 LOGD ("wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
824 get_language (&wsc_ctx->language);
826 wsc_ctx->preedit_str = strdup ("");
827 wsc_ctx->content_hint = WL_TEXT_INPUT_CONTENT_HINT_NONE;
828 wsc_ctx->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
830 wsc_ctx->im_ctx = im_ctx;
831 wl_input_method_context_add_listener (im_ctx, &wsc_im_context_listener, wsc_ctx);
833 #if ENABLE_GRAB_KEYBOARD
834 wsc_ctx->keyboard = wl_input_method_context_grab_keyboard (im_ctx);
835 if (wsc_ctx->keyboard)
836 wl_keyboard_add_listener (wsc_ctx->keyboard, &wsc_im_keyboard_listener, wsc_ctx);
839 if (wsc_ctx->language)
840 wl_input_method_context_language (im_ctx, wsc_ctx->serial, wsc_ctx->language);
842 isf_wsc_context_add (wsc_ctx);
844 if (focus_in_event) {
845 isf_wsc_context_focus_in (wsc_ctx);
846 _wl_im_ctx->need_focus_event = EINA_TRUE;
851 _wsc_im_deactivate (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx, uint32_t focus_out_event)
853 struct weescim *wsc = (weescim*)data;
854 if (!wsc || !wsc->wsc_ctx) return;
856 /* When the focus_in/input_panel_shutdown event is called,
857 * it is not possible to know the information of wl_input_method to destroy */
858 _wl_im_ctx->wsc = wsc;
859 _wl_im_ctx->input_method = input_method;
860 _wl_im_ctx->im_ctx = im_ctx;
861 _need_wl_im_init = true;
863 if (focus_out_event) {
864 isf_wsc_context_focus_out (wsc->wsc_ctx);
865 _wl_im_ctx->need_focus_event = EINA_FALSE;
870 _wsc_im_show_input_panel (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
872 struct weescim *wsc = (weescim*)data;
873 if (!wsc || !wsc->wsc_ctx) return;
875 isf_wsc_context_input_panel_show (wsc->wsc_ctx);
876 wsc->wsc_ctx->input_panel_shown = true;
879 remote_surrounding_get (wsc->wsc_ctx);
883 _wsc_im_hide_input_panel (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
885 struct weescim *wsc = (weescim*)data;
886 if (!wsc || !wsc->wsc_ctx) return;
888 isf_wsc_context_input_panel_hide (wsc->wsc_ctx);
889 wsc->wsc_ctx->input_panel_shown = false;
892 static const struct wl_input_method_listener wsc_im_listener = {
895 _wsc_im_show_input_panel,
896 _wsc_im_hide_input_panel
900 _wsc_setup (struct weescim *wsc)
902 Eina_Iterator *globals;
903 struct wl_registry *registry;
904 Ecore_Wl2_Global *global;
906 if (!wsc) return false;
908 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get (NULL);
910 LOGW ("failed to get wl2_display, try connecting");
911 wl2_display = ecore_wl2_display_connect (NULL);
914 LOGW ("failed to connect");
919 if (!(registry = ecore_wl2_display_registry_get (wl2_display))) {
920 LOGW ("failed to get wl_registry");
924 if (!(globals = ecore_wl2_display_globals_get (wl2_display))) {
925 LOGW ("failed to get wl_globals");
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);
933 eina_iterator_free (globals);
935 if (wsc->im == NULL) {
936 LOGW ("Failed because wl_input_method is null");
940 /* Input method listener */
941 LOGD ("Adding wl_input_method listener");
944 wl_input_method_add_listener (wsc->im, &wsc_im_listener, wsc);
946 LOGW ("Couldn't get wayland input method interface");
954 //////////////////////////////wayland_panel_agent_module end//////////////////////////////////////////////////
963 get_panel_client_id (void)
965 return _panel_client_id;
969 get_language (char **language)
971 *language = strdup (_language.c_str ());
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);
987 /* Function Implementations */
988 static WSCContextISFImpl *
989 new_ic_impl (WSCContextISF *parent)
991 WSCContextISFImpl *impl = NULL;
993 if (_free_ic_impl_list != NULL) {
994 impl = _free_ic_impl_list;
995 _free_ic_impl_list = _free_ic_impl_list->next;
997 impl = new WSCContextISFImpl;
1002 impl->next = _used_ic_impl_list;
1003 _used_ic_impl_list = impl;
1005 impl->parent = parent;
1011 delete_ic_impl (WSCContextISFImpl *impl)
1013 WSCContextISFImpl *rec = _used_ic_impl_list, *last = 0;
1015 for (; rec != 0; last = rec, rec = rec->next) {
1018 last->next = rec->next;
1020 _used_ic_impl_list = rec->next;
1022 rec->next = _free_ic_impl_list;
1023 _free_ic_impl_list = rec;
1030 rec->imdata_size = 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;
1045 delete_all_ic_impl (void)
1047 WSCContextISFImpl *it = _used_ic_impl_list;
1050 _used_ic_impl_list = it->next;
1052 it = _used_ic_impl_list;
1055 it = _free_ic_impl_list;
1057 _free_ic_impl_list = it->next;
1059 it = _free_ic_impl_list;
1063 static WSCContextISF *
1066 WSCContextISFImpl *rec = _used_ic_impl_list;
1069 if (rec->parent && rec->parent->id == id)
1078 check_valid_ic (WSCContextISF *ic)
1080 if (ic && ic->impl && ic->ctx)
1086 void context_scim_imdata_get (WSCContextISF *wsc_ctx, void *data, int *length, int max_len)
1088 WSCContextISF* context_scim = wsc_ctx;
1090 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
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;
1099 memcpy (data, context_scim->impl->imdata, max_len);
1105 void context_scim_mime_type_get (WSCContextISF *wsc_ctx, char *mime_types, int max_len)
1107 WSCContextISF* context_scim = wsc_ctx;
1109 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
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)
1119 memcpy ((void*)mime_types, (context_scim->impl->mime_type).c_str (), max_len);
1126 insert_text (const char *text, uint32_t offset, const char *insert)
1128 uint32_t tlen = strlen (text), ilen = strlen (insert);
1129 char *new_text = (char*)malloc (tlen + ilen + 1);
1131 if ((unsigned int) tlen < offset)
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';
1143 change_block_status_timer_cb (void *data)
1145 WSCContextISF* context_scim = static_cast<WSCContextISF*>(data);
1146 if (context_scim && context_scim->impl)
1147 context_scim->impl->block_input_resource = false;
1149 _resource_check_timer = NULL;
1151 return ECORE_CALLBACK_CANCEL;
1155 check_input_resource (WSCContextISF *wsc_ctx, Input_Resource input_res)
1157 WSCContextISF* context_scim = wsc_ctx;
1158 LOGD ("Input resource : %d", input_res);
1159 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1161 if (context_scim && context_scim->impl) {
1162 if (context_scim->impl->input_resource == input_res)
1166 if (context_scim->impl->input_resource != input_res && input_res != INPUT_RESOURCE_NONE)
1167 g_info_manager->remoteinput_callback_input_resource (input_res);
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 ());
1175 context_scim->impl->need_commit_preedit = false;
1176 context_scim->impl->preedit_string.clear ();
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;
1184 context_scim->impl->input_resource = input_res;
1188 /* Public functions */
1190 isf_wsc_context_init (void)
1192 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1195 if (!_scim_initialized) {
1196 _ecore_wl2_init_count = ecore_wl2_init ();
1197 if (_ecore_wl2_init_count > 0) {
1199 _scim_initialized = true;
1200 isf_wsc_input_panel_init ();
1201 //isf_wsc_context_set_hardware_keyboard_mode(context_scim);
1204 LOGE("Failed to initialize Ecore_Wl");
1209 isf_wsc_context_shutdown (void)
1212 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1214 if (_scim_initialized) {
1215 _scim_initialized = false;
1217 isf_wsc_input_panel_shutdown ();
1220 if (_ecore_wl2_init_count > 0) {
1221 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get (NULL);
1223 ecore_wl2_display_disconnect (wl2_display);
1225 ecore_wl2_shutdown ();
1226 _ecore_wl2_init_count = 0;
1232 isf_wsc_context_add (WSCContextISF *wsc_ctx)
1234 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1236 WSCContextISF* context_scim = wsc_ctx;
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;
1246 context_scim->impl = new_ic_impl (context_scim);
1247 if (context_scim->impl == NULL) {
1248 std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
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;
1264 context_scim->next = NULL;
1266 context_scim->next = _ic_list;
1267 _ic_list = context_scim;
1269 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
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";
1277 isf_wsc_context_del (WSCContextISF *wsc_ctx)
1279 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1282 if (!_ic_list) return;
1284 WSCContextISF *context_scim = wsc_ctx;
1285 if (!context_scim) return;
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);
1290 ecore_main_fd_handler_del (context_scim->selection_text_fd_read_handler);
1291 context_scim->selection_text_fd_read_handler = NULL;
1294 if (context_scim->selection_text) {
1295 free (context_scim->selection_text);
1296 context_scim->selection_text = NULL;
1299 if (context_scim->surrounding_text_fd_read_handler) {
1300 int fd = ecore_main_fd_handler_fd_get (context_scim->surrounding_text_fd_read_handler);
1302 ecore_main_fd_handler_del (context_scim->surrounding_text_fd_read_handler);
1303 context_scim->surrounding_text_fd_read_handler = NULL;
1306 if (context_scim->remote_surrounding_text_fd_read_handler) {
1307 int fd = ecore_main_fd_handler_fd_get (context_scim->remote_surrounding_text_fd_read_handler);
1309 ecore_main_fd_handler_del (context_scim->remote_surrounding_text_fd_read_handler);
1310 context_scim->remote_surrounding_text_fd_read_handler = NULL;
1313 if (context_scim->surrounding_text) {
1314 free (context_scim->surrounding_text);
1315 context_scim->surrounding_text = NULL;
1318 if (context_scim->remote_surrounding_text) {
1319 free (context_scim->remote_surrounding_text);
1320 context_scim->remote_surrounding_text = NULL;
1323 if (context_scim->id != _ic_list->id) {
1324 WSCContextISF * pre = _ic_list;
1325 WSCContextISF * cur = _ic_list->next;
1326 while (cur != NULL) {
1327 if (cur->id == context_scim->id) {
1328 pre->next = cur->next;
1335 _ic_list = _ic_list->next;
1338 if (context_scim->impl) {
1339 // Delete the instance.
1341 // In case the instance send out some helper event,
1342 // and this context has been focused out,
1343 // we need set the focused_ic to this context temporary.
1344 WSCContextISF* old_focused = _focused_ic;
1345 _focused_ic = context_scim;
1346 _focused_ic = old_focused;
1348 if (context_scim == _focused_ic) {
1349 g_info_manager->socket_turn_off ();
1350 g_info_manager->focus_out (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1353 g_info_manager->remove_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1355 if (context_scim->impl) {
1356 delete_ic_impl (context_scim->impl);
1357 context_scim->impl = 0;
1361 if (context_scim == _focused_ic)
1366 isf_wsc_context_focus_in (WSCContextISF *wsc_ctx)
1368 WSCContextISF* context_scim = wsc_ctx;
1372 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
1375 if (_focused_ic == context_scim) {
1376 SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
1379 SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
1380 isf_wsc_context_focus_out (_focused_ic);
1383 if (_change_keyboard_mode_by_focus_move) {
1384 //if h/w keyboard mode, keyboard mode will be changed to s/w mode when the entry get the focus.
1385 LOGD ("Keyboard mode is changed H/W->S/W because of focus_in.");
1386 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_HELPER_MODE);
1389 if (context_scim && context_scim->impl) {
1390 _focused_ic = context_scim;
1392 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1393 context_scim->impl->surrounding_text.clear ();
1394 context_scim->impl->preedit_string.clear ();
1395 context_scim->impl->preedit_attrlist.clear ();
1396 context_scim->impl->commit_string.clear ();
1397 context_scim->impl->preedit_caret = 0;
1398 context_scim->impl->preedit_started = false;
1400 g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1402 set_ic_capabilities (context_scim);
1404 //FIXME: modify the parameter ic->impl->si->get_factory_uuid ()
1405 g_info_manager->focus_in (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1406 if (context_scim->impl->is_on) {
1407 g_info_manager->socket_turn_on ();
1408 // _panel_client.hide_preedit_string (context_scim->id);
1409 // _panel_client.hide_aux_string (context_scim->id);
1410 // _panel_client.hide_lookup_table (context_scim->id);
1412 #if 0 //REMOVE_SCIM_LAUNCHER
1413 context_scim->impl->si->set_layout (wsc_context_input_panel_layout_get (wsc_ctx));
1414 context_scim->impl->si->set_prediction_allow (context_scim->impl->prediction_allow);
1416 if (context_scim->impl->imdata)
1417 context_scim->impl->si->set_imdata ((const char*)context_scim->impl->imdata, context_scim->impl->imdata_size);
1419 LOGD ("set autocapital type : %d, ctx : %p", context_scim->impl->autocapital_type, wsc_ctx);
1420 g_info_manager->set_autocapital_type ((int)context_scim->impl->autocapital_type);
1422 g_info_manager->socket_turn_off ();
1425 g_info_manager->get_active_helper_option (WAYLAND_MODULE_CLIENT_ID, _active_helper_option);
1428 g_info_manager->remoteinput_callback_focus_in ();
1430 context_scim->impl->init_remote_entry_metadata = false;
1431 context_scim->impl->init_remote_surrounding_text = false;
1432 context_scim->impl->block_input_resource = false;
1433 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1438 isf_wsc_context_focus_out (WSCContextISF *wsc_ctx)
1440 WSCContextISF* context_scim = wsc_ctx;
1442 if (!context_scim) return;
1444 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1446 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1447 LOGD ("ctx : %p", wsc_ctx);
1449 if (context_scim->impl->need_commit_preedit) {
1450 _hide_preedit_string (context_scim->id, false);
1452 wsc_context_commit_preedit_string (context_scim);
1453 g_info_manager->socket_reset_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1456 context_scim->impl->cursor_pos = -1;
1457 // if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1458 g_info_manager->focus_out (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1463 g_info_manager->remoteinput_callback_focus_out ();
1465 context_scim->impl->surrounding_text.clear ();
1466 context_scim->impl->preedit_string.clear ();
1467 context_scim->impl->preedit_attrlist.clear ();
1468 context_scim->impl->commit_string.clear ();
1469 context_scim->impl->preedit_caret = 0;
1470 context_scim->impl->preedit_started = false;
1471 context_scim->impl->need_commit_preedit = false;
1473 context_scim->impl->init_remote_entry_metadata = true;
1474 context_scim->impl->init_remote_surrounding_text = true;
1475 context_scim->impl->block_input_resource = true;
1476 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1478 _x_key_event_is_valid = false;
1482 isf_wsc_context_preedit_string_get (WSCContextISF *wsc_ctx, char** str, int *cursor_pos)
1484 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1486 WSCContextISF* context_scim = wsc_ctx;
1488 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1489 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1493 *str = strdup (mbs.c_str ());
1499 //*cursor_pos = context_scim->impl->preedit_caret;
1500 mbs = utf8_wcstombs (
1501 context_scim->impl->preedit_string.substr (0, context_scim->impl->preedit_caret));
1502 *cursor_pos = mbs.length ();
1514 isf_wsc_context_autocapital_type_set (WSCContextISF* wsc_ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1516 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1517 WSCContextISF* context_scim = wsc_ctx;
1519 if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1520 context_scim->impl->autocapital_type = autocapital_type;
1521 if (context_scim == _focused_ic) {
1522 LOGD ("ctx : %p. set autocapital type : %d", wsc_ctx, autocapital_type);
1523 g_info_manager->set_autocapital_type ((int)autocapital_type);
1529 isf_wsc_context_bidi_direction_set (WSCContextISF* wsc_ctx, Ecore_IMF_BiDi_Direction direction)
1531 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1533 WSCContextISF *context_scim = wsc_ctx;
1535 if (context_scim && context_scim->impl) {
1536 if (context_scim->impl->bidi_direction != direction) {
1537 context_scim->impl->bidi_direction = direction;
1539 if (context_scim == _focused_ic) {
1540 LOGD ("ctx : %p, bidi direction : %#x", wsc_ctx, direction);
1541 panel_req_update_bidi_direction (context_scim, direction);
1548 isf_wsc_context_send_surrounding_text (WSCContextISF* wsc_ctx, const char *text, int cursor)
1550 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1552 WSCContextISF *context_scim = wsc_ctx;
1554 if (!context_scim || !context_scim->impl)
1557 char *conv_text = strdup (utf8_wcstombs (context_scim->impl->surrounding_text).c_str ());
1561 if (!context_scim->impl->init_remote_surrounding_text || strcmp (conv_text, text) != 0 || context_scim->impl->cursor_pos != cursor) {
1562 SECURE_LOGD("remote surrounding text : \"%s\"", text);
1563 context_scim->impl->surrounding_text = utf8_mbstowcs (String (text));
1564 context_scim->impl->cursor_pos = cursor;
1567 if (context_scim->input_panel_shown && context_scim->impl->input_resource != INPUT_RESOURCE_REMOTE) {
1569 if (context_scim->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD) {
1570 const unsigned char pw_char[5] = { 0xE2, 0x80, 0xA2, 0x2A, 0x00 }; // • U+2022 * U+002A
1571 if (_text.find_first_not_of((char *)pw_char) != String::npos) {
1572 g_info_manager->remoteinput_callback_surrounding_text (_text, context_scim->impl->cursor_pos);
1576 g_info_manager->remoteinput_callback_surrounding_text (empty, 0);
1580 g_info_manager->remoteinput_callback_surrounding_text (_text, context_scim->impl->cursor_pos);
1582 context_scim->impl->init_remote_surrounding_text = true;
1586 context_scim->impl->init_remote_surrounding_text = true;
1593 isf_wsc_context_send_entry_metadata (WSCContextISF* wsc_ctx, Ecore_IMF_Input_Hints hint,
1594 Ecore_IMF_Input_Panel_Layout layout, int variation,
1595 Ecore_IMF_Autocapital_Type type, int return_key_disabled)
1597 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1599 WSCContextISF *context_scim = wsc_ctx;
1601 if (context_scim && context_scim->impl) {
1602 if (!context_scim->impl->init_remote_entry_metadata || (context_scim->impl->input_hint != hint || context_scim->impl->panel_layout != layout ||
1603 context_scim->impl->variation != variation || context_scim->impl->autocapital_type != type ||
1604 context_scim->impl->return_key_disabled != return_key_disabled)) {
1605 if (context_scim->impl->panel_layout != layout || context_scim->impl->variation != variation) {
1606 if (context_scim->impl->input_resource == INPUT_RESOURCE_REMOTE)
1607 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1610 context_scim->impl->input_hint = hint;
1611 context_scim->impl->panel_layout = layout;
1612 context_scim->impl->variation = variation;
1613 context_scim->impl->autocapital_type = type;
1614 context_scim->impl->return_key_disabled = return_key_disabled;
1617 g_info_manager->remoteinput_callback_entry_metadata (context_scim->impl->input_hint, context_scim->impl->panel_layout,
1618 context_scim->impl->variation, context_scim->impl->autocapital_type, context_scim->impl->return_key_disabled);
1620 context_scim->impl->init_remote_entry_metadata = true;
1623 remote_surrounding_get (wsc_ctx);
1628 #if ENABLE_GRAB_KEYBOARD
1630 bool is_number_key (const char *str)
1632 if (!str) return false;
1634 int result = atoi (str);
1637 if (!strcmp (str, "0"))
1647 isf_wsc_context_filter_key_event (WSCContextISF* wsc_ctx,
1649 uint32_t timestamp, uint32_t keycode, uint32_t symcode,
1651 enum wl_keyboard_key_state state)
1654 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1657 if (!wsc_ctx) return;
1659 KeyEvent key(symcode, wsc_ctx->modifiers);
1661 bool ignore_key = filter_keys (keyname, SCIM_CONFIG_HOTKEYS_FRONTEND_IGNORE_KEY);
1663 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
1664 key.mask = SCIM_KEY_ReleaseMask;
1665 } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1667 /* Hardware input detect code */
1668 if (get_keyboard_mode () == TOOLBAR_HELPER_MODE &&
1670 _support_hw_keyboard_mode &&
1671 strncmp (keyname, "XF86", 4)) {
1672 bool hw_key_detect = false;
1675 if (strcmp (keyname, "Down") &&
1676 strcmp (keyname, "KP_Down") &&
1677 strcmp (keyname, "Up") &&
1678 strcmp (keyname, "KP_Up") &&
1679 strcmp (keyname, "Right") &&
1680 strcmp (keyname, "KP_Right") &&
1681 strcmp (keyname, "Left") &&
1682 strcmp (keyname, "KP_Left") &&
1683 strcmp (keyname, "Return") &&
1684 strcmp (keyname, "Pause") &&
1685 strcmp (keyname, "NoSymbol") &&
1686 !is_number_key (keyname)) {
1687 hw_key_detect = true;
1690 if (key.code != 0x1008ff26 && key.code != 0xFF69) {
1691 /* XF86back, Cancel (Power + Volume down) key */
1692 hw_key_detect = true;
1696 if (hw_key_detect) {
1697 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_KEYBOARD_MODE);
1698 ISF_SAVE_LOG ("Changed keyboard mode from S/W to H/W (code: %x, name: %s)", key.code, keyname);
1699 LOGD ("Hardware keyboard mode, active helper option: %d", _active_helper_option);
1706 if (!_focused_ic || !_focused_ic->impl || !_focused_ic->impl->is_on) {
1709 static uint32 _serial = 0;
1710 g_info_manager->process_key_event (key, ++_serial);
1713 send_wl_key_event (wsc_ctx, key, false);
1718 isf_wsc_context_filter_key_event (WSCContextISF* wsc_ctx,
1720 uint32_t timestamp, const char *keysym,
1721 bool press, uint32_t modifiers,
1722 const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
1724 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1727 if (!wsc_ctx) return;
1730 LOGD("key is NULL");
1734 String _key(keysym);
1737 if (!scim_string_to_key (key, _key)) {
1738 xkb_keysym_t code = xkb_keysym_from_name(keysym, XKB_KEYSYM_NO_FLAGS);
1739 if (code == XKB_KEY_NoSymbol) {
1740 code = xkb_keysym_from_name(keysym, XKB_KEYSYM_CASE_INSENSITIVE);
1744 scim_set_device_info (key, dev_name ? dev_name : "", dev_class, dev_subclass);
1746 bool ignore_key = filter_keys (keysym, SCIM_CONFIG_HOTKEYS_FRONTEND_IGNORE_KEY);
1748 if (modifiers & MOD_SHIFT_MASK)
1749 key.mask |= SCIM_KEY_ShiftMask;
1750 if (modifiers & MOD_ALT_MASK)
1751 key.mask |= SCIM_KEY_AltMask;
1752 if (modifiers & MOD_CONTROL_MASK)
1753 key.mask |= SCIM_KEY_ControlMask;
1755 if (modifiers & MOD_CAPS_MASK)
1756 key.mask |= SCIM_KEY_CapsLockMask;
1757 if (modifiers & MOD_NUM_MASK)
1758 key.mask |= SCIM_KEY_NumLockMask;
1761 key.mask |= SCIM_KEY_ReleaseMask;
1764 /* Hardware input detect code */
1765 if (get_keyboard_mode () == TOOLBAR_HELPER_MODE &&
1767 _support_hw_keyboard_mode &&
1768 strncmp (keysym, "XF86", 4)) {
1769 bool hw_key_detect = false;
1772 if (strcmp (keysym, "Down") &&
1773 strcmp (keysym, "KP_Down") &&
1774 strcmp (keysym, "Up") &&
1775 strcmp (keysym, "KP_Up") &&
1776 strcmp (keysym, "Right") &&
1777 strcmp (keysym, "KP_Right") &&
1778 strcmp (keysym, "Left") &&
1779 strcmp (keysym, "KP_Left") &&
1780 strcmp (keysym, "Return") &&
1781 strcmp (keysym, "KP_Enter") &&
1782 strcmp (keysym, "Pause") &&
1783 strcmp (keysym, "NoSymbol") &&
1784 key.dev_subclass != ECORE_DEVICE_SUBCLASS_REMOCON) {
1785 hw_key_detect = true;
1788 if (key.code != 0x1008ff26 && key.code != 0xFF69) {
1789 /* XF86back, Cancel (Power + Volume down) key */
1790 hw_key_detect = true;
1794 if (hw_key_detect) {
1795 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_KEYBOARD_MODE);
1796 ISF_SAVE_LOG ("Changed keyboard mode from S/W to H/W (code: %x, key : %s)", key.code, keysym);
1797 LOGD ("Hardware keyboard mode, active helper option: %d", _active_helper_option);
1804 if (!_focused_ic || !_focused_ic->impl || !_focused_ic->impl->is_on) {
1806 } else if (g_info_manager->process_key_event (key, serial)){
1811 if (!instance.null ())
1812 instance->process_key_event_done (WAYLAND_MODULE_CLIENT_ID, wsc_ctx->id, key, EINA_FALSE, serial);
1817 wsc_commit_preedit (WSCContextISF* wsc_ctx)
1819 char* surrounding_text;
1821 if (!wsc_ctx || !wsc_ctx->preedit_str ||
1822 strlen (wsc_ctx->preedit_str) == 0)
1825 wl_input_method_context_cursor_position (wsc_ctx->im_ctx,
1828 if (strlen (wsc_ctx->preedit_str) > MAX_PREEDIT_BUFSIZE) {
1829 char str_buffer[MAX_PREEDIT_BUFSIZE];
1831 memcpy (str_buffer, wsc_ctx->preedit_str, MAX_PREEDIT_BUFSIZE - 1);
1832 str_buffer[MAX_PREEDIT_BUFSIZE - 1] = '\0';
1833 char *old_preedit_str = wsc_ctx->preedit_str;
1834 wsc_ctx->preedit_str = (char*)realloc (wsc_ctx->preedit_str, sizeof(char) * MAX_PREEDIT_BUFSIZE);
1835 if (wsc_ctx->preedit_str) {
1836 memcpy (wsc_ctx->preedit_str, str_buffer, strlen(str_buffer));
1837 wsc_ctx->preedit_str[MAX_PREEDIT_BUFSIZE - 1] = '\0';
1839 free (old_preedit_str);
1840 LOGE ("realloc failed");
1845 wl_input_method_context_commit_string (wsc_ctx->im_ctx,
1847 wsc_ctx->preedit_str);
1849 if (wsc_ctx->surrounding_text) {
1850 surrounding_text = insert_text (wsc_ctx->surrounding_text,
1851 wsc_ctx->surrounding_cursor,
1852 wsc_ctx->preedit_str);
1854 free (wsc_ctx->surrounding_text);
1855 wsc_ctx->surrounding_text = surrounding_text;
1856 wsc_ctx->surrounding_cursor += strlen (wsc_ctx->preedit_str);
1857 LOGD ("wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
1859 wsc_ctx->surrounding_text = strdup (wsc_ctx->preedit_str);
1860 wsc_ctx->surrounding_cursor = strlen (wsc_ctx->preedit_str);
1861 LOGD ("wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
1864 if (wsc_ctx->preedit_str)
1865 free (wsc_ctx->preedit_str);
1867 wsc_ctx->preedit_str = strdup ("");
1871 wsc_send_preedit_style (WSCContextISF* wsc_ctx)
1873 if (!wsc_ctx) return;
1874 if (wsc_ctx->impl && wsc_ctx->impl->is_on) {
1875 String mbs = utf8_wcstombs (wsc_ctx->impl->preedit_string);
1877 if (!wsc_ctx->impl->preedit_attrlist.empty ()) {
1878 if (mbs.length ()) {
1879 uint32_t preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT;
1880 int start_index, end_index;
1881 int wlen = wsc_ctx->impl->preedit_string.length ();
1882 AttributeList::const_iterator i;
1883 bool *attrs_flag = new bool [mbs.length ()];
1885 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1886 for (i = wsc_ctx->impl->preedit_attrlist.begin ();
1887 i != wsc_ctx->impl->preedit_attrlist.end (); ++i) {
1888 start_index = i->get_start ();
1889 end_index = i->get_end ();
1890 if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1891 start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1892 end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1893 if (i->get_type () == SCIM_ATTR_DECORATE) {
1894 switch (i->get_value ())
1896 case SCIM_ATTR_DECORATE_UNDERLINE:
1897 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE;
1899 case SCIM_ATTR_DECORATE_REVERSE:
1900 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_SELECTION;
1902 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1903 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT;
1905 case SCIM_ATTR_DECORATE_BGCOLOR1:
1906 case SCIM_ATTR_DECORATE_BGCOLOR2:
1907 case SCIM_ATTR_DECORATE_BGCOLOR3:
1908 case SCIM_ATTR_DECORATE_BGCOLOR4:
1910 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT;
1915 wl_input_method_context_preedit_styling (wsc_ctx->im_ctx,
1919 switch (i->get_value ())
1921 case SCIM_ATTR_DECORATE_UNDERLINE:
1922 case SCIM_ATTR_DECORATE_REVERSE:
1923 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1924 case SCIM_ATTR_DECORATE_BGCOLOR1:
1925 case SCIM_ATTR_DECORATE_BGCOLOR2:
1926 case SCIM_ATTR_DECORATE_BGCOLOR3:
1927 case SCIM_ATTR_DECORATE_BGCOLOR4:
1928 // Record which character has attribute.
1929 for (int pos = start_index; pos < end_index; ++pos)
1930 attrs_flag [pos] = 1;
1935 } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1936 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1937 } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1938 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1942 // Add underline for all characters which don't have attribute.
1943 for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1944 if (!attrs_flag [pos]) {
1945 int begin_pos = pos;
1946 while (pos < mbs.length () && !attrs_flag [pos])
1948 // use REVERSE style as default
1949 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE;
1950 start_index = begin_pos;
1953 wl_input_method_context_preedit_styling (wsc_ctx->im_ctx,
1959 delete [] attrs_flag;
1964 if (wsc_ctx->impl && !wsc_ctx->impl->preedit_attrlist.empty ())
1965 wsc_ctx->impl->preedit_attrlist.clear ();
1970 wsc_send_preedit (WSCContextISF* wsc_ctx, int32_t cursor)
1974 if (!wsc_ctx) return;
1976 uint32_t index = strlen (wsc_ctx->preedit_str);
1978 wsc_send_preedit_style (wsc_ctx);
1983 /* Note : Since the current wayland_immodule implementation does not call
1984 * PREEDIT_CHANGED callback even when preedit_cursor gets updated, for now
1985 * we must update preedit_string also whenever preedit_cursor is updated.
1986 * So the below 2 lines cannot be called separately. */
1987 wl_input_method_context_preedit_cursor (wsc_ctx->im_ctx, index);
1988 wl_input_method_context_preedit_string (wsc_ctx->im_ctx,
1990 wsc_ctx->preedit_str,
1991 utf8_wcstombs (wsc_ctx->impl->commit_string).c_str ());
1994 bool wsc_context_surrounding_get (WSCContextISF *wsc_ctx, char **text, int *cursor_pos)
2000 if (wsc_ctx->surrounding_text)
2001 *text = strdup (wsc_ctx->surrounding_text);
2003 *text = strdup ("");
2007 *cursor_pos = wsc_ctx->surrounding_cursor;
2013 remote_surrounding_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
2014 if (fd_handler == NULL || data == NULL)
2015 return ECORE_CALLBACK_RENEW;
2017 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
2019 int fd = ecore_main_fd_handler_fd_get (fd_handler);
2021 int len = read (fd, buff, sizeof (buff) - 1);
2024 SECURE_LOGD ("remote_surrounding_text : %s, surrounding_cursor : %d", wsc_ctx->remote_surrounding_text, wsc_ctx->surrounding_cursor);
2025 isf_wsc_context_send_surrounding_text (wsc_ctx, wsc_ctx->remote_surrounding_text ? wsc_ctx->remote_surrounding_text : "", wsc_ctx->surrounding_cursor);
2026 } else if (len < 0) {
2030 if (wsc_ctx->remote_surrounding_text == NULL) {
2031 if (len >= (int)sizeof(int)) {
2032 /* Add one byte for terminating NULL character and subtract <int> byte for cursor position */
2033 wsc_ctx->remote_surrounding_text = (char*)malloc (len + 1 - sizeof(int));
2034 if (wsc_ctx->remote_surrounding_text) {
2035 memcpy(&(wsc_ctx->surrounding_cursor), buff, sizeof(int));
2036 memcpy (wsc_ctx->remote_surrounding_text, buff + sizeof(int), len - sizeof(int));
2037 wsc_ctx->remote_surrounding_text[len - sizeof(int)] = '\0';
2038 return ECORE_CALLBACK_RENEW;
2040 LOGE ("malloc failed");
2044 int old_len = strlen (wsc_ctx->remote_surrounding_text);
2045 void * _new = realloc (wsc_ctx->remote_surrounding_text, len + old_len + 1);
2047 wsc_ctx->remote_surrounding_text = (char*)_new;
2048 memcpy (wsc_ctx->remote_surrounding_text + old_len, buff, len);
2049 wsc_ctx->remote_surrounding_text[old_len + len] = '\0';
2050 return ECORE_CALLBACK_RENEW;
2052 LOGE ("realloc failed");
2057 if (wsc_ctx->remote_surrounding_text_fd_read_handler) {
2059 ecore_main_fd_handler_del (wsc_ctx->remote_surrounding_text_fd_read_handler);
2060 wsc_ctx->remote_surrounding_text_fd_read_handler = NULL;
2063 if (wsc_ctx->remote_surrounding_text) {
2064 free (wsc_ctx->remote_surrounding_text);
2065 wsc_ctx->remote_surrounding_text = NULL;
2068 return ECORE_CALLBACK_CANCEL;
2072 remote_surrounding_get (WSCContextISF *wsc_ctx)
2074 if (wsc_ctx && wsc_ctx->im_ctx && wsc_ctx->remote_surrounding_text_fd_read_handler)
2078 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) == -1) {
2079 LOGW ("create pipe failed");
2082 LOGD("%d,%d", filedes[0], filedes[1]);
2083 if (wsc_ctx && wsc_ctx->im_ctx) {
2084 wl_input_method_context_get_surrounding_text (wsc_ctx->im_ctx, UINT_MAX, UINT_MAX, filedes[1]);
2085 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get (NULL);
2087 ecore_wl2_display_flush (wl2_display);
2091 if (wsc_ctx && wsc_ctx->im_ctx) {
2092 if (wsc_ctx->remote_surrounding_text) {
2093 free (wsc_ctx->remote_surrounding_text);
2094 wsc_ctx->remote_surrounding_text = NULL;
2097 wsc_ctx->remote_surrounding_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, remote_surrounding_text_fd_read_func, wsc_ctx, NULL, NULL);
2102 Ecore_IMF_Input_Panel_Layout wsc_context_input_panel_layout_get (WSCContextISF *wsc_ctx)
2104 Ecore_IMF_Input_Panel_Layout layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2109 switch (wsc_ctx->content_purpose) {
2110 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
2111 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED:
2112 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL:
2113 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL:
2114 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
2116 case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
2117 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER;
2119 case WL_TEXT_INPUT_CONTENT_PURPOSE_DATE:
2120 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH;
2122 case WL_TEXT_INPUT_CONTENT_PURPOSE_TIME:
2123 case WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME:
2124 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME;
2126 case WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE:
2127 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
2129 case WL_TEXT_INPUT_CONTENT_PURPOSE_URL:
2130 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
2132 case WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL:
2133 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
2135 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
2136 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS:
2137 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
2139 case WL_TEXT_INPUT_CONTENT_PURPOSE_HEX:
2140 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_HEX;
2142 case WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL:
2143 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL;
2145 case WL_TEXT_INPUT_CONTENT_PURPOSE_IP:
2146 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_IP;
2148 case WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON:
2149 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON;
2151 case WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE:
2152 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE;
2154 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
2155 case WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME:
2156 case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
2158 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2165 int wsc_context_input_panel_layout_variation_get (WSCContextISF *wsc_ctx)
2167 int layout_variation = 0;
2170 return layout_variation;
2172 switch (wsc_ctx->content_purpose) {
2173 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
2174 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_NORMAL;
2176 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED:
2177 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED;
2179 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL:
2180 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL;
2182 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL:
2183 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL;
2185 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
2186 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NORMAL;
2188 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS:
2189 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY;
2191 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
2192 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_NORMAL;
2194 case WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME:
2195 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME;
2197 case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
2198 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME;
2201 layout_variation = 0;
2205 return layout_variation;
2208 Ecore_IMF_Autocapital_Type wsc_context_autocapital_type_get (WSCContextISF *wsc_ctx)
2210 Ecore_IMF_Autocapital_Type autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
2213 return autocapital_type;
2215 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION)
2216 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE;
2217 else if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION)
2218 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_WORD;
2219 else if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
2220 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER;
2222 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
2224 return autocapital_type;
2227 bool wsc_context_input_panel_caps_lock_mode_get (WSCContextISF *wsc_ctx)
2232 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
2238 Ecore_IMF_Input_Panel_Lang wsc_context_input_panel_language_get (WSCContextISF *wsc_ctx)
2240 Ecore_IMF_Input_Panel_Lang language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
2245 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_LATIN)
2246 language = ECORE_IMF_INPUT_PANEL_LANG_ALPHABET;
2248 language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
2253 bool wsc_context_input_panel_password_mode_get (WSCContextISF *wsc_ctx)
2255 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_PASSWORD)
2258 if (wsc_context_input_panel_layout_get (wsc_ctx) == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
2264 Ecore_IMF_Input_Hints wsc_context_input_hint_get (WSCContextISF *wsc_ctx)
2266 int input_hint = ECORE_IMF_INPUT_HINT_NONE;
2269 return (Ecore_IMF_Input_Hints)input_hint;
2271 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA)
2272 input_hint |= ECORE_IMF_INPUT_HINT_SENSITIVE_DATA;
2274 input_hint &= ~ECORE_IMF_INPUT_HINT_SENSITIVE_DATA;
2276 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION)
2277 input_hint |= ECORE_IMF_INPUT_HINT_AUTO_COMPLETE;
2279 input_hint &= ~ECORE_IMF_INPUT_HINT_AUTO_COMPLETE;
2281 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_MULTILINE)
2282 input_hint |= ECORE_IMF_INPUT_HINT_MULTILINE;
2284 input_hint &= ~ECORE_IMF_INPUT_HINT_MULTILINE;
2287 switch (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_MASK)
2289 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE:
2290 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE;
2292 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY:
2293 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY;
2295 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH:
2296 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH;
2298 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR:
2299 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR;
2301 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_NUMBER:
2302 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_NUMBER;
2304 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_SECURITY_CODE:
2305 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_SECURITY_CODE;
2307 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_EMAIL_ADDRESS:
2308 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_EMAIL_ADDRESS;
2310 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_PHONE:
2311 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_PHONE;
2313 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_ADDRESS:
2314 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_ADDRESS;
2316 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_CODE:
2317 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_CODE;
2319 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_ID:
2320 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_ID;
2322 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_NAME:
2323 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_NAME;
2327 return (Ecore_IMF_Input_Hints)input_hint;
2330 Eina_Bool wsc_context_prediction_allow_get (WSCContextISF *wsc_ctx)
2335 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION)
2341 Ecore_IMF_BiDi_Direction wsc_context_bidi_direction_get (WSCContextISF *wsc_ctx)
2343 return (Ecore_IMF_BiDi_Direction)wsc_ctx->bidi_direction;
2346 void wsc_context_delete_surrounding (WSCContextISF *wsc_ctx, int offset, int len)
2348 LOGD ("offset = %d, len = %d", offset, len);
2353 wl_input_method_context_delete_surrounding_text (wsc_ctx->im_ctx, offset, len);
2356 void wsc_context_set_selection (WSCContextISF *wsc_ctx, int start, int end)
2361 wl_input_method_context_selection_region (wsc_ctx->im_ctx, wsc_ctx->serial, start, end);
2364 void wsc_context_commit_string (WSCContextISF *wsc_ctx, const char *str)
2369 if (wsc_ctx->preedit_str) {
2370 free (wsc_ctx->preedit_str);
2371 wsc_ctx->preedit_str = NULL;
2374 wsc_ctx->preedit_str = strdup (str);
2375 wsc_commit_preedit (wsc_ctx);
2378 void wsc_context_commit_preedit_string (WSCContextISF *wsc_ctx)
2380 char* preedit_str = NULL;
2386 isf_wsc_context_preedit_string_get (wsc_ctx, &preedit_str, &cursor_pos);
2388 if (wsc_ctx->preedit_str) {
2389 free (wsc_ctx->preedit_str);
2390 wsc_ctx->preedit_str = NULL;
2393 wsc_ctx->preedit_str = preedit_str;
2394 wsc_commit_preedit (wsc_ctx);
2397 void wsc_context_send_preedit_string (WSCContextISF *wsc_ctx)
2399 char* preedit_str = NULL;
2405 isf_wsc_context_preedit_string_get (wsc_ctx, &preedit_str, &cursor_pos);
2407 if (wsc_ctx->preedit_str) {
2408 free (wsc_ctx->preedit_str);
2409 wsc_ctx->preedit_str = NULL;
2412 wsc_ctx->preedit_str = preedit_str;
2413 wsc_send_preedit (wsc_ctx, cursor_pos);
2416 void wsc_context_send_key (WSCContextISF *wsc_ctx, uint32_t keysym, uint32_t modifiers, uint32_t time, bool press)
2418 if (!wsc_ctx || !wsc_ctx->im_ctx)
2421 wl_input_method_context_keysym (wsc_ctx->im_ctx, wsc_ctx->serial, time,
2422 keysym, press ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, modifiers);
2426 set_ic_capabilities (WSCContextISF *ic)
2428 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2430 if (ic && ic->impl) {
2431 unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2433 if (!_on_the_spot || !ic->impl->use_preedit)
2434 cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2436 //FIXME:add this interface
2437 //_info_manager->update_client_capabilities (cap);
2444 /* Panel Requestion functions. */
2446 panel_req_show_help (WSCContextISF *ic)
2448 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2452 help = String (_("Smart Common Input Method platform ")) +
2453 String (SCIM_VERSION) +
2454 String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2456 if (ic && ic->impl && ic->impl->si) {
2457 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2459 help += utf8_wcstombs (sf->get_name ());
2460 help += String (_(":\n\n"));
2462 help += utf8_wcstombs (sf->get_help ());
2463 help += String (_("\n\n"));
2465 help += utf8_wcstombs (sf->get_credits ());
2468 g_info_manager->socket_show_help (help);
2471 g_info_manager->remoteinput_callback_focus_out ();
2472 LOGD("Remote control button click");
2477 panel_req_update_bidi_direction (WSCContextISF *ic, int direction)
2479 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2482 g_info_manager->update_ise_bidi_direction (WAYLAND_MODULE_CLIENT_ID, direction);
2486 filter_keys (const char *keyname, const char *config_path)
2488 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2492 std::vector <String> keys;
2493 scim_split_string_list (keys, _config->read (String (config_path), String ("")), ',');
2495 for (unsigned int i = 0; i < keys.size (); ++i) {
2496 if (!strcmp (keyname, keys [i].c_str ())) {
2505 panel_initialize (void)
2507 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2508 String display_name;
2510 const char *p = getenv ("DISPLAY");
2511 if (p) display_name = String (p);
2513 g_info_manager->add_client (WAYLAND_MODULE_CLIENT_ID, 2, FRONTEND_CLIENT);
2514 _panel_client_id = WAYLAND_MODULE_CLIENT_ID;
2515 g_info_manager->register_panel_client (_panel_client_id, _panel_client_id);
2516 WSCContextISF* context_scim = _ic_list;
2518 while (context_scim != NULL) {
2519 //FIXME:modify the parameter
2520 g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
2522 context_scim = context_scim->next;
2531 panel_finalize (void)
2533 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2535 g_info_manager->del_client (WAYLAND_MODULE_CLIENT_ID);
2539 panel_slot_update_preedit_caret (int context, int caret)
2542 WSCContextISF* ic = find_ic (context);
2543 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
2545 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
2546 ic->impl->preedit_caret = caret;
2547 if (ic->impl->use_preedit) {
2548 if (!ic->impl->preedit_started) {
2549 if (check_valid_ic (ic))
2550 ic->impl->preedit_started = true;
2552 wsc_send_preedit (ic, caret);
2554 g_info_manager->socket_update_preedit_caret (caret);
2560 panel_slot_process_key_event (int context, const KeyEvent &key)
2562 WSCContextISF* ic = find_ic (context);
2563 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2565 if (!(ic && ic->impl))
2568 if ((_focused_ic != NULL) && (_focused_ic != ic))
2571 send_wl_key_event (ic, key, false);
2575 panel_slot_commit_string (int context, const WideString &wstr, bool remote_mode)
2578 WSCContextISF* ic = find_ic (context);
2579 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2581 if (ic && ic->impl) {
2582 if (_focused_ic != ic)
2586 if (ic->impl->block_input_resource) {
2587 LOGW ("block remote input");
2590 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2592 if (ic->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_URL)
2593 wsc_context_delete_surrounding (ic, INT_MIN/2, INT_MAX);
2595 wsc_context_commit_string (ic, utf8_wcstombs (wstr).c_str ());
2596 ic->impl->need_commit_preedit = false;
2597 ic->impl->preedit_string.clear ();
2599 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
2600 wsc_context_commit_string (ic, utf8_wcstombs (wstr).c_str ());
2606 panel_slot_forward_key_event (int context, const KeyEvent &key, bool remote_mode)
2609 WSCContextISF* ic = find_ic (context);
2610 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2612 if (!(ic && ic->impl))
2615 if ((_focused_ic != NULL) && (_focused_ic != ic))
2619 if (ic->impl->block_input_resource) {
2620 LOGW ("block remote input");
2623 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2625 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
2628 if (key.get_key_string ().length () >= 116)
2631 send_wl_key_event (ic, key, true);
2635 panel_slot_update_preedit_string (int context, const WideString str, const WideString commit, const AttributeList &attrs, int caret, bool remote_mode)
2638 WSCContextISF* ic = find_ic (context);
2639 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
2641 if (ic && ic->impl && _focused_ic == ic) {
2643 if (ic->impl->block_input_resource) {
2644 LOGW ("block remote input");
2647 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2650 if (!ic->impl->is_on)
2651 ic->impl->is_on = true;
2653 if (ic->impl->preedit_string != str || str.length ()) {
2654 ic->impl->preedit_string = str;
2655 ic->impl->preedit_attrlist = attrs;
2656 ic->impl->commit_string = commit;
2658 if (ic->impl->use_preedit) {
2659 if (!ic->impl->preedit_started) {
2660 if (!check_valid_ic (ic))
2663 ic->impl->preedit_started = true;
2664 ic->impl->need_commit_preedit = true;
2666 if (caret >= 0 && caret <= (int)str.length ())
2667 ic->impl->preedit_caret = caret;
2669 ic->impl->preedit_caret = str.length ();
2671 if (ic->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_URL)
2672 wsc_context_delete_surrounding (ic, INT_MIN/2, INT_MAX);
2674 wsc_context_send_preedit_string (ic);
2676 String _str = utf8_wcstombs (str);
2677 g_info_manager->socket_update_preedit_string (_str, attrs, (uint32)caret);
2684 _show_preedit_string (int context)
2687 WSCContextISF* ic = find_ic (context);
2688 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << "\n";
2690 if (ic && ic->impl && _focused_ic == ic) {
2691 if (!ic->impl->is_on)
2692 ic->impl->is_on = true;
2694 if (ic->impl->use_preedit) {
2695 if (!ic->impl->preedit_started) {
2696 if (check_valid_ic (ic)) {
2697 ic->impl->preedit_started = true;
2698 ic->impl->need_commit_preedit = true;
2702 g_info_manager->socket_show_preedit_string ();
2708 _hide_preedit_string (int context, bool update_preedit)
2710 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2712 WSCContextISF* ic = find_ic (context);
2714 if (ic && ic->impl && _focused_ic == ic) {
2715 if (!ic->impl->is_on)
2716 ic->impl->is_on = true;
2719 if (ic->impl->preedit_string.length ()) {
2720 ic->impl->preedit_string = WideString ();
2721 ic->impl->preedit_caret = 0;
2722 ic->impl->preedit_attrlist.clear ();
2725 ic->impl->commit_string = WideString ();
2726 if (ic->impl->use_preedit) {
2727 if (update_preedit && emit) {
2728 if (!check_valid_ic (ic))
2731 if (ic->impl->preedit_started) {
2732 if (check_valid_ic (ic)) {
2733 ic->impl->preedit_started = false;
2734 ic->impl->need_commit_preedit = false;
2737 wsc_context_send_preedit_string (ic);
2739 g_info_manager->socket_hide_preedit_string ();
2747 LOGD ("Initializing Wayland ISF IMModule...");
2749 // Get system language.
2750 _language = scim_get_locale_language (scim_get_current_locale ());
2752 panel_initialize ();
2758 LOGD ("Finalizing Ecore ISF IMModule...");
2760 SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2761 while (_used_ic_impl_list) {
2762 // In case in "shared input method" mode,
2763 // all contexts share only one instance,
2764 // so we need point the reference pointer correctly before finalizing.
2766 if (_used_ic_impl_list->si) {
2767 _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2770 if (_used_ic_impl_list->parent && _used_ic_impl_list->parent->ctx) {
2771 isf_wsc_context_del (_used_ic_impl_list->parent);
2775 delete_all_ic_impl ();
2777 SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2782 _scim_initialized = false;
2786 static uint32_t _keyname_to_keysym (uint32_t keyname, uint32_t *modifiers)
2791 if ((keyname >= '0' && keyname <= '9') ||
2792 (keyname >= 'a' && keyname <= 'z')) {
2794 } else if (keyname >= 'A' && keyname <= 'Z') {
2795 *modifiers |= MOD_SHIFT_MASK;
2796 return keyname + 32;
2801 *modifiers |= MOD_SHIFT_MASK;
2804 *modifiers |= MOD_SHIFT_MASK;
2807 *modifiers |= MOD_SHIFT_MASK;
2810 *modifiers |= MOD_SHIFT_MASK;
2813 *modifiers |= MOD_SHIFT_MASK;
2816 *modifiers |= MOD_SHIFT_MASK;
2819 *modifiers |= MOD_SHIFT_MASK;
2822 *modifiers |= MOD_SHIFT_MASK;
2825 *modifiers |= MOD_SHIFT_MASK;
2828 *modifiers |= MOD_SHIFT_MASK;
2831 *modifiers |= MOD_SHIFT_MASK;
2834 *modifiers |= MOD_SHIFT_MASK;
2837 *modifiers |= MOD_SHIFT_MASK;
2840 *modifiers |= MOD_SHIFT_MASK;
2843 *modifiers |= MOD_SHIFT_MASK;
2846 *modifiers |= MOD_SHIFT_MASK;
2849 *modifiers |= MOD_SHIFT_MASK;
2852 *modifiers |= MOD_SHIFT_MASK;
2855 *modifiers |= MOD_SHIFT_MASK;
2858 *modifiers |= MOD_SHIFT_MASK;
2865 static void send_wl_key_event (WSCContextISF *ic, const KeyEvent &key, bool fake)
2867 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2870 uint32_t modifiers = 0;
2875 modifiers |= MOD_Mod5_MASK;
2878 if (key.is_shift_down ())
2879 modifiers |= MOD_SHIFT_MASK;
2880 if (key.is_alt_down ())
2881 modifiers |= MOD_ALT_MASK;
2882 if (key.is_control_down ())
2883 modifiers |= MOD_CONTROL_MASK;
2885 _keyname_to_keysym (key.code, &modifiers);
2888 wsc_context_send_key (ic, key.code, modifiers, time, key.is_key_press ());
2892 reload_config_callback (const ConfigPointer &config)
2894 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2896 //FIXME:_frontend_hotkey_matcher and _imengine_hotkey_matcher should be added
2897 //_frontend_hotkey_matcher.load_hotkeys (config);
2898 //_imengine_hotkey_matcher.load_hotkeys (config);
2901 scim_string_to_key (key,
2902 config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
2903 String ("Shift+Control+Alt+Lock")));
2905 _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
2906 _valid_key_mask |= SCIM_KEY_ReleaseMask;
2907 // Special treatment for two backslash keys on jp106 keyboard.
2908 _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
2910 _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
2911 //_shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
2912 _change_keyboard_mode_by_focus_move = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_CHANGE_KEYBOARD_MODE_BY_FOCUS_MOVE), _change_keyboard_mode_by_focus_move);
2913 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
2915 // Get keyboard layout setting
2916 // Flush the global config first, in order to load the new configs from disk.
2917 scim_global_config_flush ();
2919 _keyboard_layout = scim_get_default_keyboard_layout ();
2922 class WaylandPanelAgent: public PanelAgentBase
2924 Connection _config_connection;
2927 WaylandPanelAgent ()
2928 : PanelAgentBase ("wayland") {
2930 ~WaylandPanelAgent () {
2933 bool initialize (InfoManager* info_manager, const String& display, bool resident) {
2935 g_info_manager = info_manager;
2936 isf_wsc_context_init ();
2938 if (!_wsc_setup (&_wsc)) {
2942 _config_connection = _config->signal_connect_reload (slot (reload_config_callback));
2944 _wl_im_ctx = new _wl_im;
2946 LOGW ("Can not create wl_im_ctx");
2952 bool valid (void) const {
2957 if (_need_wl_im_init)
2965 _config_connection.disconnect ();
2966 isf_wsc_context_shutdown ();
2971 exit (int id, uint32 contextid) {
2972 LOGD ("client id:%d", id);
2977 update_preedit_caret (int id, uint32 context_id, uint32 caret) {
2978 LOGD ("client id:%d", id);
2979 panel_slot_update_preedit_caret (context_id, caret);
2983 socket_helper_key_event (int id, uint32 context_id, int cmd , KeyEvent& key) {
2984 LOGD ("client id:%d", id);
2986 if (cmd == SCIM_TRANS_CMD_PROCESS_KEY_EVENT)
2987 panel_slot_process_key_event (context_id, key);
2989 panel_slot_forward_key_event (context_id, key, false);
2993 commit_string (int id, uint32 context_id, const WideString& wstr) {
2994 LOGD ("client id:%d", id);
2995 panel_slot_commit_string (context_id, wstr, false);
2999 forward_key_event (int id, uint32 context_id, const KeyEvent &key) {
3000 LOGD ("client id:%d", id);
3001 panel_slot_forward_key_event (context_id, key, false);
3005 remote_commit_string (int id, uint32 context_id, const WideString& wstr) {
3006 LOGD ("client id:%d", id);
3007 panel_slot_commit_string (context_id, wstr, true);
3011 remote_update_preedit_string (int id, uint32 context_id, const WideString str, const WideString commit, const AttributeList &attrs, uint32 caret) {
3012 LOGD ("client id:%d", id);
3013 panel_slot_update_preedit_string (context_id, str, commit, attrs, caret, true);
3017 remote_forward_key_event (int id, uint32 context_id, const KeyEvent &key) {
3018 LOGD ("client id:%d", id);
3019 panel_slot_forward_key_event (context_id, key, true);
3023 remote_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len) {
3024 LOGD ("client id:%d", id);
3027 if (_focused_ic->impl->block_input_resource)
3030 check_input_resource (_focused_ic, INPUT_RESOURCE_REMOTE);
3031 wsc_context_delete_surrounding (_focused_ic, offset, len);
3036 update_ise_input_context (int client, uint32 context, uint32 type, uint32 value) {
3037 if (!_focused_ic || !_focused_ic->im_ctx)
3040 if (type == ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT) {
3041 WSCContextISF* ic = find_ic (context);
3042 if (ic && ic->language) {
3043 wl_input_method_context_language (_focused_ic->im_ctx, _focused_ic->serial, ic->language);
3046 LOGE("language locale query failed : %p %s", ic, (ic ? ic->language : "NULL"));
3047 wl_input_method_context_language (_focused_ic->im_ctx, _focused_ic->serial, "");
3050 wl_input_method_context_input_panel_event (_focused_ic->im_ctx, _focused_ic->serial, type, value);
3054 update_ise_language_locale (int client, uint32 context, String locale) {
3055 if (!_focused_ic || !_focused_ic->im_ctx)
3058 WSCContextISF* ic = find_ic (context);
3059 if (ic && locale.length() > 0) {
3062 ic->language = NULL;
3064 ic->language = strdup(locale.c_str());
3070 request_help (int id, uint32 context_id) {
3071 LOGD ("client id:%d", id);
3072 panel_slot_request_help (context_id);
3077 request_factory_menu (int id, uint32 context_id) {
3078 LOGD ("client id:%d", id);
3079 panel_slot_request_factory_menu (context_id);
3083 change_factory (int id, uint32 context_id, const String& uuid) {
3084 LOGD ("client id:%d", id);
3085 panel_slot_change_factory (context_id, uuid);
3090 reset_keyboard_ise (int id, uint32 context_id) {
3091 LOGD ("client id:%d", id);
3092 panel_slot_reset_keyboard_ise (context_id);
3097 update_keyboard_ise (int id, uint32 context_id) {
3098 LOGD ("client id:%d", id);
3099 panel_slot_update_keyboard_ise (context_id);
3104 show_preedit_string (int id, uint32 context_id) {
3105 LOGD ("client id:%d", id);
3106 _show_preedit_string (context_id);
3110 hide_preedit_string (int id, uint32 context_id) {
3111 LOGD ("client id:%d", id);
3112 _hide_preedit_string (context_id, true);
3116 update_preedit_string (int id, uint32 context_id, WideString preedit, WideString commit, AttributeList& attrs, uint32 caret) {
3117 LOGD ("client id:%d", id);
3118 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
3119 WSCContextISF* ic = find_ic (context_id);
3121 if (ic && ic->impl && _focused_ic == ic) {
3122 if (!ic->impl->is_on)
3123 ic->impl->is_on = true;
3125 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
3127 ic->impl->preedit_string = preedit;
3128 ic->impl->preedit_attrlist = attrs;
3129 ic->impl->commit_string = commit;
3131 if (ic->impl->use_preedit) {
3132 if (!ic->impl->preedit_started) {
3133 if (!check_valid_ic (ic))
3136 ic->impl->preedit_started = true;
3137 ic->impl->need_commit_preedit = true;
3139 if (caret <= preedit.length ())
3140 ic->impl->preedit_caret = caret;
3142 ic->impl->preedit_caret = preedit.length ();
3143 wsc_context_send_preedit_string (ic);
3145 String _str = utf8_wcstombs (preedit);
3146 g_info_manager->socket_update_preedit_string (_str, attrs, (uint32)caret);
3152 recapture_string (int id, uint32 context_id, int offset, int len, WideString preedit, WideString commit, AttributeList& attrs) {
3153 LOGD ("client id:%d", id);
3154 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
3155 WSCContextISF* ic = find_ic (context_id);
3156 String preedit_str = utf8_wcstombs (preedit);
3157 String commit_str = utf8_wcstombs (commit);
3159 if (ic && ic->impl && _focused_ic == ic) {
3160 if (!ic->impl->is_on)
3161 ic->impl->is_on = true;
3163 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
3165 ic->impl->preedit_string = preedit;
3166 ic->impl->preedit_attrlist = attrs;
3167 ic->impl->commit_string = commit;
3169 if (ic->impl->use_preedit) {
3170 if (!ic->impl->preedit_started) {
3171 if (!check_valid_ic (ic))
3174 ic->impl->preedit_started = true;
3175 ic->impl->need_commit_preedit = true;
3177 ic->impl->preedit_caret = preedit.length ();
3179 wl_input_method_context_preedit_cursor (ic->im_ctx, strlen(preedit_str.c_str()));
3180 wsc_send_preedit_style (ic);
3182 wl_input_method_context_recapture_string (ic->im_ctx, ic->serial,
3183 offset, len, preedit_str.c_str(), preedit_str.c_str(), commit_str.c_str());
3185 g_info_manager->socket_recapture_string (offset, len, preedit_str, commit_str, attrs);
3191 surrounding_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
3192 if (fd_handler == NULL || data == NULL)
3193 return ECORE_CALLBACK_RENEW;
3195 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
3197 int fd = ecore_main_fd_handler_fd_get (fd_handler);
3199 return ECORE_CALLBACK_RENEW;
3202 int len = read (fd, buff, sizeof (buff) - 1);
3204 LOGD ("update, wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
3205 g_info_manager->socket_update_surrounding_text (wsc_ctx->surrounding_text ? wsc_ctx->surrounding_text : "", wsc_ctx->surrounding_cursor);
3206 } else if (len < 0) {
3210 if (wsc_ctx->surrounding_text == NULL) {
3211 if (len >= (int)sizeof(int)) {
3212 /* Add one byte for terminating NULL character and subtract <int> byte for cursor position */
3213 wsc_ctx->surrounding_text = (char*)malloc (len + 1 - sizeof(int));
3214 if (wsc_ctx->surrounding_text) {
3215 memcpy(&(wsc_ctx->surrounding_cursor), buff, sizeof(int));
3216 memcpy (wsc_ctx->surrounding_text, buff + sizeof(int), len - sizeof(int));
3217 wsc_ctx->surrounding_text[len - sizeof(int)] = '\0';
3218 return ECORE_CALLBACK_RENEW;
3220 LOGE ("malloc failed");
3224 int old_len = strlen (wsc_ctx->surrounding_text);
3225 void * _new = realloc (wsc_ctx->surrounding_text, len + old_len + 1);
3227 wsc_ctx->surrounding_text = (char*)_new;
3228 memcpy (wsc_ctx->surrounding_text + old_len, buff, len);
3229 wsc_ctx->surrounding_text[old_len + len] = '\0';
3230 return ECORE_CALLBACK_RENEW;
3232 LOGE ("realloc failed");
3237 if (wsc_ctx->surrounding_text_fd_read_handler) {
3239 ecore_main_fd_handler_del (wsc_ctx->surrounding_text_fd_read_handler);
3240 wsc_ctx->surrounding_text_fd_read_handler = NULL;
3243 if (wsc_ctx->surrounding_text) {
3244 free (wsc_ctx->surrounding_text);
3245 wsc_ctx->surrounding_text = NULL;
3248 return ECORE_CALLBACK_RENEW;
3252 socket_helper_get_surrounding_text (int id, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after) {
3253 LOGD ("client id:%d", id);
3256 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) == -1) {
3257 LOGW ("create pipe failed");
3260 LOGD("%d,%d", filedes[0], filedes[1]);
3261 WSCContextISF* ic = find_ic (context_id);
3265 wl_input_method_context_get_surrounding_text (ic->im_ctx, maxlen_before, maxlen_after, filedes[1]);
3267 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get (NULL);
3269 ecore_wl2_display_flush (wl2_display);
3272 if (ic->surrounding_text_fd_read_handler) {
3273 int fd = ecore_main_fd_handler_fd_get (ic->surrounding_text_fd_read_handler);
3275 ecore_main_fd_handler_del (ic->surrounding_text_fd_read_handler);
3276 ic->surrounding_text_fd_read_handler = NULL;
3279 if (ic->surrounding_text) {
3280 free (ic->surrounding_text);
3281 ic->surrounding_text = NULL;
3284 ic->surrounding_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, surrounding_text_fd_read_func, ic, NULL, NULL);
3288 socket_helper_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len) {
3289 LOGD ("client id:%d", id);
3290 //panel_slot_delete_surrounding_text (context_id, offset, len);
3292 check_input_resource (_focused_ic, INPUT_RESOURCE_LOCAL);
3293 wsc_context_delete_surrounding (_focused_ic, offset, len);
3298 socket_helper_set_selection (int id, uint32 context_id, uint32 start, uint32 end) {
3299 LOGD ("client id:%d", id);
3301 wsc_context_set_selection (_focused_ic, start, end);
3305 send_private_command (int id, uint32 context_id, const String& command) {
3306 LOGD ("client id:%d", id);
3307 //panel_slot_send_private_command (context_id, command);
3308 if (_focused_ic && _focused_ic->im_ctx)
3309 wl_input_method_context_private_command (_focused_ic->im_ctx, _focused_ic->serial, command.c_str ());
3313 commit_content (int id, uint32 context_id, const String& content, const String& description, const String& mime_types) {
3314 LOGD ("client id:%d", id);
3315 if (_focused_ic && _focused_ic->im_ctx)
3316 wl_input_method_context_commit_content (_focused_ic->im_ctx, _focused_ic->serial, content.c_str (), description.c_str (), mime_types.c_str ());
3320 hide_helper_ise (int id, uint32 context_id)
3322 LOGD ("client id:%d", id);
3323 WSCContextISF* ic = find_ic (context_id);
3326 wl_input_method_context_hide_input_panel (ic->im_ctx, ic->serial);
3331 selection_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
3332 if (fd_handler == NULL || data == NULL)
3333 return ECORE_CALLBACK_RENEW;
3335 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
3336 int fd = ecore_main_fd_handler_fd_get (fd_handler);
3338 return ECORE_CALLBACK_RENEW;
3341 int len = read (fd, buff, sizeof (buff) - 1);
3344 g_info_manager->socket_update_selection (wsc_ctx->selection_text ? wsc_ctx->selection_text : "");
3345 } else if (len < 0) {
3349 if (wsc_ctx->selection_text == NULL) {
3350 wsc_ctx->selection_text = (char*)malloc (len + 1);
3351 if (wsc_ctx->selection_text) {
3352 memcpy (wsc_ctx->selection_text, buff, len);
3353 wsc_ctx->selection_text[len] = '\0';
3354 return ECORE_CALLBACK_RENEW;
3356 LOGE ("malloc failed");
3359 int old_len = strlen (wsc_ctx->selection_text);
3360 void * _new = realloc (wsc_ctx->selection_text, len + old_len + 1);
3362 wsc_ctx->selection_text = (char*)_new;
3363 memcpy (wsc_ctx->selection_text + old_len, buff, len);
3364 wsc_ctx->selection_text[old_len + len] = '\0';
3365 return ECORE_CALLBACK_RENEW;
3367 LOGE ("realloc failed");
3372 if (wsc_ctx->selection_text_fd_read_handler) {
3374 ecore_main_fd_handler_del (wsc_ctx->selection_text_fd_read_handler);
3375 wsc_ctx->selection_text_fd_read_handler = NULL;
3378 if (wsc_ctx->selection_text) {
3379 free (wsc_ctx->selection_text);
3380 wsc_ctx->selection_text = NULL;
3383 return ECORE_CALLBACK_RENEW;
3387 socket_helper_get_selection (int id, uint32 context_id) {
3388 LOGD ("client id:%d", id);
3391 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) ==-1 ) {
3392 LOGW ("create pipe failed");
3395 LOGD("%d,%d", filedes[0], filedes[1]);
3397 WSCContextISF* ic = find_ic (context_id);
3400 wl_input_method_context_get_selection_text (ic->im_ctx, filedes[1]);
3401 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get (NULL);
3403 ecore_wl2_display_flush (wl2_display);
3406 if (ic->selection_text_fd_read_handler) {
3407 int fd = ecore_main_fd_handler_fd_get (ic->selection_text_fd_read_handler);
3411 ecore_main_fd_handler_del (ic->selection_text_fd_read_handler);
3412 ic->selection_text_fd_read_handler = NULL;
3415 if (ic->selection_text) {
3416 free (ic->selection_text);
3417 ic->selection_text = NULL;
3420 ic->selection_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, selection_text_fd_read_func, ic, NULL, NULL);
3423 void process_key_event_done (int id, uint32 context_id, KeyEvent &key, uint32 ret, uint32 serial) {
3424 LOGD ("client id:%d", id);
3425 WSCContextISF* ic = find_ic (context_id);
3428 #if ENABLE_GRAB_KEYBOARD
3429 if (ret == EINA_FALSE) {
3430 send_wl_key_event (ic, key, false);
3433 wl_input_method_context_filter_key_event_done (ic->im_ctx, serial, ret);
3437 void request_ise_hide (int id, uint32 context_id) {
3438 LOGD ("client id:%d", id);
3439 WSCContextISF* ic = find_ic (context_id);
3442 wl_input_method_context_hide_input_panel (ic->im_ctx, ic->serial);
3446 update_ise_geometry (int id, uint32 context_id, uint32 x, uint32 y, uint32 width, uint32 height) {
3447 LOGD ("client id:%d", id);
3449 if (_focused_ic && _focused_ic->im_ctx) {
3450 wl_input_method_context_update_ise_geometry (_focused_ic->im_ctx, _focused_ic->serial, x, y, width, height);
3454 void helper_candidate_show(int id, uint32 context_id, const String& uuid)
3456 WSCContextISF* ic = find_ic(context_id);
3460 wl_input_method_context_update_candidate_state(ic->im_ctx, 1);
3464 void helper_candidate_hide(int id, uint32 context_id, const String& uuid)
3466 WSCContextISF* ic = find_ic(context_id);
3470 wl_input_method_context_update_candidate_state(ic->im_ctx, 0);
3477 EXAPI void scim_module_init (void)
3482 EXAPI void scim_module_exit (void)
3488 EXAPI void scim_panel_agent_module_init (const scim::ConfigPointer& config)
3494 EXAPI scim::PanelAgentPointer scim_panel_agent_module_get_instance ()
3496 scim::PanelAgentBase* _instance = NULL;
3497 if (instance.null ()) {
3499 _instance = new WaylandPanelAgent ();
3506 instance = _instance;
3513 vi:ts=4:nowrap:expandtab