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 static bool _launch_ise_on_request = false;
216 #define WAYLAND_MODULE_CLIENT_ID (0)
217 #define MAX_PREEDIT_BUFSIZE 4000
219 #define MOD_SHIFT_MASK 0x01
220 #define MOD_CAPS_MASK 0x02
221 #define MOD_CONTROL_MASK 0x04
222 #define MOD_ALT_MASK 0x08
223 #define MOD_NUM_MASK 0x100
224 #define MOD_Mod5_MASK 0x80
226 #define WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_MASK 0xff0000
228 //////////////////////////////wayland_panel_agent_module begin//////////////////////////////////////////////////
230 #define scim_module_init wayland_LTX_scim_module_init
231 #define scim_module_exit wayland_LTX_scim_module_exit
232 #define scim_panel_agent_module_init wayland_LTX_scim_panel_agent_module_init
233 #define scim_panel_agent_module_get_instance wayland_LTX_scim_panel_agent_module_get_instance
235 static struct weescim _wsc = {0};
237 InfoManager* g_info_manager = NULL;
238 static scim::PanelAgentPointer instance;
241 /////////////////////////////////////////////////////////////////////////////
242 // Implementation of Wayland Input Method functions.
243 /////////////////////////////////////////////////////////////////////////////
246 _wsc_im_ctx_reset (void *data, struct wl_input_method_context *im_ctx)
248 WSCContextISF *context_scim = (WSCContextISF*)data;
250 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
251 g_info_manager->socket_reset_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
256 _wsc_im_ctx_content_type (void *data, struct wl_input_method_context *im_ctx, uint32_t hint, uint32_t purpose)
258 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
259 if (!wsc_ctx) return;
261 LOGD ("im_context = %p hint = %04x purpose = %d", im_ctx, hint, purpose);
264 if (wsc_ctx->content_purpose != purpose || !wsc_ctx->layout_initialized) {
265 wsc_ctx->layout_initialized = EINA_TRUE;
266 wsc_ctx->content_purpose = purpose;
267 isf_wsc_context_input_panel_layout_set (wsc_ctx, wsc_context_input_panel_layout_get (wsc_ctx));
270 if (wsc_ctx->content_hint != hint) {
271 uint32_t hint_copy, old_hintbit, new_hintbit;
272 const uint32_t autocap_type = WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION |
273 WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE |
274 WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION;
276 hint_copy = wsc_ctx->content_hint;
277 wsc_ctx->content_hint = hint;
279 // Set prediction allow
280 old_hintbit = hint_copy & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
281 new_hintbit = hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION;
282 if (old_hintbit != new_hintbit || !wsc_ctx->prediction_allow_initialized) {
283 wsc_ctx->prediction_allow_initialized = EINA_TRUE;
284 g_info_manager->set_prediction_allow (WAYLAND_MODULE_CLIENT_ID, wsc_context_prediction_allow_get (wsc_ctx));
287 // Set autocapital type
288 old_hintbit = hint_copy & autocap_type;
289 new_hintbit = hint & autocap_type;
290 if (old_hintbit != new_hintbit || !wsc_ctx->autocapital_type_initialized) {
291 wsc_ctx->autocapital_type_initialized = EINA_TRUE;
292 isf_wsc_context_autocapital_type_set (wsc_ctx, wsc_context_autocapital_type_get (wsc_ctx));
296 old_hintbit = hint_copy & WL_TEXT_INPUT_CONTENT_HINT_LATIN;
297 new_hintbit = hint & WL_TEXT_INPUT_CONTENT_HINT_LATIN;
298 if (old_hintbit != new_hintbit || !wsc_ctx->language_initialized) {
299 wsc_ctx->language_initialized = EINA_TRUE;
300 isf_wsc_context_input_panel_language_set (wsc_ctx, wsc_context_input_panel_language_get (wsc_ctx));
303 isf_wsc_context_input_hint_set (wsc_ctx, wsc_context_input_hint_get (wsc_ctx));
307 isf_wsc_context_send_entry_metadata (wsc_ctx, wsc_context_input_hint_get (wsc_ctx), wsc_context_input_panel_layout_get (wsc_ctx),
308 wsc_context_input_panel_layout_variation_get (wsc_ctx), wsc_context_autocapital_type_get (wsc_ctx), wsc_ctx->return_key_disabled);
313 _wsc_im_ctx_invoke_action (void *data, struct wl_input_method_context *im_ctx, uint32_t button, uint32_t index)
315 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
316 if (!wsc_ctx) return;
318 LOGD ("invoke action. button : %d", button);
320 if (button != BTN_LEFT)
323 wsc_context_send_preedit_string (wsc_ctx);
327 _wsc_im_ctx_commit_state (void *data, struct wl_input_method_context *im_ctx, uint32_t serial)
329 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
330 if (!wsc_ctx) return;
332 wsc_ctx->serial = serial;
334 if (wsc_ctx->language)
335 wl_input_method_context_language (im_ctx, wsc_ctx->serial, wsc_ctx->language);
339 _wsc_im_ctx_preferred_language (void *data, struct wl_input_method_context *im_ctx, const char *language)
341 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
342 if (!wsc_ctx) return;
344 if (language && wsc_ctx->language && !strcmp (language, wsc_ctx->language))
347 if (wsc_ctx->language) {
348 free (wsc_ctx->language);
349 wsc_ctx->language = NULL;
353 wsc_ctx->language = strdup (language);
354 LOGD ("Language changed, new: '%s'", language);
359 _wsc_im_ctx_return_key_type (void *data, struct wl_input_method_context *im_ctx, uint32_t return_key_type)
361 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
363 LOGD ("im_context = %p return key type = %d", im_ctx, return_key_type);
364 if (!wsc_ctx) return;
366 if (wsc_ctx->return_key_type != return_key_type) {
367 wsc_ctx->return_key_type = return_key_type;
368 isf_wsc_context_input_panel_return_key_type_set (wsc_ctx, (Ecore_IMF_Input_Panel_Return_Key_Type)wsc_ctx->return_key_type);
373 _wsc_im_ctx_return_key_disabled (void *data, struct wl_input_method_context *im_ctx, uint32_t disabled)
375 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
376 Eina_Bool return_key_disabled = !!disabled;
378 LOGD ("im_context = %p return key disabled = %d", im_ctx, return_key_disabled);
379 if (!wsc_ctx) return;
381 if (wsc_ctx->return_key_disabled != return_key_disabled) {
382 wsc_ctx->return_key_disabled = return_key_disabled;
383 isf_wsc_context_input_panel_return_key_disabled_set (wsc_ctx, wsc_ctx->return_key_disabled);
385 isf_wsc_context_send_entry_metadata (wsc_ctx, wsc_context_input_hint_get (wsc_ctx), wsc_context_input_panel_layout_get (wsc_ctx),
386 wsc_context_input_panel_layout_variation_get (wsc_ctx), wsc_context_autocapital_type_get (wsc_ctx), wsc_ctx->return_key_disabled);
391 _wsc_im_ctx_input_panel_data (void *data, struct wl_input_method_context *im_ctx, const char *input_panel_data, uint32_t input_panel_data_length)
393 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
394 LOGD ("im_context = %p input panel data = %s len = %d", im_ctx, input_panel_data, input_panel_data_length);
395 if (!wsc_ctx) return;
398 if (wsc_ctx->impl->imdata) {
399 free(wsc_ctx->impl->imdata);
402 wsc_ctx->impl->imdata = calloc(1, input_panel_data_length);
403 if (wsc_ctx->impl->imdata)
404 memcpy(wsc_ctx->impl->imdata, input_panel_data, input_panel_data_length);
406 wsc_ctx->impl->imdata_size = input_panel_data_length;
409 isf_wsc_context_input_panel_imdata_set (wsc_ctx, (void *)input_panel_data, input_panel_data_length);
413 _wsc_im_ctx_bidi_direction (void *data, struct wl_input_method_context *im_ctx, uint32_t bidi_direction)
415 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
417 LOGD ("im_context = %p bidi_direction = %d", im_ctx, bidi_direction);
418 if (!wsc_ctx) return;
420 if (wsc_ctx->bidi_direction != bidi_direction) {
421 wsc_ctx->bidi_direction = bidi_direction;
423 isf_wsc_context_bidi_direction_set (wsc_ctx, (Ecore_IMF_BiDi_Direction)wsc_ctx->bidi_direction);
428 _wsc_im_ctx_cursor_position (void *data, struct wl_input_method_context *im_ctx, uint32_t cursor_pos)
430 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
432 LOGD ("im_context = %p cursor_pos = %d", im_ctx, cursor_pos);
433 if (!wsc_ctx || !wsc_ctx->impl) return;
434 wsc_ctx->impl->cursor_pos = cursor_pos;
435 wsc_ctx->surrounding_cursor = cursor_pos;
436 LOGD ("wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
437 g_info_manager->socket_update_cursor_position (cursor_pos);
440 remote_surrounding_get (wsc_ctx);
444 _wsc_im_ctx_process_input_device_event (void *data, struct wl_input_method_context *im_ctx, uint32_t type, const char *input_data, uint32_t input_data_len)
446 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
448 LOGD("im_context = %p type = %d, data = (%p) %d", im_ctx, type, input_data, input_data_len);
449 if (!wsc_ctx) return;
451 isf_wsc_context_process_input_device_event (wsc_ctx, type, input_data, input_data_len);
455 _wsc_im_ctx_filter_key_event (void *data, struct wl_input_method_context *im_ctx, uint32_t serial, uint32_t time, const char *keyname, uint32_t state, uint32_t modifiers, const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
457 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
458 if (!wsc_ctx) return;
460 #if !(ENABLE_GRAB_KEYBOARD)
461 isf_wsc_context_filter_key_event (wsc_ctx, serial, time, keyname,
462 ((wl_keyboard_key_state)state) == WL_KEYBOARD_KEY_STATE_PRESSED, modifiers, dev_name, dev_class, dev_subclass);
467 _wsc_im_ctx_capital_mode (void *data, struct wl_input_method_context *im_ctx, uint32_t mode)
469 LOGD ("capital mode %d", mode);
470 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
471 if (!wsc_ctx) return;
472 wsc_ctx->caps_mode = mode;
473 isf_wsc_context_input_panel_caps_mode_set (wsc_ctx, mode);
477 _wsc_im_ctx_prediction_hint (void *data, struct wl_input_method_context *im_ctx, const char *prediction_hint)
479 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
481 LOGD ("im_context = %p, prediction hint = %s", im_ctx, prediction_hint);
482 if (!wsc_ctx) return;
484 isf_wsc_context_input_panel_prediction_hint_set (wsc_ctx, prediction_hint);
488 _wsc_im_ctx_mime_type (void *data, struct wl_input_method_context *im_ctx, const char *mime_type)
490 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
492 LOGD ("im_context = %p, mime_type = %s", im_ctx, mime_type);
493 if (!wsc_ctx) return;
496 wsc_ctx->impl->mime_type = String (mime_type);
499 isf_wsc_context_input_panel_mime_type_accept_set (wsc_ctx, mime_type);
503 _wsc_im_ctx_finalized_content (void *data, struct wl_input_method_context *im_ctx, const char *text, uint32_t cursor_pos)
505 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
507 SECURE_LOGD ("im_context = %p, text = %s, cursor_pos = %d", im_ctx, text, cursor_pos);
508 if (!wsc_ctx) return;
510 isf_wsc_context_input_panel_finalize_content (wsc_ctx, text, cursor_pos);
514 _wsc_im_ctx_prediction_hint_data (void *data, struct wl_input_method_context *im_ctx, const char *key, const char * value)
516 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
517 if (!wsc_ctx) return;
519 isf_wsc_context_input_panel_prediction_hint_data_set (wsc_ctx, key, value);
522 static const struct wl_input_method_context_listener wsc_im_context_listener = {
524 _wsc_im_ctx_content_type,
525 _wsc_im_ctx_invoke_action,
526 _wsc_im_ctx_commit_state,
527 _wsc_im_ctx_preferred_language,
528 _wsc_im_ctx_return_key_type,
529 _wsc_im_ctx_return_key_disabled,
530 _wsc_im_ctx_input_panel_data,
531 _wsc_im_ctx_bidi_direction,
532 _wsc_im_ctx_cursor_position,
533 _wsc_im_ctx_process_input_device_event,
534 _wsc_im_ctx_filter_key_event,
535 _wsc_im_ctx_capital_mode,
536 _wsc_im_ctx_prediction_hint,
537 _wsc_im_ctx_mime_type,
538 _wsc_im_ctx_finalized_content,
539 _wsc_im_ctx_prediction_hint_data
542 #if ENABLE_GRAB_KEYBOARD
544 _init_keysym2keycode (WSCContextISF *wsc_ctx)
549 const xkb_keysym_t *syms;
551 if (!wsc_ctx || !wsc_ctx->state)
554 for (i = 0; i < 256; i++) {
556 num_syms = xkb_key_get_syms (wsc_ctx->state, code, &syms);
559 wsc_ctx->_keysym2keycode[syms[0]] = i;
564 _fini_keysym2keycode (WSCContextISF *wsc_ctx)
566 wsc_ctx->_keysym2keycode.clear ();
570 _wsc_im_keyboard_keymap (void *data,
571 struct wl_keyboard *wl_keyboard,
576 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
584 _fini_keysym2keycode (wsc_ctx);
586 if (wsc_ctx->state) {
587 xkb_state_unref (wsc_ctx->state);
588 wsc_ctx->state = NULL;
591 if (wsc_ctx->keymap) {
592 xkb_map_unref (wsc_ctx->keymap);
593 wsc_ctx->keymap = NULL;
596 if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1) {
601 map_str = (char*)mmap (NULL, size, PROT_READ, MAP_SHARED, fd, 0);
602 if (map_str == MAP_FAILED) {
608 xkb_map_new_from_string (wsc_ctx->xkb_context,
610 XKB_KEYMAP_FORMAT_TEXT_V1,
611 (xkb_keymap_compile_flags)0);
613 munmap (map_str, size);
616 if (!wsc_ctx->keymap) {
617 LOGW ("failed to compile keymap");
621 wsc_ctx->state = xkb_state_new (wsc_ctx->keymap);
622 if (!wsc_ctx->state) {
623 LOGW ("failed to create XKB state");
624 xkb_map_unref (wsc_ctx->keymap);
628 wsc_ctx->control_mask =
629 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Control");
631 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Mod1");
632 wsc_ctx->shift_mask =
633 1 << xkb_map_mod_get_index (wsc_ctx->keymap, "Shift");
635 LOGD ("create _keysym2keycode");
636 _init_keysym2keycode (wsc_ctx);
640 _wsc_im_keyboard_key (void *data,
641 struct wl_keyboard *wl_keyboard,
647 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
650 const xkb_keysym_t *syms;
652 char keyname[64] = {0};
653 enum wl_keyboard_key_state state = (wl_keyboard_key_state)state_w;
655 if (!wsc_ctx || !wsc_ctx->state)
659 num_syms = xkb_key_get_syms (wsc_ctx->state, code, &syms);
661 sym = XKB_KEY_NoSymbol;
664 xkb_keysym_get_name (sym, keyname, 64);
667 isf_wsc_context_filter_key_event (wsc_ctx, serial, time, code, sym, keyname,
672 _wsc_im_keyboard_modifiers (void *data,
673 struct wl_keyboard *wl_keyboard,
675 uint32_t mods_depressed,
676 uint32_t mods_latched,
677 uint32_t mods_locked,
680 WSCContextISF *wsc_ctx = (WSCContextISF*)data;
681 if (!wsc_ctx || !wsc_ctx->state)
684 struct wl_input_method_context *context = wsc_ctx->im_ctx;
687 xkb_state_update_mask (wsc_ctx->state, mods_depressed,
688 mods_latched, mods_locked, 0, 0, group);
689 mask = xkb_state_serialize_mods (wsc_ctx->state,
690 (xkb_state_component)(XKB_STATE_DEPRESSED | XKB_STATE_LATCHED));
692 wsc_ctx->modifiers = 0;
693 if (mask & wsc_ctx->control_mask)
694 wsc_ctx->modifiers |= SCIM_KEY_ControlMask;
695 if (mask & wsc_ctx->alt_mask)
696 wsc_ctx->modifiers |= SCIM_KEY_AltMask;
697 if (mask & wsc_ctx->shift_mask)
698 wsc_ctx->modifiers |= SCIM_KEY_ShiftMask;
700 wl_input_method_context_modifiers (context, serial,
701 mods_depressed, mods_depressed,
702 mods_latched, group);
705 static const struct wl_keyboard_listener wsc_im_keyboard_listener = {
706 _wsc_im_keyboard_keymap,
709 _wsc_im_keyboard_key,
710 _wsc_im_keyboard_modifiers
717 if (!_wl_im_ctx || !_wl_im_ctx->wsc || !_wl_im_ctx->wsc->wsc_ctx)
720 WSCContextISF *wsc_ctx = _wl_im_ctx->wsc->wsc_ctx;
722 if (_wl_im_ctx->need_focus_event)
723 isf_wsc_context_focus_out (wsc_ctx);
725 #if ENABLE_GRAB_KEYBOARD
726 if (wsc_ctx->keyboard) {
727 wl_keyboard_destroy (wsc_ctx->keyboard);
728 wsc_ctx->keyboard = NULL;
731 _fini_keysym2keycode (wsc_ctx);
733 if (wsc_ctx->state) {
734 xkb_state_unref (wsc_ctx->state);
735 wsc_ctx->state = NULL;
738 if (wsc_ctx->keymap) {
739 xkb_map_unref (wsc_ctx->keymap);
740 wsc_ctx->keymap = NULL;
743 if (wsc_ctx->xkb_context) {
744 xkb_context_unref (wsc_ctx->xkb_context);
745 wsc_ctx->xkb_context = NULL;
749 if (wsc_ctx->im_ctx) {
750 wl_input_method_context_destroy (wsc_ctx->im_ctx);
751 wsc_ctx->im_ctx = NULL;
754 if (wsc_ctx->preedit_str) {
755 free (wsc_ctx->preedit_str);
756 wsc_ctx->preedit_str = NULL;
759 if (wsc_ctx->surrounding_text) {
760 free (wsc_ctx->surrounding_text);
761 wsc_ctx->surrounding_text = NULL;
764 if (wsc_ctx->remote_surrounding_text) {
765 free (wsc_ctx->remote_surrounding_text);
766 wsc_ctx->remote_surrounding_text = NULL;
769 if (wsc_ctx->language) {
770 free (wsc_ctx->language);
771 wsc_ctx->language = NULL;
774 wsc_ctx->layout_initialized = EINA_FALSE;
775 wsc_ctx->prediction_allow_initialized = EINA_FALSE;
776 wsc_ctx->autocapital_type_initialized = EINA_FALSE;
777 wsc_ctx->language_initialized = EINA_FALSE;
779 if (_resource_check_timer)
780 ecore_timer_del (_resource_check_timer);
781 _resource_check_timer = NULL;
783 isf_wsc_context_del (wsc_ctx);
785 _wl_im_ctx->wsc->wsc_ctx = NULL;
786 _wl_im_ctx->input_method = NULL;
787 _wl_im_ctx->im_ctx = NULL;
788 _wl_im_ctx->need_focus_event = EINA_FALSE;
789 _need_wl_im_init = false;
793 _wsc_im_activate (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx, uint32_t text_input_id, uint32_t focus_in_event)
795 struct weescim *wsc = (weescim*)data;
798 WSCContextISF *wsc_ctx = new WSCContextISF;
803 if (_need_wl_im_init)
806 #if ENABLE_GRAB_KEYBOARD
807 wsc_ctx->xkb_context = xkb_context_new ((xkb_context_flags)0);
808 if (wsc_ctx->xkb_context == NULL) {
809 LOGW ("Failed to create XKB context");
813 wsc_ctx->state = NULL;
814 wsc_ctx->keymap = NULL;
815 wsc_ctx->modifiers = 0;
818 wsc_ctx->id = text_input_id;
819 wsc->wsc_ctx = wsc_ctx;
821 wsc_ctx->surrounding_text = NULL;
822 wsc_ctx->remote_surrounding_text = NULL;
823 wsc_ctx->surrounding_cursor = 0;
824 LOGD ("wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
826 get_language (&wsc_ctx->language);
828 wsc_ctx->preedit_str = strdup ("");
829 wsc_ctx->content_hint = WL_TEXT_INPUT_CONTENT_HINT_NONE;
830 wsc_ctx->content_purpose = WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL;
832 wsc_ctx->im_ctx = im_ctx;
833 wl_input_method_context_add_listener (im_ctx, &wsc_im_context_listener, wsc_ctx);
835 #if ENABLE_GRAB_KEYBOARD
836 wsc_ctx->keyboard = wl_input_method_context_grab_keyboard (im_ctx);
837 if (wsc_ctx->keyboard)
838 wl_keyboard_add_listener (wsc_ctx->keyboard, &wsc_im_keyboard_listener, wsc_ctx);
841 if (wsc_ctx->language)
842 wl_input_method_context_language (im_ctx, wsc_ctx->serial, wsc_ctx->language);
844 isf_wsc_context_add (wsc_ctx);
846 if (focus_in_event) {
847 isf_wsc_context_focus_in (wsc_ctx);
848 _wl_im_ctx->need_focus_event = EINA_TRUE;
853 _wsc_im_deactivate (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx, uint32_t focus_out_event)
855 struct weescim *wsc = (weescim*)data;
856 if (!wsc || !wsc->wsc_ctx) return;
858 /* When the focus_in/input_panel_shutdown event is called,
859 * it is not possible to know the information of wl_input_method to destroy */
860 _wl_im_ctx->wsc = wsc;
861 _wl_im_ctx->input_method = input_method;
862 _wl_im_ctx->im_ctx = im_ctx;
863 _need_wl_im_init = true;
865 if (focus_out_event) {
866 isf_wsc_context_focus_out (wsc->wsc_ctx);
867 _wl_im_ctx->need_focus_event = EINA_FALSE;
870 if (_launch_ise_on_request)
875 _wsc_im_show_input_panel (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
877 struct weescim *wsc = (weescim*)data;
878 if (!wsc || !wsc->wsc_ctx) return;
880 isf_wsc_context_input_panel_show (wsc->wsc_ctx);
881 wsc->wsc_ctx->input_panel_shown = true;
884 remote_surrounding_get (wsc->wsc_ctx);
888 _wsc_im_hide_input_panel (void *data, struct wl_input_method *input_method, struct wl_input_method_context *im_ctx)
890 struct weescim *wsc = (weescim*)data;
891 if (!wsc || !wsc->wsc_ctx) return;
893 isf_wsc_context_input_panel_hide (wsc->wsc_ctx);
894 wsc->wsc_ctx->input_panel_shown = false;
897 static const struct wl_input_method_listener wsc_im_listener = {
900 _wsc_im_show_input_panel,
901 _wsc_im_hide_input_panel
905 _wsc_setup (struct weescim *wsc)
907 Eina_Iterator *globals;
908 struct wl_registry *registry;
909 Ecore_Wl2_Global *global;
911 if (!wsc) return false;
913 Ecore_Wl2_Display *wl2_display = ecore_wl2_display_connect (NULL);
915 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);
1291 ecore_main_fd_handler_del (context_scim->selection_text_fd_read_handler);
1292 context_scim->selection_text_fd_read_handler = NULL;
1295 if (context_scim->selection_text) {
1296 free (context_scim->selection_text);
1297 context_scim->selection_text = NULL;
1300 if (context_scim->surrounding_text_fd_read_handler) {
1301 int fd = ecore_main_fd_handler_fd_get (context_scim->surrounding_text_fd_read_handler);
1304 ecore_main_fd_handler_del (context_scim->surrounding_text_fd_read_handler);
1305 context_scim->surrounding_text_fd_read_handler = NULL;
1308 if (context_scim->remote_surrounding_text_fd_read_handler) {
1309 int fd = ecore_main_fd_handler_fd_get (context_scim->remote_surrounding_text_fd_read_handler);
1312 ecore_main_fd_handler_del (context_scim->remote_surrounding_text_fd_read_handler);
1313 context_scim->remote_surrounding_text_fd_read_handler = NULL;
1316 if (context_scim->surrounding_text) {
1317 free (context_scim->surrounding_text);
1318 context_scim->surrounding_text = NULL;
1321 if (context_scim->remote_surrounding_text) {
1322 free (context_scim->remote_surrounding_text);
1323 context_scim->remote_surrounding_text = NULL;
1326 if (context_scim->id != _ic_list->id) {
1327 WSCContextISF * pre = _ic_list;
1328 WSCContextISF * cur = _ic_list->next;
1329 while (cur != NULL) {
1330 if (cur->id == context_scim->id) {
1331 pre->next = cur->next;
1338 _ic_list = _ic_list->next;
1341 if (context_scim->impl) {
1342 if (context_scim == _focused_ic) {
1343 g_info_manager->socket_turn_off ();
1344 g_info_manager->focus_out (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1347 g_info_manager->remove_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1349 if (context_scim->impl) {
1350 delete_ic_impl (context_scim->impl);
1351 context_scim->impl = 0;
1355 if (context_scim == _focused_ic)
1360 isf_wsc_context_focus_in (WSCContextISF *wsc_ctx)
1362 WSCContextISF* context_scim = wsc_ctx;
1366 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__<< "(" << context_scim->id << ")...\n";
1369 if (_focused_ic == context_scim) {
1370 SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
1373 SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
1374 isf_wsc_context_focus_out (_focused_ic);
1377 if (_change_keyboard_mode_by_focus_move) {
1378 //if h/w keyboard mode, keyboard mode will be changed to s/w mode when the entry get the focus.
1379 LOGD ("Keyboard mode is changed H/W->S/W because of focus_in.");
1380 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_HELPER_MODE);
1383 if (context_scim && context_scim->impl) {
1384 _focused_ic = context_scim;
1386 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
1387 context_scim->impl->surrounding_text.clear ();
1388 context_scim->impl->preedit_string.clear ();
1389 context_scim->impl->preedit_attrlist.clear ();
1390 context_scim->impl->commit_string.clear ();
1391 context_scim->impl->preedit_caret = 0;
1392 context_scim->impl->preedit_started = false;
1394 g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1396 set_ic_capabilities (context_scim);
1398 //FIXME: modify the parameter ic->impl->si->get_factory_uuid ()
1399 g_info_manager->focus_in (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
1400 if (context_scim->impl->is_on) {
1401 g_info_manager->socket_turn_on ();
1402 // _panel_client.hide_preedit_string (context_scim->id);
1403 // _panel_client.hide_aux_string (context_scim->id);
1404 // _panel_client.hide_lookup_table (context_scim->id);
1406 #if 0 //REMOVE_SCIM_LAUNCHER
1407 context_scim->impl->si->set_layout (wsc_context_input_panel_layout_get (wsc_ctx));
1408 context_scim->impl->si->set_prediction_allow (context_scim->impl->prediction_allow);
1410 if (context_scim->impl->imdata)
1411 context_scim->impl->si->set_imdata ((const char*)context_scim->impl->imdata, context_scim->impl->imdata_size);
1413 LOGD ("set autocapital type : %d, ctx : %p", context_scim->impl->autocapital_type, wsc_ctx);
1414 g_info_manager->set_autocapital_type ((int)context_scim->impl->autocapital_type);
1416 g_info_manager->socket_turn_off ();
1419 g_info_manager->get_active_helper_option (WAYLAND_MODULE_CLIENT_ID, _active_helper_option);
1422 g_info_manager->remoteinput_callback_focus_in ();
1424 context_scim->impl->init_remote_entry_metadata = false;
1425 context_scim->impl->init_remote_surrounding_text = false;
1426 context_scim->impl->block_input_resource = false;
1427 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1432 isf_wsc_context_focus_out (WSCContextISF *wsc_ctx)
1434 WSCContextISF* context_scim = wsc_ctx;
1436 if (!context_scim) return;
1438 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "(" << context_scim->id << ")...\n";
1440 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1441 LOGD ("ctx : %p", wsc_ctx);
1443 if (context_scim->impl->need_commit_preedit) {
1444 _hide_preedit_string (context_scim->id, false);
1446 wsc_context_commit_preedit_string (context_scim);
1447 g_info_manager->socket_reset_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1450 context_scim->impl->cursor_pos = -1;
1451 // if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1452 g_info_manager->focus_out (WAYLAND_MODULE_CLIENT_ID, context_scim->id);
1457 g_info_manager->remoteinput_callback_focus_out ();
1459 context_scim->impl->surrounding_text.clear ();
1460 context_scim->impl->preedit_string.clear ();
1461 context_scim->impl->preedit_attrlist.clear ();
1462 context_scim->impl->commit_string.clear ();
1463 context_scim->impl->preedit_caret = 0;
1464 context_scim->impl->preedit_started = false;
1465 context_scim->impl->need_commit_preedit = false;
1467 context_scim->impl->init_remote_entry_metadata = true;
1468 context_scim->impl->init_remote_surrounding_text = true;
1469 context_scim->impl->block_input_resource = true;
1470 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1472 _x_key_event_is_valid = false;
1476 isf_wsc_context_preedit_string_get (WSCContextISF *wsc_ctx, char** str, int *cursor_pos)
1478 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1480 WSCContextISF* context_scim = wsc_ctx;
1482 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1483 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1487 *str = strdup (mbs.c_str ());
1493 //*cursor_pos = context_scim->impl->preedit_caret;
1494 mbs = utf8_wcstombs (
1495 context_scim->impl->preedit_string.substr (0, context_scim->impl->preedit_caret));
1496 *cursor_pos = mbs.length ();
1508 isf_wsc_context_autocapital_type_set (WSCContextISF* wsc_ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1510 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " = " << autocapital_type << "...\n";
1511 WSCContextISF* context_scim = wsc_ctx;
1513 if (context_scim && context_scim->impl && context_scim->impl->autocapital_type != autocapital_type) {
1514 context_scim->impl->autocapital_type = autocapital_type;
1515 if (context_scim == _focused_ic) {
1516 LOGD ("ctx : %p. set autocapital type : %d", wsc_ctx, autocapital_type);
1517 g_info_manager->set_autocapital_type ((int)autocapital_type);
1523 isf_wsc_context_bidi_direction_set (WSCContextISF* wsc_ctx, Ecore_IMF_BiDi_Direction direction)
1525 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1527 WSCContextISF *context_scim = wsc_ctx;
1529 if (context_scim && context_scim->impl) {
1530 if (context_scim->impl->bidi_direction != direction) {
1531 context_scim->impl->bidi_direction = direction;
1533 if (context_scim == _focused_ic) {
1534 LOGD ("ctx : %p, bidi direction : %#x", wsc_ctx, direction);
1535 panel_req_update_bidi_direction (context_scim, direction);
1542 isf_wsc_context_send_surrounding_text (WSCContextISF* wsc_ctx, const char *text, int cursor)
1544 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1546 WSCContextISF *context_scim = wsc_ctx;
1548 if (!context_scim || !context_scim->impl)
1551 char *conv_text = strdup (utf8_wcstombs (context_scim->impl->surrounding_text).c_str ());
1555 if (!context_scim->impl->init_remote_surrounding_text || strcmp (conv_text, text) != 0 || context_scim->impl->cursor_pos != cursor) {
1556 SECURE_LOGD("remote surrounding text : \"%s\"", text);
1557 context_scim->impl->surrounding_text = utf8_mbstowcs (String (text));
1558 context_scim->impl->cursor_pos = cursor;
1561 if (context_scim->input_panel_shown && context_scim->impl->input_resource != INPUT_RESOURCE_REMOTE) {
1563 if (context_scim->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD) {
1564 const unsigned char pw_char[5] = { 0xE2, 0x80, 0xA2, 0x2A, 0x00 }; // • U+2022 * U+002A
1565 if (_text.find_first_not_of((char *)pw_char) != String::npos) {
1566 g_info_manager->remoteinput_callback_surrounding_text (_text, context_scim->impl->cursor_pos);
1570 g_info_manager->remoteinput_callback_surrounding_text (empty, 0);
1574 g_info_manager->remoteinput_callback_surrounding_text (_text, context_scim->impl->cursor_pos);
1576 context_scim->impl->init_remote_surrounding_text = true;
1580 context_scim->impl->init_remote_surrounding_text = true;
1587 isf_wsc_context_send_entry_metadata (WSCContextISF* wsc_ctx, Ecore_IMF_Input_Hints hint,
1588 Ecore_IMF_Input_Panel_Layout layout, int variation,
1589 Ecore_IMF_Autocapital_Type type, int return_key_disabled)
1591 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
1593 WSCContextISF *context_scim = wsc_ctx;
1595 if (context_scim && context_scim->impl) {
1596 if (!context_scim->impl->init_remote_entry_metadata || (context_scim->impl->input_hint != hint || context_scim->impl->panel_layout != layout ||
1597 context_scim->impl->variation != variation || context_scim->impl->autocapital_type != type ||
1598 context_scim->impl->return_key_disabled != return_key_disabled)) {
1599 if (context_scim->impl->panel_layout != layout || context_scim->impl->variation != variation) {
1600 if (context_scim->impl->input_resource == INPUT_RESOURCE_REMOTE)
1601 context_scim->impl->input_resource = INPUT_RESOURCE_NONE;
1604 context_scim->impl->input_hint = hint;
1605 context_scim->impl->panel_layout = layout;
1606 context_scim->impl->variation = variation;
1607 context_scim->impl->autocapital_type = type;
1608 context_scim->impl->return_key_disabled = return_key_disabled;
1611 g_info_manager->remoteinput_callback_entry_metadata (context_scim->impl->input_hint, context_scim->impl->panel_layout,
1612 context_scim->impl->variation, context_scim->impl->autocapital_type, context_scim->impl->return_key_disabled);
1614 context_scim->impl->init_remote_entry_metadata = true;
1617 remote_surrounding_get (wsc_ctx);
1622 #if ENABLE_GRAB_KEYBOARD
1624 bool is_number_key (const char *str)
1626 if (!str) return false;
1628 int result = atoi (str);
1631 if (!strcmp (str, "0"))
1641 isf_wsc_context_filter_key_event (WSCContextISF* wsc_ctx,
1643 uint32_t timestamp, uint32_t keycode, uint32_t symcode,
1645 enum wl_keyboard_key_state state)
1648 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1651 if (!wsc_ctx) return;
1653 KeyEvent key(symcode, wsc_ctx->modifiers);
1655 bool ignore_key = filter_keys (keyname, SCIM_CONFIG_HOTKEYS_FRONTEND_IGNORE_KEY);
1657 if (state == WL_KEYBOARD_KEY_STATE_RELEASED) {
1658 key.mask = SCIM_KEY_ReleaseMask;
1659 } else if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
1661 /* Hardware input detect code */
1662 if (get_keyboard_mode () == TOOLBAR_HELPER_MODE &&
1664 _support_hw_keyboard_mode &&
1665 strncmp (keyname, "XF86", 4)) {
1666 bool hw_key_detect = false;
1669 if (strcmp (keyname, "Down") &&
1670 strcmp (keyname, "KP_Down") &&
1671 strcmp (keyname, "Up") &&
1672 strcmp (keyname, "KP_Up") &&
1673 strcmp (keyname, "Right") &&
1674 strcmp (keyname, "KP_Right") &&
1675 strcmp (keyname, "Left") &&
1676 strcmp (keyname, "KP_Left") &&
1677 strcmp (keyname, "Return") &&
1678 strcmp (keyname, "Pause") &&
1679 strcmp (keyname, "NoSymbol") &&
1680 !is_number_key (keyname)) {
1681 hw_key_detect = true;
1684 if (key.code != 0x1008ff26 && key.code != 0xFF69) {
1685 /* XF86back, Cancel (Power + Volume down) key */
1686 hw_key_detect = true;
1690 if (hw_key_detect) {
1691 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_KEYBOARD_MODE);
1692 ISF_SAVE_LOG ("Changed keyboard mode from S/W to H/W (code: %x, name: %s)", key.code, keyname);
1693 LOGD ("Hardware keyboard mode, active helper option: %d", _active_helper_option);
1700 if (!_focused_ic || !_focused_ic->impl || !_focused_ic->impl->is_on) {
1703 static uint32 _serial = 0;
1704 g_info_manager->process_key_event (key, ++_serial);
1707 send_wl_key_event (wsc_ctx, key, false);
1712 isf_wsc_context_filter_key_event (WSCContextISF* wsc_ctx,
1714 uint32_t timestamp, const char *keysym,
1715 bool press, uint32_t modifiers,
1716 const char *dev_name, uint32_t dev_class, uint32_t dev_subclass)
1718 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
1721 if (!wsc_ctx) return;
1724 LOGD("key is NULL");
1728 String _key(keysym);
1731 if (!scim_string_to_key (key, _key)) {
1732 xkb_keysym_t code = xkb_keysym_from_name(keysym, XKB_KEYSYM_NO_FLAGS);
1733 if (code == XKB_KEY_NoSymbol) {
1734 code = xkb_keysym_from_name(keysym, XKB_KEYSYM_CASE_INSENSITIVE);
1738 scim_set_device_info (key, dev_name ? dev_name : "", dev_class, dev_subclass);
1740 bool ignore_key = filter_keys (keysym, SCIM_CONFIG_HOTKEYS_FRONTEND_IGNORE_KEY);
1742 if (modifiers & MOD_SHIFT_MASK)
1743 key.mask |= SCIM_KEY_ShiftMask;
1744 if (modifiers & MOD_ALT_MASK)
1745 key.mask |= SCIM_KEY_AltMask;
1746 if (modifiers & MOD_CONTROL_MASK)
1747 key.mask |= SCIM_KEY_ControlMask;
1749 if (modifiers & MOD_CAPS_MASK)
1750 key.mask |= SCIM_KEY_CapsLockMask;
1751 if (modifiers & MOD_NUM_MASK)
1752 key.mask |= SCIM_KEY_NumLockMask;
1755 key.mask |= SCIM_KEY_ReleaseMask;
1758 /* Hardware input detect code */
1759 if (get_keyboard_mode () == TOOLBAR_HELPER_MODE &&
1761 _support_hw_keyboard_mode &&
1762 strncmp (keysym, "XF86", 4)) {
1763 bool hw_key_detect = false;
1766 if (strcmp (keysym, "Down") &&
1767 strcmp (keysym, "KP_Down") &&
1768 strcmp (keysym, "Up") &&
1769 strcmp (keysym, "KP_Up") &&
1770 strcmp (keysym, "Right") &&
1771 strcmp (keysym, "KP_Right") &&
1772 strcmp (keysym, "Left") &&
1773 strcmp (keysym, "KP_Left") &&
1774 strcmp (keysym, "Return") &&
1775 strcmp (keysym, "KP_Enter") &&
1776 strcmp (keysym, "Pause") &&
1777 strcmp (keysym, "NoSymbol") &&
1778 key.dev_subclass != ECORE_DEVICE_SUBCLASS_REMOCON) {
1779 hw_key_detect = true;
1782 if (key.code != 0x1008ff26 && key.code != 0xFF69) {
1783 /* XF86back, Cancel (Power + Volume down) key */
1784 hw_key_detect = true;
1788 if (hw_key_detect) {
1789 isf_wsc_context_set_keyboard_mode (wsc_ctx, TOOLBAR_KEYBOARD_MODE);
1790 ISF_SAVE_LOG ("Changed keyboard mode from S/W to H/W (code: %x, key : %s)", key.code, keysym);
1791 LOGD ("Hardware keyboard mode, active helper option: %d", _active_helper_option);
1798 if (!_focused_ic || !_focused_ic->impl || !_focused_ic->impl->is_on) {
1800 } else if (g_info_manager->process_key_event (key, serial)){
1805 if (!instance.null ())
1806 instance->process_key_event_done (WAYLAND_MODULE_CLIENT_ID, wsc_ctx->id, key, EINA_FALSE, serial);
1811 wsc_commit_preedit (WSCContextISF* wsc_ctx)
1813 char* surrounding_text;
1815 if (!wsc_ctx || !wsc_ctx->preedit_str ||
1816 strlen (wsc_ctx->preedit_str) == 0)
1819 wl_input_method_context_cursor_position (wsc_ctx->im_ctx,
1822 if (strlen (wsc_ctx->preedit_str) > MAX_PREEDIT_BUFSIZE) {
1823 char str_buffer[MAX_PREEDIT_BUFSIZE];
1825 memcpy (str_buffer, wsc_ctx->preedit_str, MAX_PREEDIT_BUFSIZE - 1);
1826 str_buffer[MAX_PREEDIT_BUFSIZE - 1] = '\0';
1827 char *old_preedit_str = wsc_ctx->preedit_str;
1828 wsc_ctx->preedit_str = (char*)realloc (wsc_ctx->preedit_str, sizeof(char) * MAX_PREEDIT_BUFSIZE);
1829 if (wsc_ctx->preedit_str) {
1830 memcpy (wsc_ctx->preedit_str, str_buffer, strlen(str_buffer));
1831 wsc_ctx->preedit_str[MAX_PREEDIT_BUFSIZE - 1] = '\0';
1833 free (old_preedit_str);
1834 LOGE ("realloc failed");
1839 wl_input_method_context_commit_string (wsc_ctx->im_ctx,
1841 wsc_ctx->preedit_str);
1843 if (wsc_ctx->surrounding_text) {
1844 surrounding_text = insert_text (wsc_ctx->surrounding_text,
1845 wsc_ctx->surrounding_cursor,
1846 wsc_ctx->preedit_str);
1848 free (wsc_ctx->surrounding_text);
1849 wsc_ctx->surrounding_text = surrounding_text;
1850 wsc_ctx->surrounding_cursor += strlen (wsc_ctx->preedit_str);
1851 LOGD ("wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
1853 wsc_ctx->surrounding_text = strdup (wsc_ctx->preedit_str);
1854 wsc_ctx->surrounding_cursor = strlen (wsc_ctx->preedit_str);
1855 LOGD ("wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
1858 if (wsc_ctx->preedit_str)
1859 free (wsc_ctx->preedit_str);
1861 wsc_ctx->preedit_str = strdup ("");
1865 wsc_send_preedit_style (WSCContextISF* wsc_ctx)
1867 if (!wsc_ctx) return;
1868 if (wsc_ctx->impl && wsc_ctx->impl->is_on) {
1869 String mbs = utf8_wcstombs (wsc_ctx->impl->preedit_string);
1871 if (!wsc_ctx->impl->preedit_attrlist.empty ()) {
1872 if (mbs.length ()) {
1873 uint32_t preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT;
1874 int start_index, end_index;
1875 int wlen = wsc_ctx->impl->preedit_string.length ();
1876 AttributeList::const_iterator i;
1877 bool *attrs_flag = new bool [mbs.length ()];
1879 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1880 for (i = wsc_ctx->impl->preedit_attrlist.begin ();
1881 i != wsc_ctx->impl->preedit_attrlist.end (); ++i) {
1882 start_index = i->get_start ();
1883 end_index = i->get_end ();
1884 if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1885 start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1886 end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1887 if (i->get_type () == SCIM_ATTR_DECORATE) {
1888 switch (i->get_value ())
1890 case SCIM_ATTR_DECORATE_UNDERLINE:
1891 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE;
1893 case SCIM_ATTR_DECORATE_REVERSE:
1894 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_REVERSE;
1896 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1897 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_HIGHLIGHT;
1899 case SCIM_ATTR_DECORATE_BGCOLOR1:
1900 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR1;
1902 case SCIM_ATTR_DECORATE_BGCOLOR2:
1903 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR2;
1905 case SCIM_ATTR_DECORATE_BGCOLOR3:
1906 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR3;
1908 case SCIM_ATTR_DECORATE_BGCOLOR4:
1909 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_BGCOLOR4;
1912 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_DEFAULT;
1917 wl_input_method_context_preedit_styling (wsc_ctx->im_ctx,
1921 switch (i->get_value ())
1923 case SCIM_ATTR_DECORATE_UNDERLINE:
1924 case SCIM_ATTR_DECORATE_REVERSE:
1925 case SCIM_ATTR_DECORATE_HIGHLIGHT:
1926 case SCIM_ATTR_DECORATE_BGCOLOR1:
1927 case SCIM_ATTR_DECORATE_BGCOLOR2:
1928 case SCIM_ATTR_DECORATE_BGCOLOR3:
1929 case SCIM_ATTR_DECORATE_BGCOLOR4:
1930 // Record which character has attribute.
1931 for (int pos = start_index; pos < end_index; ++pos)
1932 attrs_flag [pos] = 1;
1937 } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1938 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1939 } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1940 SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1944 // Add underline for all characters which don't have attribute.
1945 for (unsigned int pos = 0; pos < mbs.length (); ++pos) {
1946 if (!attrs_flag [pos]) {
1947 int begin_pos = pos;
1948 while (pos < mbs.length () && !attrs_flag [pos])
1950 // use REVERSE style as default
1951 preedit_style = WL_TEXT_INPUT_PREEDIT_STYLE_UNDERLINE;
1952 start_index = begin_pos;
1955 wl_input_method_context_preedit_styling (wsc_ctx->im_ctx,
1961 delete [] attrs_flag;
1966 if (wsc_ctx->impl && !wsc_ctx->impl->preedit_attrlist.empty ())
1967 wsc_ctx->impl->preedit_attrlist.clear ();
1972 wsc_send_preedit (WSCContextISF* wsc_ctx, int32_t cursor)
1976 if (!wsc_ctx) return;
1978 uint32_t index = strlen (wsc_ctx->preedit_str);
1983 /* Note : Since the current wayland_immodule implementation does not call
1984 * PREEDIT_CHANGED callback even when preedit_cursor or preedit_style gets updated, for now
1985 * we must update preedit_string also whenever preedit_cursor or preedit_style is updated.
1986 * So the below 3 lines cannot be called separately. */
1987 wsc_send_preedit_style (wsc_ctx);
1988 wl_input_method_context_preedit_cursor (wsc_ctx->im_ctx, index);
1989 wl_input_method_context_preedit_string (wsc_ctx->im_ctx,
1991 wsc_ctx->preedit_str,
1992 utf8_wcstombs (wsc_ctx->impl->commit_string).c_str ());
1995 bool wsc_context_surrounding_get (WSCContextISF *wsc_ctx, char **text, int *cursor_pos)
2001 if (wsc_ctx->surrounding_text)
2002 *text = strdup (wsc_ctx->surrounding_text);
2004 *text = strdup ("");
2008 *cursor_pos = wsc_ctx->surrounding_cursor;
2014 remote_surrounding_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
2015 if (fd_handler == NULL || data == NULL)
2016 return ECORE_CALLBACK_RENEW;
2018 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
2020 int fd = ecore_main_fd_handler_fd_get (fd_handler);
2022 return ECORE_CALLBACK_RENEW;
2025 int len = read (fd, buff, sizeof (buff) - 1);
2028 SECURE_LOGD ("remote_surrounding_text : %s, surrounding_cursor : %d", wsc_ctx->remote_surrounding_text, wsc_ctx->surrounding_cursor);
2029 isf_wsc_context_send_surrounding_text (wsc_ctx, wsc_ctx->remote_surrounding_text ? wsc_ctx->remote_surrounding_text : "", wsc_ctx->surrounding_cursor);
2030 } else if (len < 0) {
2034 if (wsc_ctx->remote_surrounding_text == NULL) {
2035 if (len >= (int)sizeof(int)) {
2036 /* Add one byte for terminating NULL character and subtract <int> byte for cursor position */
2037 wsc_ctx->remote_surrounding_text = (char*)malloc (len + 1 - sizeof(int));
2038 if (wsc_ctx->remote_surrounding_text) {
2039 memcpy(&(wsc_ctx->surrounding_cursor), buff, sizeof(int));
2040 memcpy (wsc_ctx->remote_surrounding_text, buff + sizeof(int), len - sizeof(int));
2041 wsc_ctx->remote_surrounding_text[len - sizeof(int)] = '\0';
2042 return ECORE_CALLBACK_RENEW;
2044 LOGE ("malloc failed");
2048 int old_len = strlen (wsc_ctx->remote_surrounding_text);
2049 void * _new = realloc (wsc_ctx->remote_surrounding_text, len + old_len + 1);
2051 wsc_ctx->remote_surrounding_text = (char*)_new;
2052 memcpy (wsc_ctx->remote_surrounding_text + old_len, buff, len);
2053 wsc_ctx->remote_surrounding_text[old_len + len] = '\0';
2054 return ECORE_CALLBACK_RENEW;
2056 LOGE ("realloc failed");
2061 if (wsc_ctx->remote_surrounding_text_fd_read_handler) {
2063 ecore_main_fd_handler_del (wsc_ctx->remote_surrounding_text_fd_read_handler);
2064 wsc_ctx->remote_surrounding_text_fd_read_handler = NULL;
2067 if (wsc_ctx->remote_surrounding_text) {
2068 free (wsc_ctx->remote_surrounding_text);
2069 wsc_ctx->remote_surrounding_text = NULL;
2072 return ECORE_CALLBACK_CANCEL;
2076 remote_surrounding_get (WSCContextISF *wsc_ctx)
2078 if (wsc_ctx && wsc_ctx->im_ctx && wsc_ctx->remote_surrounding_text_fd_read_handler)
2082 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) == -1) {
2083 LOGW ("create pipe failed");
2086 LOGD("%d,%d", filedes[0], filedes[1]);
2087 if (wsc_ctx && wsc_ctx->im_ctx) {
2088 wl_input_method_context_get_surrounding_text (wsc_ctx->im_ctx, UINT_MAX, UINT_MAX, filedes[1]);
2089 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get (NULL);
2091 ecore_wl2_display_flush (wl2_display);
2095 if (wsc_ctx && wsc_ctx->im_ctx) {
2096 if (wsc_ctx->remote_surrounding_text) {
2097 free (wsc_ctx->remote_surrounding_text);
2098 wsc_ctx->remote_surrounding_text = NULL;
2101 wsc_ctx->remote_surrounding_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, remote_surrounding_text_fd_read_func, wsc_ctx, NULL, NULL);
2106 Ecore_IMF_Input_Panel_Layout wsc_context_input_panel_layout_get (WSCContextISF *wsc_ctx)
2108 Ecore_IMF_Input_Panel_Layout layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2113 switch (wsc_ctx->content_purpose) {
2114 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
2115 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED:
2116 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL:
2117 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL:
2118 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY;
2120 case WL_TEXT_INPUT_CONTENT_PURPOSE_NUMBER:
2121 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBER;
2123 case WL_TEXT_INPUT_CONTENT_PURPOSE_DATE:
2124 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_MONTH;
2126 case WL_TEXT_INPUT_CONTENT_PURPOSE_TIME:
2127 case WL_TEXT_INPUT_CONTENT_PURPOSE_DATETIME:
2128 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_DATETIME;
2130 case WL_TEXT_INPUT_CONTENT_PURPOSE_PHONE:
2131 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PHONENUMBER;
2133 case WL_TEXT_INPUT_CONTENT_PURPOSE_URL:
2134 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_URL;
2136 case WL_TEXT_INPUT_CONTENT_PURPOSE_EMAIL:
2137 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMAIL;
2139 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
2140 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS:
2141 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD;
2143 case WL_TEXT_INPUT_CONTENT_PURPOSE_HEX:
2144 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_HEX;
2146 case WL_TEXT_INPUT_CONTENT_PURPOSE_TERMINAL:
2147 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_TERMINAL;
2149 case WL_TEXT_INPUT_CONTENT_PURPOSE_IP:
2150 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_IP;
2152 case WL_TEXT_INPUT_CONTENT_PURPOSE_EMOTICON:
2153 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_EMOTICON;
2155 case WL_TEXT_INPUT_CONTENT_PURPOSE_VOICE:
2156 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_VOICE;
2158 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
2159 case WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME:
2160 case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
2162 layout = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL;
2169 int wsc_context_input_panel_layout_variation_get (WSCContextISF *wsc_ctx)
2171 int layout_variation = 0;
2174 return layout_variation;
2176 switch (wsc_ctx->content_purpose) {
2177 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS:
2178 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_NORMAL;
2180 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNED:
2181 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED;
2183 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_DECIMAL:
2184 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_DECIMAL;
2186 case WL_TEXT_INPUT_CONTENT_PURPOSE_DIGITS_SIGNEDDECIMAL:
2187 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NUMBERONLY_VARIATION_SIGNED_AND_DECIMAL;
2189 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD:
2190 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NORMAL;
2192 case WL_TEXT_INPUT_CONTENT_PURPOSE_PASSWORD_DIGITS:
2193 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD_VARIATION_NUMBERONLY;
2195 case WL_TEXT_INPUT_CONTENT_PURPOSE_NORMAL:
2196 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_NORMAL;
2198 case WL_TEXT_INPUT_CONTENT_PURPOSE_FILENAME:
2199 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_FILENAME;
2201 case WL_TEXT_INPUT_CONTENT_PURPOSE_NAME:
2202 layout_variation = ECORE_IMF_INPUT_PANEL_LAYOUT_NORMAL_VARIATION_PERSON_NAME;
2205 layout_variation = 0;
2209 return layout_variation;
2212 Ecore_IMF_Autocapital_Type wsc_context_autocapital_type_get (WSCContextISF *wsc_ctx)
2214 Ecore_IMF_Autocapital_Type autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
2217 return autocapital_type;
2219 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_CAPITALIZATION)
2220 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_SENTENCE;
2221 else if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_WORD_CAPITALIZATION)
2222 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_WORD;
2223 else if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
2224 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_ALLCHARACTER;
2226 autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
2228 return autocapital_type;
2231 bool wsc_context_input_panel_caps_lock_mode_get (WSCContextISF *wsc_ctx)
2236 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_UPPERCASE)
2242 Ecore_IMF_Input_Panel_Lang wsc_context_input_panel_language_get (WSCContextISF *wsc_ctx)
2244 Ecore_IMF_Input_Panel_Lang language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
2249 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_LATIN)
2250 language = ECORE_IMF_INPUT_PANEL_LANG_ALPHABET;
2252 language = ECORE_IMF_INPUT_PANEL_LANG_AUTOMATIC;
2257 bool wsc_context_input_panel_password_mode_get (WSCContextISF *wsc_ctx)
2259 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_PASSWORD)
2262 if (wsc_context_input_panel_layout_get (wsc_ctx) == ECORE_IMF_INPUT_PANEL_LAYOUT_PASSWORD)
2268 Ecore_IMF_Input_Hints wsc_context_input_hint_get (WSCContextISF *wsc_ctx)
2270 int input_hint = ECORE_IMF_INPUT_HINT_NONE;
2273 return (Ecore_IMF_Input_Hints)input_hint;
2275 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_SENSITIVE_DATA)
2276 input_hint |= ECORE_IMF_INPUT_HINT_SENSITIVE_DATA;
2278 input_hint &= ~ECORE_IMF_INPUT_HINT_SENSITIVE_DATA;
2280 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION)
2281 input_hint |= ECORE_IMF_INPUT_HINT_AUTO_COMPLETE;
2283 input_hint &= ~ECORE_IMF_INPUT_HINT_AUTO_COMPLETE;
2285 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_MULTILINE)
2286 input_hint |= ECORE_IMF_INPUT_HINT_MULTILINE;
2288 input_hint &= ~ECORE_IMF_INPUT_HINT_MULTILINE;
2291 switch (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_MASK)
2293 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE:
2294 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DATE;
2296 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY:
2297 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_DAY;
2299 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH:
2300 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_MONTH;
2302 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR:
2303 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_EXPIRATION_YEAR;
2305 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_CREDIT_CARD_NUMBER:
2306 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_CREDIT_CARD_NUMBER;
2308 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_EMAIL_ADDRESS:
2309 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_EMAIL_ADDRESS;
2311 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_PHONE:
2312 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_PHONE;
2314 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_ADDRESS:
2315 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_ADDRESS;
2317 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_POSTAL_CODE:
2318 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_POSTAL_CODE;
2320 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_ID:
2321 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_ID;
2323 case WL_TEXT_INPUT_CONTENT_HINT_AUTOFILL_NAME:
2324 input_hint |= ECORE_IMF_INPUT_HINT_AUTOFILL_NAME;
2328 return (Ecore_IMF_Input_Hints)input_hint;
2331 Eina_Bool wsc_context_prediction_allow_get (WSCContextISF *wsc_ctx)
2336 if (wsc_ctx->content_hint & WL_TEXT_INPUT_CONTENT_HINT_AUTO_COMPLETION)
2342 Ecore_IMF_BiDi_Direction wsc_context_bidi_direction_get (WSCContextISF *wsc_ctx)
2344 return (Ecore_IMF_BiDi_Direction)wsc_ctx->bidi_direction;
2347 void wsc_context_delete_surrounding (WSCContextISF *wsc_ctx, int offset, int len)
2349 LOGD ("offset = %d, len = %d", offset, len);
2354 wl_input_method_context_delete_surrounding_text (wsc_ctx->im_ctx, offset, len);
2357 void wsc_context_set_selection (WSCContextISF *wsc_ctx, int start, int end)
2362 wl_input_method_context_selection_region (wsc_ctx->im_ctx, wsc_ctx->serial, start, end);
2365 void wsc_context_commit_string (WSCContextISF *wsc_ctx, const char *str)
2370 if (wsc_ctx->preedit_str) {
2371 free (wsc_ctx->preedit_str);
2372 wsc_ctx->preedit_str = NULL;
2375 wsc_ctx->preedit_str = strdup (str);
2376 wsc_commit_preedit (wsc_ctx);
2379 void wsc_context_commit_preedit_string (WSCContextISF *wsc_ctx)
2381 char* preedit_str = NULL;
2387 isf_wsc_context_preedit_string_get (wsc_ctx, &preedit_str, &cursor_pos);
2389 if (wsc_ctx->preedit_str) {
2390 free (wsc_ctx->preedit_str);
2391 wsc_ctx->preedit_str = NULL;
2394 wsc_ctx->preedit_str = preedit_str;
2395 wsc_commit_preedit (wsc_ctx);
2398 void wsc_context_send_preedit_string (WSCContextISF *wsc_ctx)
2400 char* preedit_str = NULL;
2406 isf_wsc_context_preedit_string_get (wsc_ctx, &preedit_str, &cursor_pos);
2408 if (wsc_ctx->preedit_str) {
2409 free (wsc_ctx->preedit_str);
2410 wsc_ctx->preedit_str = NULL;
2413 wsc_ctx->preedit_str = preedit_str;
2414 wsc_send_preedit (wsc_ctx, cursor_pos);
2417 void wsc_context_send_key (WSCContextISF *wsc_ctx, uint32_t keysym, uint32_t modifiers, uint32_t time, bool press)
2419 if (!wsc_ctx || !wsc_ctx->im_ctx)
2422 wl_input_method_context_keysym (wsc_ctx->im_ctx, wsc_ctx->serial, time,
2423 keysym, press ? WL_KEYBOARD_KEY_STATE_PRESSED : WL_KEYBOARD_KEY_STATE_RELEASED, modifiers);
2427 set_ic_capabilities (WSCContextISF *ic)
2429 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2431 if (ic && ic->impl) {
2432 unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
2434 if (!_on_the_spot || !ic->impl->use_preedit)
2435 cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
2437 //FIXME:add this interface
2438 //_info_manager->update_client_capabilities (cap);
2445 /* Panel Requestion functions. */
2447 panel_req_show_help (WSCContextISF *ic)
2449 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2453 help = String (_("Smart Common Input Method platform ")) +
2454 String (SCIM_VERSION) +
2455 String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
2457 if (ic && ic->impl && ic->impl->si) {
2458 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
2460 help += utf8_wcstombs (sf->get_name ());
2461 help += String (_(":\n\n"));
2463 help += utf8_wcstombs (sf->get_help ());
2464 help += String (_("\n\n"));
2466 help += utf8_wcstombs (sf->get_credits ());
2469 g_info_manager->socket_show_help (help);
2472 g_info_manager->remoteinput_callback_focus_out ();
2473 LOGD("Remote control button click");
2478 panel_req_update_bidi_direction (WSCContextISF *ic, int direction)
2480 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << "...\n";
2483 g_info_manager->update_ise_bidi_direction (WAYLAND_MODULE_CLIENT_ID, direction);
2487 filter_keys (const char *keyname, const char *config_path)
2489 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2493 std::vector <String> keys;
2494 scim_split_string_list (keys, _config->read (String (config_path), String ("")), ',');
2496 for (unsigned int i = 0; i < keys.size (); ++i) {
2497 if (!strcmp (keyname, keys [i].c_str ())) {
2506 panel_initialize (void)
2508 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2509 String display_name;
2511 const char *p = getenv ("DISPLAY");
2512 if (p) display_name = String (p);
2514 g_info_manager->add_client (WAYLAND_MODULE_CLIENT_ID, 2, FRONTEND_CLIENT);
2515 _panel_client_id = WAYLAND_MODULE_CLIENT_ID;
2516 g_info_manager->register_panel_client (_panel_client_id, _panel_client_id);
2517 WSCContextISF* context_scim = _ic_list;
2518 _launch_ise_on_request = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_LAUNCH_ISE_ON_REQUEST), false);
2520 while (context_scim != NULL) {
2521 //FIXME:modify the parameter
2522 g_info_manager->register_input_context (WAYLAND_MODULE_CLIENT_ID, context_scim->id, "");
2524 context_scim = context_scim->next;
2533 panel_finalize (void)
2535 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2537 g_info_manager->del_client (WAYLAND_MODULE_CLIENT_ID);
2541 panel_slot_update_preedit_caret (int context, int caret)
2544 WSCContextISF* ic = find_ic (context);
2545 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
2547 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
2548 ic->impl->preedit_caret = caret;
2549 if (ic->impl->use_preedit) {
2550 if (!ic->impl->preedit_started) {
2551 if (check_valid_ic (ic))
2552 ic->impl->preedit_started = true;
2554 wsc_send_preedit (ic, caret);
2556 g_info_manager->socket_update_preedit_caret (caret);
2562 panel_slot_process_key_event (int context, const KeyEvent &key)
2564 WSCContextISF* ic = find_ic (context);
2565 SCIM_DEBUG_FRONTEND(1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2567 if (!(ic && ic->impl))
2570 if ((_focused_ic != NULL) && (_focused_ic != ic))
2573 send_wl_key_event (ic, key, false);
2577 panel_slot_commit_string (int context, const WideString &wstr, bool remote_mode)
2580 WSCContextISF* ic = find_ic (context);
2581 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
2583 if (ic && ic->impl) {
2584 if (_focused_ic != ic)
2588 if (ic->impl->block_input_resource) {
2589 LOGW ("block remote input");
2592 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2594 if (ic->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_URL)
2595 wsc_context_delete_surrounding (ic, INT_MIN/2, INT_MAX);
2597 wsc_context_commit_string (ic, utf8_wcstombs (wstr).c_str ());
2598 ic->impl->need_commit_preedit = false;
2599 ic->impl->preedit_string.clear ();
2601 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
2602 wsc_context_commit_string (ic, utf8_wcstombs (wstr).c_str ());
2608 panel_slot_forward_key_event (int context, const KeyEvent &key, bool remote_mode)
2611 WSCContextISF* ic = find_ic (context);
2612 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
2614 if (!(ic && ic->impl))
2617 if ((_focused_ic != NULL) && (_focused_ic != ic))
2621 if (ic->impl->block_input_resource) {
2622 LOGW ("block remote input");
2625 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2627 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
2630 if (key.get_key_string ().length () >= 116)
2633 send_wl_key_event (ic, key, true);
2637 panel_slot_update_preedit_string (int context, const WideString str, const WideString commit, const AttributeList &attrs, int caret, bool remote_mode)
2640 WSCContextISF* ic = find_ic (context);
2641 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << " caret=" << caret << " ic=" << ic << "\n";
2643 if (ic && ic->impl && _focused_ic == ic) {
2645 if (ic->impl->block_input_resource) {
2646 LOGW ("block remote input");
2649 check_input_resource (ic, INPUT_RESOURCE_REMOTE);
2652 if (!ic->impl->is_on)
2653 ic->impl->is_on = true;
2655 if (ic->impl->preedit_string != str || str.length ()) {
2656 ic->impl->preedit_string = str;
2657 ic->impl->preedit_attrlist = attrs;
2658 ic->impl->commit_string = commit;
2660 if (ic->impl->use_preedit) {
2661 if (!ic->impl->preedit_started) {
2662 if (!check_valid_ic (ic))
2665 ic->impl->preedit_started = true;
2666 ic->impl->need_commit_preedit = true;
2668 if (caret >= 0 && caret <= (int)str.length ())
2669 ic->impl->preedit_caret = caret;
2671 ic->impl->preedit_caret = str.length ();
2673 if (ic->impl->panel_layout == ECORE_IMF_INPUT_PANEL_LAYOUT_URL)
2674 wsc_context_delete_surrounding (ic, INT_MIN/2, INT_MAX);
2676 wsc_context_send_preedit_string (ic);
2678 String _str = utf8_wcstombs (str);
2679 g_info_manager->socket_update_preedit_string (_str, attrs, (uint32)caret);
2686 _show_preedit_string (int context)
2689 WSCContextISF* ic = find_ic (context);
2690 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << " context=" << context << "\n";
2692 if (ic && ic->impl && _focused_ic == ic) {
2693 if (!ic->impl->is_on)
2694 ic->impl->is_on = true;
2696 if (ic->impl->use_preedit) {
2697 if (!ic->impl->preedit_started) {
2698 if (check_valid_ic (ic)) {
2699 ic->impl->preedit_started = true;
2700 ic->impl->need_commit_preedit = true;
2704 g_info_manager->socket_show_preedit_string ();
2710 _hide_preedit_string (int context, bool update_preedit)
2712 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2714 WSCContextISF* ic = find_ic (context);
2716 if (ic && ic->impl && _focused_ic == ic) {
2717 if (!ic->impl->is_on)
2718 ic->impl->is_on = true;
2721 if (ic->impl->preedit_string.length ()) {
2722 ic->impl->preedit_string = WideString ();
2723 ic->impl->preedit_caret = 0;
2724 ic->impl->preedit_attrlist.clear ();
2727 ic->impl->commit_string = WideString ();
2728 if (ic->impl->use_preedit) {
2729 if (update_preedit && emit) {
2730 if (!check_valid_ic (ic))
2733 if (ic->impl->preedit_started) {
2734 if (check_valid_ic (ic)) {
2735 ic->impl->preedit_started = false;
2736 ic->impl->need_commit_preedit = false;
2739 wsc_context_send_preedit_string (ic);
2741 g_info_manager->socket_hide_preedit_string ();
2749 LOGD ("Initializing Wayland ISF IMModule...");
2751 // Get system language.
2752 _language = scim_get_locale_language (scim_get_current_locale ());
2754 panel_initialize ();
2760 LOGD ("Finalizing Ecore ISF IMModule...");
2762 SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2763 while (_used_ic_impl_list) {
2764 // In case in "shared input method" mode,
2765 // all contexts share only one instance,
2766 // so we need point the reference pointer correctly before finalizing.
2768 if (_used_ic_impl_list->si) {
2769 _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2772 if (_used_ic_impl_list->parent && _used_ic_impl_list->parent->ctx) {
2773 isf_wsc_context_del (_used_ic_impl_list->parent);
2777 delete_all_ic_impl ();
2779 SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2784 _scim_initialized = false;
2788 static uint32_t _keyname_to_keysym (uint32_t keyname, uint32_t *modifiers)
2793 if ((keyname >= '0' && keyname <= '9') ||
2794 (keyname >= 'a' && keyname <= 'z')) {
2796 } else if (keyname >= 'A' && keyname <= 'Z') {
2797 *modifiers |= MOD_SHIFT_MASK;
2798 return keyname + 32;
2803 *modifiers |= MOD_SHIFT_MASK;
2806 *modifiers |= MOD_SHIFT_MASK;
2809 *modifiers |= MOD_SHIFT_MASK;
2812 *modifiers |= MOD_SHIFT_MASK;
2815 *modifiers |= MOD_SHIFT_MASK;
2818 *modifiers |= MOD_SHIFT_MASK;
2821 *modifiers |= MOD_SHIFT_MASK;
2824 *modifiers |= MOD_SHIFT_MASK;
2827 *modifiers |= MOD_SHIFT_MASK;
2830 *modifiers |= MOD_SHIFT_MASK;
2833 *modifiers |= MOD_SHIFT_MASK;
2836 *modifiers |= MOD_SHIFT_MASK;
2839 *modifiers |= MOD_SHIFT_MASK;
2842 *modifiers |= MOD_SHIFT_MASK;
2845 *modifiers |= MOD_SHIFT_MASK;
2848 *modifiers |= MOD_SHIFT_MASK;
2851 *modifiers |= MOD_SHIFT_MASK;
2854 *modifiers |= MOD_SHIFT_MASK;
2857 *modifiers |= MOD_SHIFT_MASK;
2860 *modifiers |= MOD_SHIFT_MASK;
2867 static void send_wl_key_event (WSCContextISF *ic, const KeyEvent &key, bool fake)
2869 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2872 uint32_t modifiers = 0;
2877 modifiers |= MOD_Mod5_MASK;
2880 if (key.is_shift_down ())
2881 modifiers |= MOD_SHIFT_MASK;
2882 if (key.is_alt_down ())
2883 modifiers |= MOD_ALT_MASK;
2884 if (key.is_control_down ())
2885 modifiers |= MOD_CONTROL_MASK;
2887 _keyname_to_keysym (key.code, &modifiers);
2890 wsc_context_send_key (ic, key.code, modifiers, time, key.is_key_press ());
2894 reload_config_callback (const ConfigPointer &config)
2896 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
2898 //FIXME:_frontend_hotkey_matcher and _imengine_hotkey_matcher should be added
2899 //_frontend_hotkey_matcher.load_hotkeys (config);
2900 //_imengine_hotkey_matcher.load_hotkeys (config);
2903 scim_string_to_key (key,
2904 config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
2905 String ("Shift+Control+Alt+Lock")));
2907 _valid_key_mask = (key.mask > 0) ? (key.mask) : 0xFFFF;
2908 _valid_key_mask |= SCIM_KEY_ReleaseMask;
2909 // Special treatment for two backslash keys on jp106 keyboard.
2910 _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
2912 _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
2913 //_shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
2914 _change_keyboard_mode_by_focus_move = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_CHANGE_KEYBOARD_MODE_BY_FOCUS_MOVE), _change_keyboard_mode_by_focus_move);
2915 _support_hw_keyboard_mode = scim_global_config_read (String (SCIM_GLOBAL_CONFIG_SUPPORT_HW_KEYBOARD_MODE), _support_hw_keyboard_mode);
2917 // Get keyboard layout setting
2918 // Flush the global config first, in order to load the new configs from disk.
2919 scim_global_config_flush ();
2921 _keyboard_layout = scim_get_default_keyboard_layout ();
2924 class WaylandPanelAgent: public PanelAgentBase
2926 Connection _config_connection;
2929 WaylandPanelAgent ()
2930 : PanelAgentBase ("wayland") {
2932 ~WaylandPanelAgent () {
2935 bool initialize (InfoManager* info_manager, const String& display, bool resident) {
2937 g_info_manager = info_manager;
2938 isf_wsc_context_init ();
2940 if (!_wsc_setup (&_wsc)) {
2944 _config_connection = _config->signal_connect_reload (slot (reload_config_callback));
2946 _wl_im_ctx = new _wl_im;
2948 LOGW ("Can not create wl_im_ctx");
2954 bool valid (void) const {
2959 if (_need_wl_im_init)
2967 _config_connection.disconnect ();
2968 isf_wsc_context_shutdown ();
2973 exit (int id, uint32 contextid) {
2974 LOGD ("client id:%d", id);
2979 update_preedit_caret (int id, uint32 context_id, uint32 caret) {
2980 LOGD ("client id:%d", id);
2981 panel_slot_update_preedit_caret (context_id, caret);
2985 socket_helper_key_event (int id, uint32 context_id, int cmd , KeyEvent& key) {
2986 LOGD ("client id:%d", id);
2988 if (cmd == SCIM_TRANS_CMD_PROCESS_KEY_EVENT)
2989 panel_slot_process_key_event (context_id, key);
2991 panel_slot_forward_key_event (context_id, key, false);
2995 commit_string (int id, uint32 context_id, const WideString& wstr) {
2996 LOGD ("client id:%d", id);
2997 panel_slot_commit_string (context_id, wstr, false);
3001 forward_key_event (int id, uint32 context_id, const KeyEvent &key) {
3002 LOGD ("client id:%d", id);
3003 panel_slot_forward_key_event (context_id, key, false);
3007 remote_commit_string (int id, uint32 context_id, const WideString& wstr) {
3008 LOGD ("client id:%d", id);
3009 panel_slot_commit_string (context_id, wstr, true);
3013 remote_update_preedit_string (int id, uint32 context_id, const WideString str, const WideString commit, const AttributeList &attrs, uint32 caret) {
3014 LOGD ("client id:%d", id);
3015 panel_slot_update_preedit_string (context_id, str, commit, attrs, caret, true);
3019 remote_forward_key_event (int id, uint32 context_id, const KeyEvent &key) {
3020 LOGD ("client id:%d", id);
3021 panel_slot_forward_key_event (context_id, key, true);
3025 remote_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len) {
3026 LOGD ("client id:%d", id);
3029 if (_focused_ic->impl->block_input_resource)
3032 check_input_resource (_focused_ic, INPUT_RESOURCE_REMOTE);
3033 wsc_context_delete_surrounding (_focused_ic, offset, len);
3038 update_ise_input_context (int client, uint32 context, uint32 type, uint32 value) {
3039 if (!_focused_ic || !_focused_ic->im_ctx)
3042 if (type == ECORE_IMF_INPUT_PANEL_LANGUAGE_EVENT) {
3043 WSCContextISF* ic = find_ic (context);
3044 if (ic && ic->language) {
3045 wl_input_method_context_language (_focused_ic->im_ctx, _focused_ic->serial, ic->language);
3048 LOGE("language locale query failed : %p %s", ic, (ic ? ic->language : "NULL"));
3049 wl_input_method_context_language (_focused_ic->im_ctx, _focused_ic->serial, "");
3052 wl_input_method_context_input_panel_event (_focused_ic->im_ctx, _focused_ic->serial, type, value);
3056 update_ise_language_locale (int client, uint32 context, String locale) {
3057 if (!_focused_ic || !_focused_ic->im_ctx)
3060 WSCContextISF* ic = find_ic (context);
3061 if (ic && locale.length() > 0) {
3064 ic->language = NULL;
3066 ic->language = strdup(locale.c_str());
3072 request_help (int id, uint32 context_id) {
3073 LOGD ("client id:%d", id);
3074 panel_slot_request_help (context_id);
3079 request_factory_menu (int id, uint32 context_id) {
3080 LOGD ("client id:%d", id);
3081 panel_slot_request_factory_menu (context_id);
3085 change_factory (int id, uint32 context_id, const String& uuid) {
3086 LOGD ("client id:%d", id);
3087 panel_slot_change_factory (context_id, uuid);
3092 reset_keyboard_ise (int id, uint32 context_id) {
3093 LOGD ("client id:%d", id);
3094 panel_slot_reset_keyboard_ise (context_id);
3099 update_keyboard_ise (int id, uint32 context_id) {
3100 LOGD ("client id:%d", id);
3101 panel_slot_update_keyboard_ise (context_id);
3106 show_preedit_string (int id, uint32 context_id) {
3107 LOGD ("client id:%d", id);
3108 _show_preedit_string (context_id);
3112 hide_preedit_string (int id, uint32 context_id) {
3113 LOGD ("client id:%d", id);
3114 _hide_preedit_string (context_id, true);
3118 update_preedit_string (int id, uint32 context_id, WideString preedit, WideString commit, AttributeList& attrs, uint32 caret) {
3119 LOGD ("client id:%d", id);
3120 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
3121 WSCContextISF* ic = find_ic (context_id);
3123 if (ic && ic->impl && _focused_ic == ic) {
3124 if (!ic->impl->is_on)
3125 ic->impl->is_on = true;
3127 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
3129 ic->impl->preedit_string = preedit;
3130 ic->impl->preedit_attrlist = attrs;
3131 ic->impl->commit_string = commit;
3133 if (ic->impl->use_preedit) {
3134 if (!ic->impl->preedit_started) {
3135 if (!check_valid_ic (ic))
3138 ic->impl->preedit_started = true;
3139 ic->impl->need_commit_preedit = true;
3141 if (caret <= preedit.length ())
3142 ic->impl->preedit_caret = caret;
3144 ic->impl->preedit_caret = preedit.length ();
3145 wsc_context_send_preedit_string (ic);
3147 String _str = utf8_wcstombs (preedit);
3148 g_info_manager->socket_update_preedit_string (_str, attrs, (uint32)caret);
3154 recapture_string (int id, uint32 context_id, int offset, int len, WideString preedit, WideString commit, AttributeList& attrs) {
3155 LOGD ("client id:%d", id);
3156 SCIM_DEBUG_FRONTEND (1) << __FUNCTION__ << "...\n";
3157 WSCContextISF* ic = find_ic (context_id);
3158 String preedit_str = utf8_wcstombs (preedit);
3159 String commit_str = utf8_wcstombs (commit);
3161 if (ic && ic->impl && _focused_ic == ic) {
3162 if (!ic->impl->is_on)
3163 ic->impl->is_on = true;
3165 check_input_resource (ic, INPUT_RESOURCE_LOCAL);
3167 ic->impl->preedit_string = preedit;
3168 ic->impl->preedit_attrlist = attrs;
3169 ic->impl->commit_string = commit;
3171 if (ic->impl->use_preedit) {
3172 if (!ic->impl->preedit_started) {
3173 if (!check_valid_ic (ic))
3176 ic->impl->preedit_started = true;
3177 ic->impl->need_commit_preedit = true;
3179 ic->impl->preedit_caret = preedit.length ();
3181 wl_input_method_context_preedit_cursor (ic->im_ctx, strlen(preedit_str.c_str()));
3182 wsc_send_preedit_style (ic);
3184 wl_input_method_context_recapture_string (ic->im_ctx, ic->serial,
3185 offset, len, preedit_str.c_str(), preedit_str.c_str(), commit_str.c_str());
3187 g_info_manager->socket_recapture_string (offset, len, preedit_str, commit_str, attrs);
3193 surrounding_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
3194 if (fd_handler == NULL || data == NULL)
3195 return ECORE_CALLBACK_RENEW;
3197 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
3199 int fd = ecore_main_fd_handler_fd_get (fd_handler);
3201 return ECORE_CALLBACK_RENEW;
3204 int len = read (fd, buff, sizeof (buff) - 1);
3206 LOGD ("update, wsc_ctx->surrounding_cursor = %d", wsc_ctx->surrounding_cursor);
3207 g_info_manager->socket_update_surrounding_text (wsc_ctx->surrounding_text ? wsc_ctx->surrounding_text : "", wsc_ctx->surrounding_cursor);
3208 } else if (len < 0) {
3212 if (wsc_ctx->surrounding_text == NULL) {
3213 if (len >= (int)sizeof(int)) {
3214 /* Add one byte for terminating NULL character and subtract <int> byte for cursor position */
3215 wsc_ctx->surrounding_text = (char*)malloc (len + 1 - sizeof(int));
3216 if (wsc_ctx->surrounding_text) {
3217 memcpy(&(wsc_ctx->surrounding_cursor), buff, sizeof(int));
3218 memcpy (wsc_ctx->surrounding_text, buff + sizeof(int), len - sizeof(int));
3219 wsc_ctx->surrounding_text[len - sizeof(int)] = '\0';
3220 return ECORE_CALLBACK_RENEW;
3222 LOGE ("malloc failed");
3226 int old_len = strlen (wsc_ctx->surrounding_text);
3227 void * _new = realloc (wsc_ctx->surrounding_text, len + old_len + 1);
3229 wsc_ctx->surrounding_text = (char*)_new;
3230 memcpy (wsc_ctx->surrounding_text + old_len, buff, len);
3231 wsc_ctx->surrounding_text[old_len + len] = '\0';
3232 return ECORE_CALLBACK_RENEW;
3234 LOGE ("realloc failed");
3239 if (wsc_ctx->surrounding_text_fd_read_handler) {
3241 ecore_main_fd_handler_del (wsc_ctx->surrounding_text_fd_read_handler);
3242 wsc_ctx->surrounding_text_fd_read_handler = NULL;
3245 if (wsc_ctx->surrounding_text) {
3246 free (wsc_ctx->surrounding_text);
3247 wsc_ctx->surrounding_text = NULL;
3250 return ECORE_CALLBACK_RENEW;
3254 socket_helper_get_surrounding_text (int id, uint32 context_id, uint32 maxlen_before, uint32 maxlen_after) {
3255 LOGD ("client id:%d", id);
3258 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) == -1) {
3259 LOGW ("create pipe failed");
3262 LOGD("%d,%d", filedes[0], filedes[1]);
3263 WSCContextISF* ic = find_ic (context_id);
3267 wl_input_method_context_get_surrounding_text (ic->im_ctx, maxlen_before, maxlen_after, filedes[1]);
3269 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get (NULL);
3271 ecore_wl2_display_flush (wl2_display);
3274 if (ic->surrounding_text_fd_read_handler) {
3275 int fd = ecore_main_fd_handler_fd_get (ic->surrounding_text_fd_read_handler);
3278 ecore_main_fd_handler_del (ic->surrounding_text_fd_read_handler);
3279 ic->surrounding_text_fd_read_handler = NULL;
3282 if (ic->surrounding_text) {
3283 free (ic->surrounding_text);
3284 ic->surrounding_text = NULL;
3287 ic->surrounding_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, surrounding_text_fd_read_func, ic, NULL, NULL);
3291 socket_helper_delete_surrounding_text (int id, uint32 context_id, uint32 offset, uint32 len) {
3292 LOGD ("client id:%d", id);
3293 //panel_slot_delete_surrounding_text (context_id, offset, len);
3295 check_input_resource (_focused_ic, INPUT_RESOURCE_LOCAL);
3296 wsc_context_delete_surrounding (_focused_ic, offset, len);
3301 socket_helper_set_selection (int id, uint32 context_id, uint32 start, uint32 end) {
3302 LOGD ("client id:%d", id);
3304 wsc_context_set_selection (_focused_ic, start, end);
3308 send_private_command (int id, uint32 context_id, const String& command) {
3309 LOGD ("client id:%d", id);
3310 //panel_slot_send_private_command (context_id, command);
3311 if (_focused_ic && _focused_ic->im_ctx)
3312 wl_input_method_context_private_command (_focused_ic->im_ctx, _focused_ic->serial, command.c_str ());
3316 commit_content (int id, uint32 context_id, const String& content, const String& description, const String& mime_types) {
3317 LOGD ("client id:%d", id);
3318 if (_focused_ic && _focused_ic->im_ctx)
3319 wl_input_method_context_commit_content (_focused_ic->im_ctx, _focused_ic->serial, content.c_str (), description.c_str (), mime_types.c_str ());
3323 hide_helper_ise (int id, uint32 context_id)
3325 LOGD ("client id:%d", id);
3326 WSCContextISF* ic = find_ic (context_id);
3329 wl_input_method_context_hide_input_panel (ic->im_ctx, ic->serial);
3334 selection_text_fd_read_func (void* data, Ecore_Fd_Handler* fd_handler) {
3335 if (fd_handler == NULL || data == NULL)
3336 return ECORE_CALLBACK_RENEW;
3338 WSCContextISF* wsc_ctx = (WSCContextISF*)data;
3339 int fd = ecore_main_fd_handler_fd_get (fd_handler);
3341 return ECORE_CALLBACK_RENEW;
3344 int len = read (fd, buff, sizeof (buff) - 1);
3347 g_info_manager->socket_update_selection (wsc_ctx->selection_text ? wsc_ctx->selection_text : "");
3348 } else if (len < 0) {
3352 if (wsc_ctx->selection_text == NULL) {
3353 wsc_ctx->selection_text = (char*)malloc (len + 1);
3354 if (wsc_ctx->selection_text) {
3355 memcpy (wsc_ctx->selection_text, buff, len);
3356 wsc_ctx->selection_text[len] = '\0';
3357 return ECORE_CALLBACK_RENEW;
3359 LOGE ("malloc failed");
3362 int old_len = strlen (wsc_ctx->selection_text);
3363 void * _new = realloc (wsc_ctx->selection_text, len + old_len + 1);
3365 wsc_ctx->selection_text = (char*)_new;
3366 memcpy (wsc_ctx->selection_text + old_len, buff, len);
3367 wsc_ctx->selection_text[old_len + len] = '\0';
3368 return ECORE_CALLBACK_RENEW;
3370 LOGE ("realloc failed");
3375 if (wsc_ctx->selection_text_fd_read_handler) {
3377 ecore_main_fd_handler_del (wsc_ctx->selection_text_fd_read_handler);
3378 wsc_ctx->selection_text_fd_read_handler = NULL;
3381 if (wsc_ctx->selection_text) {
3382 free (wsc_ctx->selection_text);
3383 wsc_ctx->selection_text = NULL;
3386 return ECORE_CALLBACK_RENEW;
3390 socket_helper_get_selection (int id, uint32 context_id) {
3391 LOGD ("client id:%d", id);
3394 if (pipe2(filedes, O_CLOEXEC | O_NONBLOCK) ==-1 ) {
3395 LOGW ("create pipe failed");
3398 LOGD("%d,%d", filedes[0], filedes[1]);
3400 WSCContextISF* ic = find_ic (context_id);
3403 wl_input_method_context_get_selection_text (ic->im_ctx, filedes[1]);
3404 Ecore_Wl2_Display *wl2_display = ecore_wl2_connected_display_get (NULL);
3406 ecore_wl2_display_flush (wl2_display);
3409 if (ic->selection_text_fd_read_handler) {
3410 int fd = ecore_main_fd_handler_fd_get (ic->selection_text_fd_read_handler);
3414 ecore_main_fd_handler_del (ic->selection_text_fd_read_handler);
3415 ic->selection_text_fd_read_handler = NULL;
3418 if (ic->selection_text) {
3419 free (ic->selection_text);
3420 ic->selection_text = NULL;
3423 ic->selection_text_fd_read_handler = ecore_main_fd_handler_add (filedes[0], ECORE_FD_READ, selection_text_fd_read_func, ic, NULL, NULL);
3426 void process_key_event_done (int id, uint32 context_id, KeyEvent &key, uint32 ret, uint32 serial) {
3427 LOGD ("client id:%d", id);
3428 WSCContextISF* ic = find_ic (context_id);
3431 #if ENABLE_GRAB_KEYBOARD
3432 if (ret == EINA_FALSE) {
3433 send_wl_key_event (ic, key, false);
3436 wl_input_method_context_filter_key_event_done (ic->im_ctx, serial, ret);
3440 void request_ise_hide (int id, uint32 context_id) {
3441 LOGD ("client id:%d", id);
3442 WSCContextISF* ic = find_ic (context_id);
3445 wl_input_method_context_hide_input_panel (ic->im_ctx, ic->serial);
3449 update_ise_geometry (int id, uint32 context_id, uint32 x, uint32 y, uint32 width, uint32 height) {
3450 LOGD ("client id:%d", id);
3452 if (_focused_ic && _focused_ic->im_ctx) {
3453 wl_input_method_context_update_ise_geometry (_focused_ic->im_ctx, _focused_ic->serial, x, y, width, height);
3457 void helper_candidate_show(int id, uint32 context_id, const String& uuid)
3459 WSCContextISF* ic = find_ic(context_id);
3463 wl_input_method_context_update_candidate_state(ic->im_ctx, 1);
3467 void helper_candidate_hide(int id, uint32 context_id, const String& uuid)
3469 WSCContextISF* ic = find_ic(context_id);
3473 wl_input_method_context_update_candidate_state(ic->im_ctx, 0);
3477 void update_entry_metadata (int id, uint32 context_id) {
3478 LOGD ("client id:%d", id);
3479 WSCContextISF* ic = find_ic(context_id);
3480 if (!ic || !ic->im_ctx) return;
3482 if (ic->layout_initialized)
3483 isf_wsc_context_input_panel_layout_set (ic, wsc_context_input_panel_layout_get (ic));
3485 if (ic->prediction_allow_initialized)
3486 g_info_manager->set_prediction_allow (WAYLAND_MODULE_CLIENT_ID, wsc_context_prediction_allow_get (ic));
3488 if (ic->autocapital_type_initialized)
3489 isf_wsc_context_autocapital_type_set (ic, wsc_context_autocapital_type_get (ic));
3491 if (ic->language_initialized)
3492 isf_wsc_context_input_panel_language_set (ic, wsc_context_input_panel_language_get (ic));
3494 g_info_manager->socket_update_cursor_position (ic->surrounding_cursor);
3495 isf_wsc_context_input_panel_return_key_type_set (ic, (Ecore_IMF_Input_Panel_Return_Key_Type)ic->return_key_type);
3496 isf_wsc_context_input_panel_return_key_disabled_set (ic, ic->return_key_disabled);
3499 isf_wsc_context_input_panel_imdata_set (ic, (void *)ic->impl->imdata, ic->impl->imdata_size);
3501 isf_wsc_context_bidi_direction_set (ic, (Ecore_IMF_BiDi_Direction)ic->bidi_direction);
3502 isf_wsc_context_input_panel_caps_mode_set (ic, ic->caps_mode);
3505 isf_wsc_context_input_panel_mime_type_accept_set (ic, ic->impl->mime_type.c_str ());
3508 isf_wsc_context_send_entry_metadata (ic, wsc_context_input_hint_get (ic), wsc_context_input_panel_layout_get (ic),
3509 wsc_context_input_panel_layout_variation_get (ic), wsc_context_autocapital_type_get (ic), ic->return_key_disabled);
3516 EXAPI void scim_module_init (void)
3521 EXAPI void scim_module_exit (void)
3527 EXAPI void scim_panel_agent_module_init (const scim::ConfigPointer& config)
3533 EXAPI scim::PanelAgentPointer scim_panel_agent_module_get_instance ()
3535 scim::PanelAgentBase* _instance = NULL;
3536 if (instance.null ()) {
3538 _instance = new WaylandPanelAgent ();
3545 instance = _instance;
3552 vi:ts=4:nowrap:expandtab