6
#define Uses_SCIM_BACKEND
7
#define Uses_SCIM_IMENGINE_MODULE
8
#define Uses_SCIM_HOTKEY
9
#define Uses_SCIM_PANEL_CLIENT
17
#include <Ecore_Evas.h>
23
#include <X11/keysym.h>
26
#pragma GCC diagnostic push
27
#pragma GCC diagnostic ignored "-Wshadow"
29
#pragma GCC diagnostic pop
31
#include "scim_imcontext.h"
35
struct _EcoreIMFContextISFImpl
37
EcoreIMFContextISF *parent;
38
IMEngineInstancePointer si;
39
Ecore_X_Window client_window;
41
Ecore_IMF_Input_Mode input_mode;
42
WideString preedit_string;
43
AttributeList preedit_attrlist;
44
Ecore_IMF_Autocapital_Type autocapital_type;
53
bool preedit_updating;
54
bool prediction_allow;
56
EcoreIMFContextISFImpl *next;
59
/* Input Context handling functions. */
60
static EcoreIMFContextISFImpl *new_ic_impl (EcoreIMFContextISF *parent);
61
static void delete_ic_impl (EcoreIMFContextISFImpl *impl);
62
static void delete_all_ic_impl (void);
64
static EcoreIMFContextISF *find_ic (int id);
67
/* private functions */
68
static void panel_slot_reload_config (int context);
69
static void panel_slot_exit (int context);
70
static void panel_slot_update_lookup_table_page_size(int context,
72
static void panel_slot_lookup_table_page_up (int context);
73
static void panel_slot_lookup_table_page_down (int context);
74
static void panel_slot_trigger_property (int context,
75
const String &property);
76
static void panel_slot_process_helper_event (int context,
77
const String &target_uuid,
78
const String &helper_uuid,
79
const Transaction &trans);
80
static void panel_slot_move_preedit_caret (int context,
82
static void panel_slot_select_candidate (int context,
84
static void panel_slot_process_key_event (int context,
86
static void panel_slot_commit_string (int context,
87
const WideString &wstr);
88
static void panel_slot_forward_key_event (int context,
90
static void panel_slot_request_help (int context);
91
static void panel_slot_request_factory_menu (int context);
92
static void panel_slot_change_factory (int context,
95
static void panel_req_focus_in (EcoreIMFContextISF *ic);
96
static void panel_req_update_factory_info (EcoreIMFContextISF *ic);
97
static void panel_req_update_spot_location (EcoreIMFContextISF *ic);
98
static void panel_req_show_help (EcoreIMFContextISF *ic);
99
static void panel_req_show_factory_menu (EcoreIMFContextISF *ic);
101
/* Panel iochannel handler*/
102
static bool panel_initialize (void);
103
static void panel_finalize (void);
104
static Eina_Bool panel_iochannel_handler (void *data,
105
Ecore_Fd_Handler *fd_handler);
107
/* utility functions */
108
static bool filter_hotkeys (EcoreIMFContextISF *ic,
109
const KeyEvent &key);
110
static void turn_on_ic (EcoreIMFContextISF *ic);
111
static void turn_off_ic (EcoreIMFContextISF *ic);
112
static void set_ic_capabilities (EcoreIMFContextISF *ic);
114
static void initialize (void);
115
static void finalize (void);
117
static void open_next_factory (EcoreIMFContextISF *ic);
118
static void open_previous_factory (EcoreIMFContextISF *ic);
119
static void open_specific_factory (EcoreIMFContextISF *ic,
121
static void initialize_modifier_bits (Display *display);
122
static unsigned int scim_x11_keymask_scim_to_x11 (Display *display, uint16 scimkeymask);
123
static XKeyEvent createKeyEvent (Display *display, Window &win,
124
Window &winRoot, bool press,
125
int keysym, int modifiers);
126
static void _x_send_key_event (const KeyEvent &key);
128
static void attach_instance (const IMEngineInstancePointer &si);
131
static void slot_show_preedit_string (IMEngineInstanceBase *si);
132
static void slot_show_aux_string (IMEngineInstanceBase *si);
133
static void slot_show_lookup_table (IMEngineInstanceBase *si);
135
static void slot_hide_preedit_string (IMEngineInstanceBase *si);
136
static void slot_hide_aux_string (IMEngineInstanceBase *si);
137
static void slot_hide_lookup_table (IMEngineInstanceBase *si);
139
static void slot_update_preedit_caret (IMEngineInstanceBase *si,
141
static void slot_update_preedit_string (IMEngineInstanceBase *si,
142
const WideString &str,
143
const AttributeList &attrs);
144
static void slot_update_aux_string (IMEngineInstanceBase *si,
145
const WideString &str,
146
const AttributeList &attrs);
147
static void slot_commit_string (IMEngineInstanceBase *si,
148
const WideString &str);
149
static void slot_forward_key_event (IMEngineInstanceBase *si,
150
const KeyEvent &key);
151
static void slot_update_lookup_table (IMEngineInstanceBase *si,
152
const LookupTable &table);
154
static void slot_register_properties (IMEngineInstanceBase *si,
155
const PropertyList &properties);
156
static void slot_update_property (IMEngineInstanceBase *si,
157
const Property &property);
158
static void slot_beep (IMEngineInstanceBase *si);
159
static void slot_start_helper (IMEngineInstanceBase *si,
160
const String &helper_uuid);
161
static void slot_stop_helper (IMEngineInstanceBase *si,
162
const String &helper_uuid);
163
static void slot_send_helper_event (IMEngineInstanceBase *si,
164
const String &helper_uuid,
165
const Transaction &trans);
166
static bool slot_get_surrounding_text (IMEngineInstanceBase *si,
171
static bool slot_delete_surrounding_text (IMEngineInstanceBase *si,
175
static void reload_config_callback (const ConfigPointer &config);
177
static void fallback_commit_string_cb (IMEngineInstanceBase *si,
178
const WideString &str);
180
/* Local variables declaration */
181
static String _language;
182
static EcoreIMFContextISFImpl *_used_ic_impl_list = 0;
183
static EcoreIMFContextISFImpl *_free_ic_impl_list = 0;
184
static EcoreIMFContextISF *_ic_list = 0;
186
static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
187
static int _valid_key_mask = SCIM_KEY_AllMasks;
189
static FrontEndHotkeyMatcher _frontend_hotkey_matcher;
190
static IMEngineHotkeyMatcher _imengine_hotkey_matcher;
192
static IMEngineInstancePointer _default_instance;
194
static ConfigModule *_config_module = 0;
195
static ConfigPointer _config;
196
static BackEndPointer _backend;
198
static EcoreIMFContextISF *_focused_ic = 0;
200
static bool _scim_initialized = false;
202
static int _instance_count = 0;
203
static int _context_count = 0;
205
static IMEngineFactoryPointer _fallback_factory;
206
static IMEngineInstancePointer _fallback_instance;
207
static PanelClient _panel_client;
209
static Ecore_Fd_Handler *_panel_iochannel_read_handler = 0;
210
static Ecore_Fd_Handler *_panel_iochannel_err_handler = 0;
212
static Ecore_X_Window _client_window = 0;
214
static bool _on_the_spot = true;
215
static bool _shared_input_method = false;
217
static Display *__current_display = 0;
218
static int __current_alt_mask = Mod1Mask;
219
static int __current_meta_mask = 0;
220
static int __current_super_mask = 0;
221
static int __current_hyper_mask = 0;
222
static int __current_numlock_mask = Mod2Mask;
224
// A hack to shutdown the immodule cleanly even if im_module_exit() is not called when exiting.
230
SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::FinalizeHandler()\n";
234
SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::~FinalizeHandler()\n";
235
isf_imf_context_shutdown();
239
static FinalizeHandler _finalize_handler;
242
utf8_offset_to_index(const char *str, int offset)
246
for (i = 0; i < offset; i++)
248
eina_unicode_utf8_next_get(str, &index);
259
struct timezone tz; /* is not used since ages */
260
gettimeofday(&tv, &tz);
261
tint = tv.tv_sec * 1000;
262
tint = tint / 1000 * 1000;
263
tint = tint + tv.tv_usec / 1000;
267
/* Function Implementations */
268
static EcoreIMFContextISFImpl *
269
new_ic_impl(EcoreIMFContextISF *parent)
271
EcoreIMFContextISFImpl *impl = NULL;
273
if (_free_ic_impl_list != NULL)
275
impl = _free_ic_impl_list;
276
_free_ic_impl_list = _free_ic_impl_list->next;
280
impl = new EcoreIMFContextISFImpl;
285
impl->autocapital_type = ECORE_IMF_AUTOCAPITAL_TYPE_NONE;
286
impl->next = _used_ic_impl_list;
287
_used_ic_impl_list = impl;
289
impl->parent = parent;
295
delete_ic_impl(EcoreIMFContextISFImpl *impl)
297
EcoreIMFContextISFImpl *rec = _used_ic_impl_list, *last = 0;
299
for (; rec != 0; last = rec, rec = rec->next)
304
last->next = rec->next;
306
_used_ic_impl_list = rec->next;
308
rec->next = _free_ic_impl_list;
309
_free_ic_impl_list = rec;
313
rec->client_window = 0;
314
rec->preedit_string = WideString();
315
rec->preedit_attrlist.clear();
323
delete_all_ic_impl(void)
325
EcoreIMFContextISFImpl *it = _used_ic_impl_list;
329
_used_ic_impl_list = it->next;
331
it = _used_ic_impl_list;
334
it = _free_ic_impl_list;
337
_free_ic_impl_list = it->next;
339
it = _free_ic_impl_list;
343
static EcoreIMFContextISF *
346
EcoreIMFContextISFImpl *rec = _used_ic_impl_list;
350
if (rec->parent && rec->parent->id == id)
359
feed_key_event(Evas *evas, const char *str, Eina_Bool fake)
361
char key_string[128] = { 0 };
362
unsigned int timestamp = 0;
365
timestamp = get_time();
367
if (strncmp(str, "KeyRelease+", 11) == 0)
369
if ((strlen(str) - 11 + 1) > sizeof(key_string))
371
fprintf(stderr, "Key string too long: '%s'", str);
374
strcpy(key_string, str + 11);
375
evas_event_feed_key_up(evas, key_string, key_string, NULL, NULL,
377
SCIM_DEBUG_FRONTEND(1) << " evas_event_feed_key_up()...\n";
381
if ((strlen(str) + 1) > sizeof(key_string))
383
fprintf(stderr, "Key string too long: '%s'", str);
386
strcpy(key_string, str);
387
evas_event_feed_key_down(evas, key_string, key_string, NULL, NULL,
389
SCIM_DEBUG_FRONTEND(1) << " evas_event_feed_key_down()...\n";
394
window_to_screen_geometry_get(Ecore_X_Window client_win, int *x, int *y)
396
Ecore_X_Window root_window, win;
398
int sum_x = 0, sum_y = 0;
400
if (!ecore_x_display_get()) goto end;
402
root_window = ecore_x_window_root_get(client_win);
405
while (root_window != win)
407
ecore_x_window_geometry_get(win, &win_x, &win_y, NULL, NULL);
410
win = ecore_x_window_parent_get(win);
421
_ecore_imf_modifier_to_scim_mask(unsigned int modifiers)
423
unsigned int mask = 0;
425
/**< "Control" is pressed */
426
if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_CTRL)
427
mask |= SCIM_KEY_ControlMask;
429
/**< "Alt" is pressed */
430
if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALT)
431
mask |= SCIM_KEY_AltMask;
433
/**< "Shift" is pressed */
434
if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_SHIFT)
435
mask |= SCIM_KEY_ShiftMask;
437
/**< "Win" (between "Ctrl" and "Alt") is pressed */
438
if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_WIN)
439
mask |= SCIM_KEY_SuperMask;
441
/**< "AltGr" is pressed */
442
if (modifiers & ECORE_IMF_KEYBOARD_MODIFIER_ALTGR)
443
mask |= SCIM_KEY_Mod5Mask;
449
_ecore_imf_lock_to_scim_mask(unsigned int locks)
451
unsigned int mask = 0;
453
if (locks & ECORE_IMF_KEYBOARD_LOCK_CAPS)
454
mask |= SCIM_KEY_CapsLockMask;
456
if (locks & ECORE_IMF_KEYBOARD_LOCK_NUM)
457
mask |= SCIM_KEY_NumLockMask;
462
/* Public functions */
464
* isf_imf_context_new
466
* This function will be called by Ecore IMF.
467
* Create a instance of type EcoreIMFContextISF.
469
* Return value: A pointer to the newly created EcoreIMFContextISF instance
472
isf_imf_context_new(void)
474
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
476
EcoreIMFContextISF *context_scim = new EcoreIMFContextISF;
477
if (context_scim == NULL)
479
std::cerr << "memory allocation failed in " << __func__ << "\n";
483
context_scim->id = _context_count++;
485
if (!_scim_initialized)
488
_scim_initialized = true;
495
* isf_imf_context_shutdown
497
* It will be called when the scim im module is unloaded by ecore. It will do some
501
isf_imf_context_shutdown(void)
503
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
505
if (_scim_initialized)
507
_scim_initialized = false;
513
isf_imf_context_add(Ecore_IMF_Context *ctx)
515
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
517
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
518
EINA_SAFETY_ON_NULL_RETURN(context_scim);
520
context_scim->impl = NULL;
525
IMEngineInstancePointer si;
527
// Use the default instance if "shared input method" mode is enabled.
528
if (_shared_input_method && !_default_instance.null())
530
si = _default_instance;
531
SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id() << " " << si->get_factory_uuid() << "\n";
534
// Not in "shared input method" mode, or no default instance, create an instance.
537
IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
538
if (factory.null()) return;
539
si = factory->create_instance("UTF-8", _instance_count++);
540
if (si.null()) return;
542
SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id() << " " << si->get_factory_uuid() << "\n";
545
// If "shared input method" mode is enabled, and there is no default instance,
546
// then store this instance as default one.
547
if (_shared_input_method && _default_instance.null())
549
SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
550
_default_instance = si;
553
context_scim->ctx = ctx;
554
context_scim->impl = new_ic_impl(context_scim);
555
if (context_scim->impl == NULL)
557
std::cerr << "memory allocation failed in " << __func__ << "\n";
561
context_scim->impl->si = si;
562
context_scim->impl->client_window = 0;
563
context_scim->impl->client_canvas = NULL;
564
context_scim->impl->preedit_caret = 0;
565
context_scim->impl->cursor_x = 0;
566
context_scim->impl->cursor_y = 0;
567
context_scim->impl->cursor_pos = -1;
568
context_scim->impl->is_on = false;
569
context_scim->impl->shared_si = _shared_input_method;
570
context_scim->impl->use_preedit = _on_the_spot;
571
context_scim->impl->preedit_started = false;
572
context_scim->impl->preedit_updating = false;
573
context_scim->impl->prediction_allow = false;
576
context_scim->next = NULL;
578
context_scim->next = _ic_list;
579
_ic_list = context_scim;
581
if (_shared_input_method)
582
context_scim->impl->is_on = _config->read(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
584
_panel_client.prepare(context_scim->id);
585
_panel_client.register_input_context(context_scim->id, si->get_factory_uuid());
586
set_ic_capabilities(context_scim);
587
_panel_client.send();
589
SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
593
isf_imf_context_del(Ecore_IMF_Context *ctx)
595
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
597
if (!_ic_list) return;
599
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
600
EINA_SAFETY_ON_NULL_RETURN(context_scim);
601
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
603
if (context_scim->id != _ic_list->id)
605
EcoreIMFContextISF *pre = _ic_list;
606
EcoreIMFContextISF *cur = _ic_list->next;
609
if (cur->id == context_scim->id)
611
pre->next = cur->next;
619
_ic_list = _ic_list->next;
621
_panel_client.prepare(context_scim->id);
623
if (context_scim == _focused_ic)
624
context_scim->impl->si->focus_out();
626
// Delete the instance.
627
EcoreIMFContextISF *old_focused = _focused_ic;
628
_focused_ic = context_scim;
629
context_scim->impl->si.reset();
630
_focused_ic = old_focused;
632
if (context_scim == _focused_ic)
634
_panel_client.turn_off(context_scim->id);
635
_panel_client.focus_out(context_scim->id);
638
_panel_client.remove_input_context(context_scim->id);
639
_panel_client.send();
641
if (context_scim->impl->client_window)
642
isf_imf_context_client_window_set(ctx, NULL);
644
delete_ic_impl(context_scim->impl);
645
context_scim->impl = 0;
647
if (context_scim == _focused_ic)
655
* isf_imf_context_client_canvas_set
656
* @ctx: a #Ecore_IMF_Context
657
* @canvas: the client canvas
659
* This function will be called by Ecore IMF.
661
* Set the client canvas for the Input Method Context; this is the canvas
662
* in which the input appears.
664
* The canvas type can be determined by using the context canvas type.
665
* Actually only canvas with type "evas" (Evas *) is supported. This canvas
666
* may be used in order to correctly position status windows, and may also
667
* be used for purposes internal to the Input Method Context.
670
isf_imf_context_client_canvas_set(Ecore_IMF_Context *ctx, void *canvas)
672
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
674
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
675
EINA_SAFETY_ON_NULL_RETURN(context_scim);
676
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
678
if (context_scim->impl->client_canvas != (Evas*) canvas)
679
context_scim->impl->client_canvas = (Evas*)canvas;
683
* isf_imf_context_client_window_set
684
* @ctx: a #Ecore_IMF_Context
685
* @window: the client window
687
* This function will be called by Ecore IMF.
689
* Set the client window for the Input Method Context; this is the Ecore_X_Window
690
* when using X11, Ecore_Win32_Window when using Win32, etc.
692
* This window is used in order to correctly position status windows,
693
* and may also be used for purposes internal to the Input Method Context.
696
isf_imf_context_client_window_set(Ecore_IMF_Context *ctx, void *window)
698
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
700
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
701
EINA_SAFETY_ON_NULL_RETURN(context_scim);
702
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
704
if (context_scim->impl->client_window != (Ecore_X_Window)((Ecore_Window)window))
706
context_scim->impl->client_window = (Ecore_X_Window)((Ecore_Window)window);
708
if ((context_scim->impl->client_window != 0) &&
709
(context_scim->impl->client_window != _client_window))
710
_client_window = context_scim->impl->client_window;
715
* isf_imf_context_reset
716
* @ctx: a #Ecore_IMF_Context
718
* This function will be called by Ecore IMF.
720
* Notify the Input Method Context that a change such as a change in cursor
721
* position has been made. This will typically cause the Input Method Context
722
* to clear the preedit state.
725
isf_imf_context_reset(Ecore_IMF_Context *ctx)
727
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
729
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
730
EINA_SAFETY_ON_NULL_RETURN(context_scim);
731
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
733
if (context_scim != _focused_ic)
736
WideString wstr = context_scim->impl->preedit_string;
738
_panel_client.prepare(context_scim->id);
739
context_scim->impl->si->reset();
740
_panel_client.send();
744
* isf_imf_context_focus_in
745
* @ctx: a #Ecore_IMF_Context
747
* This function will be called by Ecore IMF.
749
* Notify the Input Method Context that the widget to which its correspond has gained focus.
752
isf_imf_context_focus_in(Ecore_IMF_Context *ctx)
754
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
755
EINA_SAFETY_ON_NULL_RETURN(context_scim);
756
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
758
SCIM_DEBUG_FRONTEND(1) << __func__<< "(" << context_scim->id << ")...\n";
762
if (_focused_ic == context_scim)
764
SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
767
SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
768
if (_focused_ic->ctx)
769
isf_imf_context_focus_out(_focused_ic->ctx);
772
bool need_cap = false;
773
bool need_reset = false;
774
bool need_reg = false;
776
_focused_ic = context_scim;
777
_panel_client.prepare(context_scim->id);
779
// Handle the "Shared Input Method" mode.
780
if (_shared_input_method)
782
SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
783
IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
786
if (_default_instance.null() || _default_instance->get_factory_uuid() != factory->get_uuid())
788
_default_instance = factory->create_instance("UTF-8", _default_instance.null() ? _instance_count++ : _default_instance->get_id());
789
attach_instance(_default_instance);
790
SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id() << " " << _default_instance->get_factory_uuid() << "\n";
793
context_scim->impl->shared_si = true;
794
context_scim->impl->si = _default_instance;
796
context_scim->impl->is_on = _config->read(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
797
context_scim->impl->preedit_string.clear();
798
context_scim->impl->preedit_attrlist.clear();
799
context_scim->impl->preedit_caret = 0;
800
context_scim->impl->preedit_started = false;
806
else if (context_scim->impl->shared_si)
808
SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
809
IMEngineFactoryPointer factory = _backend->get_default_factory(_language, "UTF-8");
812
context_scim->impl->si = factory->create_instance("UTF-8", _instance_count++);
813
context_scim->impl->preedit_string.clear();
814
context_scim->impl->preedit_attrlist.clear();
815
context_scim->impl->preedit_caret = 0;
816
context_scim->impl->preedit_started = false;
817
attach_instance(context_scim->impl->si);
820
context_scim->impl->shared_si = false;
821
SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id() << " " << context_scim->impl->si->get_factory_uuid() << "\n";
825
context_scim->impl->si->set_frontend_data(static_cast <void*>(context_scim));
827
if (need_reg) _panel_client.register_input_context(context_scim->id, context_scim->impl->si->get_factory_uuid());
828
if (need_cap) set_ic_capabilities(context_scim);
829
if (need_reset) context_scim->impl->si->reset();
831
panel_req_focus_in(context_scim);
832
panel_req_update_spot_location(context_scim);
833
panel_req_update_factory_info(context_scim);
835
if (context_scim->impl->is_on)
837
_panel_client.turn_on(context_scim->id);
838
_panel_client.hide_preedit_string(context_scim->id);
839
_panel_client.hide_aux_string(context_scim->id);
840
_panel_client.hide_lookup_table(context_scim->id);
841
context_scim->impl->si->focus_in();
845
_panel_client.turn_off(context_scim->id);
848
_panel_client.send();
850
if (ecore_imf_context_input_panel_enabled_get(ctx))
851
ecore_imf_context_input_panel_show(ctx);
855
* isf_imf_context_focus_out
856
* @ctx: a #Ecore_IMF_Context
858
* This function will be called by Ecore IMF.
860
* Notify the Input Method Context that the widget to which its correspond has lost focus.
863
isf_imf_context_focus_out(Ecore_IMF_Context *ctx)
865
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
866
EINA_SAFETY_ON_NULL_RETURN(context_scim);
867
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
869
SCIM_DEBUG_FRONTEND(1) << __func__ << "(" << context_scim->id << ")...\n";
871
if (context_scim == _focused_ic)
873
WideString wstr = context_scim->impl->preedit_string;
875
_panel_client.prepare(context_scim->id);
876
context_scim->impl->si->focus_out();
877
context_scim->impl->si->reset();
878
_panel_client.turn_off(context_scim->id);
879
_panel_client.focus_out(context_scim->id);
880
_panel_client.send();
884
if (ecore_imf_context_input_panel_enabled_get(ctx))
885
ecore_imf_context_input_panel_hide(ctx);
889
* isf_imf_context_cursor_location_set
890
* @ctx: a #Ecore_IMF_Context
891
* @x: x position of New cursor.
892
* @y: y position of New cursor.
893
* @w: the width of New cursor.
894
* @h: the height of New cursor.
896
* This function will be called by Ecore IMF.
898
* Notify the Input Method Context that a change in the cursor location has been made.
901
isf_imf_context_cursor_location_set(Ecore_IMF_Context *ctx, int cx, int cy, int cw, int ch)
903
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
905
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
906
EINA_SAFETY_ON_NULL_RETURN(context_scim);
907
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
910
int canvas_x, canvas_y;
911
int new_cursor_x, new_cursor_y;
912
Ecore_X_Window client_win = 0;
914
if (cw == 0 && ch == 0)
917
if (context_scim != _focused_ic)
920
if (context_scim->impl->client_window)
921
client_win = context_scim->impl->client_window;
924
if (context_scim->impl->client_canvas)
926
ee = ecore_evas_ecore_evas_get(context_scim->impl->client_canvas);
929
client_win = (Ecore_X_Window)ecore_evas_window_get(ee);
933
window_to_screen_geometry_get(client_win, &canvas_x, &canvas_y);
935
new_cursor_x = canvas_x + cx;
936
new_cursor_y = canvas_y + cy + ch;
938
// Don't update spot location while updating preedit string.
939
if (context_scim->impl->preedit_updating && (context_scim->impl->cursor_y == new_cursor_y))
942
if (context_scim->impl->cursor_x != new_cursor_x || context_scim->impl->cursor_y != new_cursor_y)
944
context_scim->impl->cursor_x = new_cursor_x;
945
context_scim->impl->cursor_y = new_cursor_y;
946
_panel_client.prepare(context_scim->id);
947
panel_req_update_spot_location(context_scim);
948
_panel_client.send();
949
SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
954
* isf_imf_context_use_preedit_set
955
* @ctx: a #Ecore_IMF_Context
956
* @use_preedit: Whether the IM context should use the preedit string.
958
* This function will be called by Ecore IMF.
960
* Set whether the IM context should use the preedit string to display feedback.
961
* If is 0 (default is 1), then the IM context may use some other method to
962
* display feedback, such as displaying it in a child of the root window.
965
isf_imf_context_use_preedit_set(Ecore_IMF_Context* ctx, Eina_Bool use_preedit)
967
SCIM_DEBUG_FRONTEND(1) << __func__ << " = " << (use_preedit ? "true" : "false") << "...\n";
969
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
970
EINA_SAFETY_ON_NULL_RETURN(context_scim);
971
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
973
if (!_on_the_spot) return;
975
bool old = context_scim->impl->use_preedit;
976
context_scim->impl->use_preedit = use_preedit;
977
if (context_scim == _focused_ic)
979
_panel_client.prepare(context_scim->id);
981
if (old != use_preedit)
982
set_ic_capabilities(context_scim);
984
if (context_scim->impl->preedit_string.length())
985
slot_show_preedit_string(context_scim->impl->si);
987
_panel_client.send();
992
isf_imf_context_preedit_string_with_attributes_get(Ecore_IMF_Context *ctx, char** str, Eina_List **attrs, int *cursor_pos)
994
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
996
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
997
EINA_SAFETY_ON_NULL_RETURN(context_scim);
998
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
1000
if (context_scim->impl->is_on)
1002
String mbs = utf8_wcstombs(context_scim->impl->preedit_string);
1007
*str = strdup(mbs.c_str());
1014
*cursor_pos = context_scim->impl->preedit_caret;
1021
int start_index, end_index;
1022
int wlen = context_scim->impl->preedit_string.length();
1024
Ecore_IMF_Preedit_Attr *attr = NULL;
1025
AttributeList::const_iterator i;
1026
bool *attrs_flag = new bool [mbs.length()];
1027
memset(attrs_flag, 0, mbs.length() *sizeof(bool));
1029
for (i = context_scim->impl->preedit_attrlist.begin();
1030
i != context_scim->impl->preedit_attrlist.end(); ++i)
1032
start_index = i->get_start();
1033
end_index = i->get_end();
1035
if (end_index <= wlen && start_index < end_index && i->get_type() != SCIM_ATTR_DECORATE_NONE)
1037
start_index = utf8_offset_to_index(mbs.c_str(), i->get_start());
1038
end_index = utf8_offset_to_index(mbs.c_str(), i->get_end());
1040
if (i->get_type() == SCIM_ATTR_DECORATE)
1042
attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
1045
attr->start_index = start_index;
1046
attr->end_index = end_index;
1048
if (i->get_value() == SCIM_ATTR_DECORATE_UNDERLINE)
1050
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB1;
1051
*attrs = eina_list_append(*attrs, (void *)attr);
1053
else if (i->get_value() == SCIM_ATTR_DECORATE_REVERSE)
1055
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1056
*attrs = eina_list_append(*attrs, (void *)attr);
1058
else if (i->get_value() == SCIM_ATTR_DECORATE_HIGHLIGHT)
1060
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB3;
1061
*attrs = eina_list_append(*attrs, (void *)attr);
1068
switch(i->get_value())
1070
case SCIM_ATTR_DECORATE_UNDERLINE:
1071
case SCIM_ATTR_DECORATE_REVERSE:
1072
case SCIM_ATTR_DECORATE_HIGHLIGHT:
1073
// Record which character has attribute.
1074
for (int pos = start_index; pos < end_index; ++pos)
1075
attrs_flag [pos] = 1;
1081
else if (i->get_type() == SCIM_ATTR_FOREGROUND)
1083
SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_FOREGROUND\n";
1085
else if (i->get_type() == SCIM_ATTR_BACKGROUND)
1087
SCIM_DEBUG_FRONTEND(4) << "SCIM_ATTR_BACKGROUND\n";
1092
// Add underline for all characters which don't have attribute.
1093
for (unsigned int pos = 0; pos < mbs.length(); ++pos)
1095
if (!attrs_flag [pos])
1097
int begin_pos = pos;
1099
while (pos < mbs.length() && !attrs_flag[pos])
1102
// use REVERSE style as default
1103
attr = (Ecore_IMF_Preedit_Attr *)calloc(1, sizeof(Ecore_IMF_Preedit_Attr));
1106
attr->preedit_type = ECORE_IMF_PREEDIT_TYPE_SUB2;
1107
attr->start_index = begin_pos;
1108
attr->end_index = pos;
1109
*attrs = eina_list_append(*attrs, (void *)attr);
1113
delete [] attrs_flag;
1131
* isf_imf_context_preedit_string_get
1132
* @ctx: a #Ecore_IMF_Context
1133
* @str: the preedit string
1134
* @cursor_pos: the cursor position
1136
* This function will be called by Ecore IMF.
1138
* To get the preedit string of the input method.
1141
isf_imf_context_preedit_string_get(Ecore_IMF_Context *ctx, char** str, int *cursor_pos)
1143
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1145
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
1146
EINA_SAFETY_ON_NULL_RETURN(context_scim);
1147
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
1149
if (context_scim->impl->is_on)
1151
String mbs = utf8_wcstombs(context_scim->impl->preedit_string);
1156
*str = strdup(mbs.c_str());
1162
*cursor_pos = context_scim->impl->preedit_caret;
1175
* isf_imf_context_cursor_position_set
1176
* @ctx: a #Ecore_IMF_Context
1177
* @cursor_pos: New cursor position in characters.
1179
* This function will be called by Ecore IMF.
1181
* Notify the Input Method Context that a change in the cursor position has been made.
1184
isf_imf_context_cursor_position_set(Ecore_IMF_Context *ctx, int cursor_pos)
1186
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1188
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
1189
EINA_SAFETY_ON_NULL_RETURN(context_scim);
1190
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
1192
if (context_scim != _focused_ic)
1195
// Don't update spot location while updating preedit string.
1196
if (context_scim->impl->preedit_updating)
1199
if (context_scim->impl->cursor_pos != cursor_pos)
1200
context_scim->impl->cursor_pos = cursor_pos;
1204
* isf_imf_context_input_mode_set
1205
* @ctx: a #Ecore_IMF_Context
1206
* @input_mode: the input mode
1208
* This function will be called by Ecore IMF.
1210
* To set the input mode of input method. The definition of Ecore_IMF_Input_Mode
1211
* is in Ecore_IMF.h.
1214
isf_imf_context_input_mode_set(Ecore_IMF_Context *ctx, Ecore_IMF_Input_Mode input_mode)
1216
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1218
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
1219
EINA_SAFETY_ON_NULL_RETURN(context_scim);
1220
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
1222
context_scim->impl->input_mode = input_mode;
1226
* isf_imf_context_prediction_allow_set
1227
* @ctx: a #Ecore_IMF_Context
1228
* @use_prediction: Whether the IM context should use the prediction.
1230
* This function will be called by Ecore IMF.
1232
* Set whether the IM context should use the prediction.
1235
isf_imf_context_prediction_allow_set(Ecore_IMF_Context* ctx, Eina_Bool prediction)
1237
SCIM_DEBUG_FRONTEND(1) << __func__ << " = " << (prediction ? "true" : "false") << "...\n";
1239
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
1240
EINA_SAFETY_ON_NULL_RETURN(context_scim);
1241
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
1243
if (context_scim->impl->prediction_allow != prediction)
1244
context_scim->impl->prediction_allow = prediction;
1248
isf_imf_context_autocapital_type_set(Ecore_IMF_Context* ctx, Ecore_IMF_Autocapital_Type autocapital_type)
1250
SCIM_DEBUG_FRONTEND(1) << __func__ << " = " << autocapital_type << "...\n";
1252
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF *)ecore_imf_context_data_get(ctx);
1253
EINA_SAFETY_ON_NULL_RETURN(context_scim);
1254
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
1256
if (context_scim->impl->autocapital_type != autocapital_type)
1257
context_scim->impl->autocapital_type = autocapital_type;
1261
* isf_imf_context_filter_event
1262
* @ctx: a #Ecore_IMF_Context
1263
* @type: The type of event defined by Ecore_IMF_Event_Type.
1264
* @event: The event itself.
1265
* Return value: %TRUE if the input method handled the key event.
1267
* This function will be called by Ecore IMF.
1269
* Allow an Ecore Input Context to internally handle an event. If this function
1270
* returns 1, then no further processing should be done for this event. Input
1271
* methods must be able to accept all types of events (simply returning 0 if
1272
* the event was not handled), but there is no obligation of any events to be
1273
* submitted to this function.
1276
isf_imf_context_filter_event(Ecore_IMF_Context *ctx, Ecore_IMF_Event_Type type, Ecore_IMF_Event *event)
1278
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1280
EcoreIMFContextISF *ic = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
1281
EINA_SAFETY_ON_NULL_RETURN_VAL(ic, EINA_FALSE);
1282
EINA_SAFETY_ON_NULL_RETURN_VAL(ic->impl, EINA_FALSE);
1284
Eina_Bool ret = EINA_FALSE;
1287
if (type == ECORE_IMF_EVENT_KEY_DOWN)
1289
Ecore_IMF_Event_Key_Down *ev = (Ecore_IMF_Event_Key_Down *)event;
1290
scim_string_to_key(key, ev->key);
1291
key.mask |= _ecore_imf_modifier_to_scim_mask(ev->modifiers);
1292
key.mask |= _ecore_imf_lock_to_scim_mask(ev->locks);
1294
else if (type == ECORE_IMF_EVENT_KEY_UP)
1296
Ecore_IMF_Event_Key_Up *ev = (Ecore_IMF_Event_Key_Up *)event;
1297
scim_string_to_key(key, ev->key);
1298
key.mask = SCIM_KEY_ReleaseMask;
1299
key.mask |= _ecore_imf_modifier_to_scim_mask(ev->modifiers);
1300
key.mask |= _ecore_imf_lock_to_scim_mask(ev->locks);
1307
key.mask &= _valid_key_mask;
1309
_panel_client.prepare(ic->id);
1312
if (!filter_hotkeys(ic, key))
1314
if (!_focused_ic || !_focused_ic->impl->is_on ||
1315
!_focused_ic->impl->si->process_key_event(key))
1319
_panel_client.send();
1325
isf_imf_context_input_panel_show(Ecore_IMF_Context *ctx)
1327
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1329
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
1330
EINA_SAFETY_ON_NULL_RETURN(context_scim);
1331
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
1333
if (!ecore_x_display_get()) return;
1334
ecore_x_e_virtual_keyboard_state_set
1335
(context_scim->impl->client_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_ON);
1339
isf_imf_context_input_panel_hide(Ecore_IMF_Context *ctx)
1341
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1343
EcoreIMFContextISF *context_scim = (EcoreIMFContextISF*)ecore_imf_context_data_get(ctx);
1344
EINA_SAFETY_ON_NULL_RETURN(context_scim);
1345
EINA_SAFETY_ON_NULL_RETURN(context_scim->impl);
1347
if (!ecore_x_display_get()) return;
1348
ecore_x_e_virtual_keyboard_state_set
1349
(context_scim->impl->client_window, ECORE_X_VIRTUAL_KEYBOARD_STATE_OFF);
1352
/* Panel Slot functions */
1354
panel_slot_reload_config(int context EINA_UNUSED)
1356
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1361
panel_slot_exit(int /* context */)
1363
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1369
panel_slot_update_lookup_table_page_size(int context, int page_size)
1371
EcoreIMFContextISF *ic = find_ic(context);
1372
EINA_SAFETY_ON_NULL_RETURN(ic);
1373
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1375
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
1377
_panel_client.prepare(ic->id);
1378
ic->impl->si->update_lookup_table_page_size(page_size);
1379
_panel_client.send();
1383
panel_slot_lookup_table_page_up(int context)
1385
EcoreIMFContextISF *ic = find_ic(context);
1386
EINA_SAFETY_ON_NULL_RETURN(ic);
1387
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1389
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " ic=" << ic << "\n";
1391
_panel_client.prepare(ic->id);
1392
ic->impl->si->lookup_table_page_up();
1393
_panel_client.send();
1397
panel_slot_lookup_table_page_down(int context)
1399
EcoreIMFContextISF *ic = find_ic(context);
1400
EINA_SAFETY_ON_NULL_RETURN(ic);
1401
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1403
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " ic=" << ic << "\n";
1405
_panel_client.prepare(ic->id);
1406
ic->impl->si->lookup_table_page_down();
1407
_panel_client.send();
1411
panel_slot_trigger_property(int context, const String &property)
1413
EcoreIMFContextISF *ic = find_ic(context);
1414
EINA_SAFETY_ON_NULL_RETURN(ic);
1415
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1417
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " property=" << property << " ic=" << ic << "\n";
1419
_panel_client.prepare(ic->id);
1420
ic->impl->si->trigger_property(property);
1421
_panel_client.send();
1425
panel_slot_process_helper_event(int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
1427
EcoreIMFContextISF *ic = find_ic(context);
1428
EINA_SAFETY_ON_NULL_RETURN(ic);
1429
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1431
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " target=" << target_uuid
1432
<< " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << ic->impl << " ic-uuid="
1433
<< (ic->impl ? ic->impl->si->get_factory_uuid() : "" ) << "\n";
1435
if (ic->impl->si->get_factory_uuid() == target_uuid)
1437
_panel_client.prepare(ic->id);
1438
SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
1439
ic->impl->si->process_helper_event(helper_uuid, trans);
1440
_panel_client.send();
1445
panel_slot_move_preedit_caret(int context, int caret_pos)
1447
EcoreIMFContextISF *ic = find_ic(context);
1448
EINA_SAFETY_ON_NULL_RETURN(ic);
1449
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1451
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
1453
_panel_client.prepare(ic->id);
1454
ic->impl->si->move_preedit_caret(caret_pos);
1455
_panel_client.send();
1459
panel_slot_select_candidate(int context, int cand_index)
1461
EcoreIMFContextISF *ic = find_ic(context);
1462
EINA_SAFETY_ON_NULL_RETURN(ic);
1463
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1465
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
1467
_panel_client.prepare(ic->id);
1468
ic->impl->si->select_candidate(cand_index);
1469
_panel_client.send();
1473
panel_slot_process_key_event(int context, const KeyEvent &key)
1475
EcoreIMFContextISF *ic = find_ic(context);
1476
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " key=" << key.get_key_string() << " ic=" << ic << "\n";
1478
if (!ecore_x_display_get()) return;
1479
if (key.is_key_press())
1480
ecore_x_test_fake_key_press(key.get_key_string().c_str());
1484
panel_slot_commit_string(int context, const WideString &wstr)
1486
EcoreIMFContextISF *ic = find_ic(context);
1487
EINA_SAFETY_ON_NULL_RETURN(ic);
1489
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " str=" << utf8_wcstombs(wstr) << " ic=" << ic << "\n";
1491
if (_focused_ic != ic)
1494
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(wstr).c_str());
1498
panel_slot_forward_key_event(int context, const KeyEvent &key)
1500
EcoreIMFContextISF *ic = find_ic(context);
1501
EINA_SAFETY_ON_NULL_RETURN(ic);
1502
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1504
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " key=" << key.get_key_string() << " ic=" << ic << "\n";
1506
if (ic->impl->client_canvas)
1507
feed_key_event(ic->impl->client_canvas, key.get_key_string().c_str(), EINA_TRUE);
1511
panel_slot_request_help(int context)
1513
EcoreIMFContextISF *ic = find_ic(context);
1514
EINA_SAFETY_ON_NULL_RETURN(ic);
1516
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " ic=" << ic << "\n";
1518
_panel_client.prepare(ic->id);
1519
panel_req_show_help(ic);
1520
_panel_client.send();
1524
panel_slot_request_factory_menu(int context)
1526
EcoreIMFContextISF *ic = find_ic(context);
1527
EINA_SAFETY_ON_NULL_RETURN(ic);
1529
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " ic=" << ic << "\n";
1531
_panel_client.prepare(ic->id);
1532
panel_req_show_factory_menu(ic);
1533
_panel_client.send();
1537
panel_slot_change_factory(int context, const String &uuid)
1539
EcoreIMFContextISF *ic = find_ic(context);
1540
EINA_SAFETY_ON_NULL_RETURN(ic);
1541
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1543
SCIM_DEBUG_FRONTEND(1) << __func__ << " context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
1545
ic->impl->si->reset();
1546
_panel_client.prepare(ic->id);
1547
open_specific_factory(ic, uuid);
1548
_panel_client.send();
1551
/* Panel Requestion functions. */
1553
panel_req_show_help(EcoreIMFContextISF *ic)
1555
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1557
EINA_SAFETY_ON_NULL_RETURN(ic);
1558
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1562
help = String("Smart Common Input Method platform ") +
1563
//String(SCIM_VERSION) +
1564
String("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n");
1566
IMEngineFactoryPointer sf = _backend->get_factory(ic->impl->si->get_factory_uuid());
1569
help += utf8_wcstombs(sf->get_name());
1570
help += String(":\n\n");
1572
help += utf8_wcstombs(sf->get_help());
1573
help += String("\n\n");
1575
help += utf8_wcstombs(sf->get_credits());
1577
_panel_client.show_help(ic->id, help);
1581
panel_req_show_factory_menu(EcoreIMFContextISF *ic)
1583
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1585
std::vector<IMEngineFactoryPointer> factories;
1586
std::vector <PanelFactoryInfo> menu;
1588
_backend->get_factories_for_encoding(factories, "UTF-8");
1590
for (size_t i = 0; i < factories.size(); ++ i)
1592
menu.push_back(PanelFactoryInfo(
1593
factories [i]->get_uuid(),
1594
utf8_wcstombs(factories [i]->get_name()),
1595
factories [i]->get_language(),
1596
factories [i]->get_icon_file()));
1600
_panel_client.show_factory_menu(ic->id, menu);
1604
panel_req_update_factory_info(EcoreIMFContextISF *ic)
1606
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1608
EINA_SAFETY_ON_NULL_RETURN(ic);
1609
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1611
if (ic != _focused_ic)
1614
PanelFactoryInfo info;
1615
if (ic->impl->is_on)
1617
IMEngineFactoryPointer sf = _backend->get_factory(ic->impl->si->get_factory_uuid());
1619
info = PanelFactoryInfo(sf->get_uuid(), utf8_wcstombs(sf->get_name()), sf->get_language(), sf->get_icon_file());
1623
info = PanelFactoryInfo(String(""), String("English/Keyboard"), String("C"), "");
1625
_panel_client.update_factory_info(ic->id, info);
1629
panel_req_focus_in(EcoreIMFContextISF *ic)
1631
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1633
_panel_client.focus_in(ic->id, ic->impl->si->get_factory_uuid());
1637
panel_req_update_spot_location(EcoreIMFContextISF *ic)
1639
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1641
_panel_client.update_spot_location(ic->id, ic->impl->cursor_x, ic->impl->cursor_y);
1645
filter_hotkeys(EcoreIMFContextISF *ic, const KeyEvent &key)
1647
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1651
_frontend_hotkey_matcher.push_key_event(key);
1652
_imengine_hotkey_matcher.push_key_event(key);
1654
FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result();
1656
if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER)
1658
if (!ic->impl->is_on)
1664
else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON)
1666
if (!ic->impl->is_on)
1670
else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF)
1672
if (ic->impl->is_on)
1676
else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY)
1678
open_next_factory(ic);
1681
else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY)
1683
open_previous_factory(ic);
1686
else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU)
1688
panel_req_show_factory_menu(ic);
1691
else if (_imengine_hotkey_matcher.is_matched())
1693
String sfid = _imengine_hotkey_matcher.get_match_result();
1694
open_specific_factory(ic, sfid);
1701
panel_initialize(void)
1703
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1705
String display_name;
1707
const char *p = getenv("DISPLAY");
1708
if (p) display_name = String(p);
1711
if (_panel_client.open_connection(_config->get_name(), display_name) >= 0)
1713
int fd = _panel_client.get_connection_number();
1715
_panel_iochannel_read_handler = ecore_main_fd_handler_add(fd, ECORE_FD_READ, panel_iochannel_handler, NULL, NULL, NULL);
1717
SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
1721
std::cerr << "panel_initialize() failed!!!\n";
1728
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1730
_panel_client.close_connection();
1732
if (_panel_iochannel_read_handler)
1734
ecore_main_fd_handler_del(_panel_iochannel_read_handler);
1735
_panel_iochannel_read_handler = 0;
1738
if (_panel_iochannel_err_handler)
1740
ecore_main_fd_handler_del(_panel_iochannel_err_handler);
1741
_panel_iochannel_err_handler = 0;
1746
panel_iochannel_handler(void *data EINA_UNUSED, Ecore_Fd_Handler *fd_handler)
1748
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1750
if (fd_handler == _panel_iochannel_read_handler)
1752
if (!_panel_client.filter_event())
1756
return ECORE_CALLBACK_CANCEL;
1759
else if (fd_handler == _panel_iochannel_err_handler)
1763
return ECORE_CALLBACK_CANCEL;
1765
return ECORE_CALLBACK_RENEW;
1769
turn_on_ic(EcoreIMFContextISF *ic)
1771
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1773
EINA_SAFETY_ON_NULL_RETURN(ic);
1774
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1776
if (!ic->impl->is_on)
1778
ic->impl->is_on = true;
1780
if (ic == _focused_ic)
1782
panel_req_focus_in(ic);
1783
panel_req_update_spot_location(ic);
1784
panel_req_update_factory_info(ic);
1785
_panel_client.turn_on(ic->id);
1786
_panel_client.hide_preedit_string(ic->id);
1787
_panel_client.hide_aux_string(ic->id);
1788
_panel_client.hide_lookup_table(ic->id);
1789
ic->impl->si->focus_in();
1792
//Record the IC on/off status
1793
if (_shared_input_method)
1794
_config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
1796
if (ic->impl->use_preedit && ic->impl->preedit_string.length())
1798
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
1799
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1800
ic->impl->preedit_started = true;
1806
turn_off_ic(EcoreIMFContextISF *ic)
1808
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1810
EINA_SAFETY_ON_NULL_RETURN(ic);
1811
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1813
if (ic->impl->is_on)
1815
ic->impl->is_on = false;
1817
if (ic == _focused_ic)
1819
ic->impl->si->focus_out();
1821
panel_req_update_factory_info(ic);
1822
_panel_client.turn_off(ic->id);
1825
//Record the IC on/off status
1826
if (_shared_input_method)
1827
_config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
1829
if (ic->impl->use_preedit && ic->impl->preedit_string.length())
1831
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
1832
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
1833
ic->impl->preedit_started = false;
1839
set_ic_capabilities(EcoreIMFContextISF *ic)
1841
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1843
EINA_SAFETY_ON_NULL_RETURN(ic);
1844
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
1846
unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
1848
if (!_on_the_spot || !ic->impl->use_preedit)
1849
cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
1851
ic->impl->si->update_client_capabilities(cap);
1855
check_socket_frontend(void)
1857
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
1859
SocketAddress address;
1860
SocketClient client;
1864
address.set_address(scim_get_default_socket_frontend_address());
1866
if (!client.connect(address))
1869
if (!scim_socket_open_connection(magic,
1870
String("ConnectionTester"),
1871
String("SocketFrontEnd"),
1882
std::vector<String> config_list;
1883
std::vector<String> engine_list;
1884
std::vector<String> load_engine_list;
1886
std::vector<String>::iterator it;
1888
bool manual = false;
1892
String config_module_name = "simple";
1894
SCIM_DEBUG_FRONTEND(1) << "Initializing Ecore SCIM IMModule...\n";
1896
// Get system language.
1897
_language = scim_get_locale_language(scim_get_current_locale());
1901
// If no Socket FrontEnd is running, then launch one.
1902
// And set manual to false.
1903
bool check_result = check_socket_frontend();
1906
std::cerr << "Launching a SCIM daemon with Socket FrontEnd...\n";
1908
scim_get_imengine_module_list(engine_list);
1910
for (it = engine_list.begin(); it != engine_list.end(); it++)
1912
if (*it != "socket")
1913
load_engine_list.push_back(*it);
1916
const char *new_argv [] = { "--no-stay", 0 };
1919
(load_engine_list.size() ? scim_combine_string_list(load_engine_list, ',') : "none"),
1925
// If there is one Socket FrontEnd running and it's not manual mode,
1926
// then just use this Socket Frontend.
1929
for (int i = 0; i < 200; ++i)
1933
config_module_name = "socket";
1934
load_engine_list.clear();
1935
load_engine_list.push_back("socket");
1939
check_result = check_socket_frontend();
1944
if (config_module_name != "dummy")
1946
//load config module
1947
SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
1948
_config_module = new ConfigModule(config_module_name);
1950
//create config instance
1951
if (_config_module != NULL && _config_module->valid())
1952
_config = _config_module->create_config();
1957
SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
1959
if (_config_module) delete _config_module;
1960
_config_module = NULL;
1962
_config = new DummyConfig();
1963
config_module_name = "dummy";
1966
reload_config_callback(_config);
1967
_config->signal_connect_reload(slot(reload_config_callback));
1970
_backend = new CommonBackEnd(_config, load_engine_list.size() ? load_engine_list : engine_list);
1972
if (_backend.null())
1973
std::cerr << "Cannot create BackEnd Object!\n";
1975
_fallback_factory = _backend->get_factory(SCIM_COMPOSE_KEY_FACTORY_UUID);
1977
if (_fallback_factory.null())
1978
_fallback_factory = new DummyIMEngineFactory();
1980
_fallback_instance = _fallback_factory->create_instance(String("UTF-8"), 0);
1981
_fallback_instance->signal_connect_commit_string(slot(fallback_commit_string_cb));
1983
// Attach Panel Client signal.
1984
_panel_client.signal_connect_reload_config (slot(panel_slot_reload_config));
1985
_panel_client.signal_connect_exit (slot(panel_slot_exit));
1986
_panel_client.signal_connect_update_lookup_table_page_size(slot(panel_slot_update_lookup_table_page_size));
1987
_panel_client.signal_connect_lookup_table_page_up (slot(panel_slot_lookup_table_page_up));
1988
_panel_client.signal_connect_lookup_table_page_down (slot(panel_slot_lookup_table_page_down));
1989
_panel_client.signal_connect_trigger_property (slot(panel_slot_trigger_property));
1990
_panel_client.signal_connect_process_helper_event (slot(panel_slot_process_helper_event));
1991
_panel_client.signal_connect_move_preedit_caret (slot(panel_slot_move_preedit_caret));
1992
_panel_client.signal_connect_select_candidate (slot(panel_slot_select_candidate));
1993
_panel_client.signal_connect_process_key_event (slot(panel_slot_process_key_event));
1994
_panel_client.signal_connect_commit_string (slot(panel_slot_commit_string));
1995
_panel_client.signal_connect_forward_key_event (slot(panel_slot_forward_key_event));
1996
_panel_client.signal_connect_request_help (slot(panel_slot_request_help));
1997
_panel_client.signal_connect_request_factory_menu (slot(panel_slot_request_factory_menu));
1998
_panel_client.signal_connect_change_factory (slot(panel_slot_change_factory));
2000
if (!panel_initialize())
2001
std::cerr << "Ecore IM Module: Cannot connect to Panel!\n";
2007
SCIM_DEBUG_FRONTEND(1) << "Finalizing Ecore ISF IMModule...\n";
2009
// Reset this first so that the shared instance could be released correctly afterwards.
2010
_default_instance.reset();
2012
SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2013
while (_used_ic_impl_list)
2015
// In case in "shared input method" mode,
2016
// all contexts share only one instance,
2017
// so we need point the reference pointer correctly before finalizing.
2018
_used_ic_impl_list->si->set_frontend_data(static_cast <void*>(_used_ic_impl_list->parent));
2019
isf_imf_context_del(_used_ic_impl_list->parent->ctx);
2022
delete_all_ic_impl();
2024
_fallback_instance.reset();
2025
_fallback_factory.reset();
2027
SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
2030
SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2035
SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
2036
delete _config_module;
2043
_scim_initialized = false;
2049
open_next_factory(EcoreIMFContextISF *ic)
2051
SCIM_DEBUG_FRONTEND(2) << __func__ << " context=" << ic->id << "\n";
2052
IMEngineFactoryPointer sf = _backend->get_next_factory("", "UTF-8", ic->impl->si->get_factory_uuid());
2057
ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
2058
ic->impl->si->set_frontend_data(static_cast <void*>(ic));
2059
ic->impl->preedit_string = WideString();
2060
ic->impl->preedit_caret = 0;
2061
attach_instance(ic->impl->si);
2062
_backend->set_default_factory(_language, sf->get_uuid());
2063
_panel_client.register_input_context(ic->id, sf->get_uuid());
2064
set_ic_capabilities(ic);
2067
if (_shared_input_method)
2069
_default_instance = ic->impl->si;
2070
ic->impl->shared_si = true;
2076
open_previous_factory(EcoreIMFContextISF *ic)
2078
EINA_SAFETY_ON_NULL_RETURN(ic);
2079
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
2081
SCIM_DEBUG_FRONTEND(2) << __func__ << " context=" << ic->id << "\n";
2082
IMEngineFactoryPointer sf = _backend->get_previous_factory("", "UTF-8", ic->impl->si->get_factory_uuid());
2087
ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
2088
ic->impl->si->set_frontend_data(static_cast <void*>(ic));
2089
ic->impl->preedit_string = WideString();
2090
ic->impl->preedit_caret = 0;
2091
attach_instance(ic->impl->si);
2092
_backend->set_default_factory(_language, sf->get_uuid());
2093
_panel_client.register_input_context(ic->id, sf->get_uuid());
2094
set_ic_capabilities(ic);
2097
if (_shared_input_method)
2099
_default_instance = ic->impl->si;
2100
ic->impl->shared_si = true;
2106
open_specific_factory(EcoreIMFContextISF *ic,
2109
EINA_SAFETY_ON_NULL_RETURN(ic);
2110
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
2112
SCIM_DEBUG_FRONTEND(2) << __func__ << " context=" << ic->id << "\n";
2114
// The same input method is selected, just turn on the IC.
2115
if (ic->impl->si->get_factory_uuid() == uuid)
2121
IMEngineFactoryPointer sf = _backend->get_factory(uuid);
2123
if (uuid.length() && !sf.null())
2126
ic->impl->si = sf->create_instance("UTF-8", ic->impl->si->get_id());
2127
ic->impl->si->set_frontend_data(static_cast <void*>(ic));
2128
ic->impl->preedit_string = WideString();
2129
ic->impl->preedit_caret = 0;
2130
attach_instance(ic->impl->si);
2131
_backend->set_default_factory(_language, sf->get_uuid());
2132
_panel_client.register_input_context(ic->id, sf->get_uuid());
2133
set_ic_capabilities(ic);
2136
if (_shared_input_method)
2138
_default_instance = ic->impl->si;
2139
ic->impl->shared_si = true;
2144
// turn_off_ic comment out panel_req_update_factory_info()
2146
if (ic->impl->is_on)
2148
ic->impl->is_on = false;
2150
if (ic == _focused_ic)
2152
ic->impl->si->focus_out();
2154
panel_req_update_factory_info(ic);
2155
_panel_client.turn_off(ic->id);
2158
//Record the IC on/off status
2159
if (_shared_input_method)
2160
_config->write(String(SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2162
if (ic->impl->use_preedit && ic->impl->preedit_string.length())
2164
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2165
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2166
ic->impl->preedit_started = false;
2172
static void initialize_modifier_bits(Display *display)
2174
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2176
if (__current_display == display)
2179
__current_display = display;
2183
__current_alt_mask = Mod1Mask;
2184
__current_meta_mask = ShiftMask | Mod1Mask;
2185
__current_super_mask = 0;
2186
__current_hyper_mask = 0;
2187
__current_numlock_mask = Mod2Mask;
2191
XModifierKeymap *mods = NULL;
2193
::KeyCode ctrl_l = XKeysymToKeycode(display, XK_Control_L);
2194
::KeyCode ctrl_r = XKeysymToKeycode(display, XK_Control_R);
2195
::KeyCode meta_l = XKeysymToKeycode(display, XK_Meta_L);
2196
::KeyCode meta_r = XKeysymToKeycode(display, XK_Meta_R);
2197
::KeyCode alt_l = XKeysymToKeycode(display, XK_Alt_L);
2198
::KeyCode alt_r = XKeysymToKeycode(display, XK_Alt_R);
2199
::KeyCode super_l = XKeysymToKeycode(display, XK_Super_L);
2200
::KeyCode super_r = XKeysymToKeycode(display, XK_Super_R);
2201
::KeyCode hyper_l = XKeysymToKeycode(display, XK_Hyper_L);
2202
::KeyCode hyper_r = XKeysymToKeycode(display, XK_Hyper_R);
2203
::KeyCode numlock = XKeysymToKeycode(display, XK_Num_Lock);
2207
mods = XGetModifierMapping(display);
2211
__current_alt_mask = 0;
2212
__current_meta_mask = 0;
2213
__current_super_mask = 0;
2214
__current_hyper_mask = 0;
2215
__current_numlock_mask = 0;
2217
/* We skip the first three sets for Shift, Lock, and Control. The
2218
remaining sets are for Mod1, Mod2, Mod3, Mod4, and Mod5. */
2219
for (i = 3; i < 8; i++)
2221
for (j = 0; j < mods->max_keypermod; j++)
2223
::KeyCode code = mods->modifiermap [i * mods->max_keypermod + j];
2224
if (! code) continue;
2225
if (code == alt_l || code == alt_r)
2226
__current_alt_mask |= (1 << i);
2227
else if (code == meta_l || code == meta_r)
2228
__current_meta_mask |= (1 << i);
2229
else if (code == super_l || code == super_r)
2230
__current_super_mask |= (1 << i);
2231
else if (code == hyper_l || code == hyper_r)
2232
__current_hyper_mask |= (1 << i);
2233
else if (code == numlock)
2234
__current_numlock_mask |= (1 << i);
2238
/* Check whether there is a combine keys mapped to Meta */
2239
if (__current_meta_mask == 0)
2243
KeySym keysym_l, keysym_r;
2245
xkey.type = KeyPress;
2246
xkey.display = display;
2248
xkey.send_event = False;
2249
xkey.x = xkey.y = xkey.x_root = xkey.y_root = 0;
2251
xkey.same_screen = False;
2252
xkey.subwindow = None;
2254
xkey.root = DefaultRootWindow(display);
2255
xkey.state = ShiftMask;
2257
xkey.keycode = meta_l;
2258
XLookupString(&xkey, buf, 32, &keysym_l, 0);
2259
xkey.keycode = meta_r;
2260
XLookupString(&xkey, buf, 32, &keysym_r, 0);
2262
if ((meta_l == alt_l && keysym_l == XK_Meta_L) || (meta_r == alt_r && keysym_r == XK_Meta_R))
2263
__current_meta_mask = ShiftMask + __current_alt_mask;
2264
else if ((meta_l == ctrl_l && keysym_l == XK_Meta_L) || (meta_r == ctrl_r && keysym_r == XK_Meta_R))
2265
__current_meta_mask = ShiftMask + ControlMask;
2268
XFreeModifiermap(mods);
2271
static unsigned int scim_x11_keymask_scim_to_x11(Display *display, uint16 scimkeymask)
2273
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2275
unsigned int state = 0;
2277
initialize_modifier_bits(display);
2279
if (scimkeymask & SCIM_KEY_ShiftMask) state |= ShiftMask;
2280
if (scimkeymask & SCIM_KEY_CapsLockMask) state |= LockMask;
2281
if (scimkeymask & SCIM_KEY_ControlMask) state |= ControlMask;
2282
if (scimkeymask & SCIM_KEY_AltMask) state |= __current_alt_mask;
2283
if (scimkeymask & SCIM_KEY_MetaMask) state |= __current_meta_mask;
2284
if (scimkeymask & SCIM_KEY_SuperMask) state |= __current_super_mask;
2285
if (scimkeymask & SCIM_KEY_HyperMask) state |= __current_hyper_mask;
2286
if (scimkeymask & SCIM_KEY_NumLockMask) state |= __current_numlock_mask;
2291
static XKeyEvent createKeyEvent(Display *display, Window &win,
2292
Window &winRoot, bool press,
2293
int keysym, int modifiers)
2295
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2299
event.display = display;
2301
event.root = winRoot;
2302
event.subwindow = None;
2303
event.time = CurrentTime;
2308
event.same_screen = EINA_TRUE;
2309
event.state = modifiers;
2310
event.keycode = XKeysymToKeycode(display, keysym);
2312
event.type = KeyPress;
2314
event.type = KeyRelease;
2315
event.send_event = EINA_FALSE;
2321
static void _x_send_key_event(const KeyEvent &key)
2323
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2325
// Obtain the X11 display.
2326
Display *display = (Display *)ecore_x_display_get();
2327
EINA_SAFETY_ON_NULL_RETURN(display);
2329
// Get the root window for the current display.
2332
// Find the window which has the current keyboard focus.
2333
Window winFocus = 0;
2334
int revert = RevertToParent;
2336
XGetInputFocus(display, &winFocus, &revert);
2338
unsigned int modifier = scim_x11_keymask_scim_to_x11(display, key.mask);
2340
if (key.is_key_press())
2342
event = createKeyEvent(display, winFocus, winRoot, true, key.code, modifier);
2343
XSendEvent(event.display, event.window, True, KeyPressMask, (XEvent *)&event);
2347
event = createKeyEvent(display, winFocus, winRoot, false, key.code, modifier);
2348
XSendEvent(event.display, event.window, True, KeyReleaseMask, (XEvent *)&event);
2353
attach_instance(const IMEngineInstancePointer &si)
2355
si->signal_connect_show_preedit_string(
2356
slot(slot_show_preedit_string));
2357
si->signal_connect_show_aux_string(
2358
slot(slot_show_aux_string));
2359
si->signal_connect_show_lookup_table(
2360
slot(slot_show_lookup_table));
2362
si->signal_connect_hide_preedit_string(
2363
slot(slot_hide_preedit_string));
2364
si->signal_connect_hide_aux_string(
2365
slot(slot_hide_aux_string));
2366
si->signal_connect_hide_lookup_table(
2367
slot(slot_hide_lookup_table));
2369
si->signal_connect_update_preedit_caret(
2370
slot(slot_update_preedit_caret));
2371
si->signal_connect_update_preedit_string(
2372
slot(slot_update_preedit_string));
2373
si->signal_connect_update_aux_string(
2374
slot(slot_update_aux_string));
2375
si->signal_connect_update_lookup_table(
2376
slot(slot_update_lookup_table));
2378
si->signal_connect_commit_string(
2379
slot(slot_commit_string));
2381
si->signal_connect_forward_key_event(
2382
slot(slot_forward_key_event));
2384
si->signal_connect_register_properties(
2385
slot(slot_register_properties));
2387
si->signal_connect_update_property(
2388
slot(slot_update_property));
2390
si->signal_connect_beep(
2393
si->signal_connect_start_helper(
2394
slot(slot_start_helper));
2396
si->signal_connect_stop_helper(
2397
slot(slot_stop_helper));
2399
si->signal_connect_send_helper_event(
2400
slot(slot_send_helper_event));
2402
si->signal_connect_get_surrounding_text(
2403
slot(slot_get_surrounding_text));
2405
si->signal_connect_delete_surrounding_text(
2406
slot(slot_delete_surrounding_text));
2409
// Implementation of slot functions
2411
slot_show_preedit_string(IMEngineInstanceBase *si)
2413
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2415
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2416
EINA_SAFETY_ON_NULL_RETURN(ic);
2417
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
2419
if (_focused_ic != ic)
2422
if (ic->impl->use_preedit)
2424
if (!ic->impl->preedit_started)
2426
ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2427
ic->impl->preedit_started = true;
2431
_panel_client.show_preedit_string(ic->id);
2435
slot_show_aux_string(IMEngineInstanceBase *si)
2437
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2439
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2440
EINA_SAFETY_ON_NULL_RETURN(ic);
2442
if (_focused_ic == ic)
2443
_panel_client.show_aux_string(ic->id);
2447
slot_show_lookup_table(IMEngineInstanceBase *si)
2449
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2451
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2452
EINA_SAFETY_ON_NULL_RETURN(ic);
2454
if (_focused_ic == ic)
2455
_panel_client.show_lookup_table(ic->id);
2459
slot_hide_preedit_string(IMEngineInstanceBase *si)
2461
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2463
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2464
EINA_SAFETY_ON_NULL_RETURN(ic);
2465
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
2467
if (_focused_ic != ic)
2471
if (ic->impl->preedit_string.length())
2473
ic->impl->preedit_string = WideString();
2474
ic->impl->preedit_caret = 0;
2475
ic->impl->preedit_attrlist.clear();
2478
if (ic->impl->use_preedit)
2482
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2484
if (ic->impl->preedit_started)
2486
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_END, NULL);
2487
ic->impl->preedit_started = false;
2491
_panel_client.hide_preedit_string(ic->id);
2495
slot_hide_aux_string(IMEngineInstanceBase *si)
2497
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2499
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2500
EINA_SAFETY_ON_NULL_RETURN(ic);
2502
if (_focused_ic == ic)
2503
_panel_client.hide_aux_string(ic->id);
2507
slot_hide_lookup_table(IMEngineInstanceBase *si)
2509
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2511
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2512
EINA_SAFETY_ON_NULL_RETURN(ic);
2514
if (_focused_ic == ic)
2515
_panel_client.hide_lookup_table(ic->id);
2519
slot_update_preedit_caret(IMEngineInstanceBase *si, int caret)
2521
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2523
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2524
EINA_SAFETY_ON_NULL_RETURN(ic);
2525
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
2527
if (_focused_ic == ic && ic->impl->preedit_caret != caret)
2529
ic->impl->preedit_caret = caret;
2530
if (ic->impl->use_preedit)
2532
if (!ic->impl->preedit_started)
2534
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2535
ic->impl->preedit_started = true;
2537
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2540
_panel_client.update_preedit_caret(ic->id, caret);
2545
slot_update_preedit_string(IMEngineInstanceBase *si,
2546
const WideString & str,
2547
const AttributeList & attrs)
2549
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2551
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2552
EINA_SAFETY_ON_NULL_RETURN(ic);
2553
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
2555
if (_focused_ic == ic && (ic->impl->preedit_string != str || str.length()))
2557
ic->impl->preedit_string = str;
2558
ic->impl->preedit_attrlist = attrs;
2559
if (ic->impl->use_preedit)
2561
if (!ic->impl->preedit_started)
2563
ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_START, NULL);
2564
ic->impl->preedit_started = true;
2566
ic->impl->preedit_caret = str.length();
2567
ic->impl->preedit_updating = true;
2568
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_PREEDIT_CHANGED, NULL);
2569
ic->impl->preedit_updating = false;
2573
_panel_client.update_preedit_string(ic->id, str, attrs);
2579
slot_update_aux_string(IMEngineInstanceBase *si,
2580
const WideString & str,
2581
const AttributeList & attrs)
2583
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2585
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2586
EINA_SAFETY_ON_NULL_RETURN(ic);
2588
if (_focused_ic == ic)
2589
_panel_client.update_aux_string(ic->id, str, attrs);
2593
slot_commit_string(IMEngineInstanceBase *si,
2594
const WideString & str)
2596
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2598
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2599
EINA_SAFETY_ON_NULL_RETURN(ic);
2600
EINA_SAFETY_ON_NULL_RETURN(ic->ctx);
2602
ecore_imf_context_event_callback_call(ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(str).c_str());
2606
slot_forward_key_event(IMEngineInstanceBase *si,
2607
const KeyEvent & key)
2609
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2611
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2612
EINA_SAFETY_ON_NULL_RETURN(ic);
2614
if (_focused_ic == ic)
2616
if (!_fallback_instance->process_key_event(key))
2617
_x_send_key_event(key);
2622
slot_update_lookup_table(IMEngineInstanceBase *si,
2623
const LookupTable & table)
2625
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2627
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2628
EINA_SAFETY_ON_NULL_RETURN(ic);
2630
if (_focused_ic == ic)
2631
_panel_client.update_lookup_table(ic->id, table);
2635
slot_register_properties(IMEngineInstanceBase *si,
2636
const PropertyList & properties)
2638
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2640
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2641
EINA_SAFETY_ON_NULL_RETURN(ic);
2643
if (_focused_ic == ic)
2644
_panel_client.register_properties(ic->id, properties);
2648
slot_update_property(IMEngineInstanceBase *si,
2649
const Property & property)
2651
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2653
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2654
EINA_SAFETY_ON_NULL_RETURN(ic);
2656
if (_focused_ic == ic)
2657
_panel_client.update_property(ic->id, property);
2661
slot_beep(IMEngineInstanceBase *si)
2663
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2665
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2666
EINA_SAFETY_ON_NULL_RETURN(ic);
2668
if (!ecore_x_display_get()) return;
2669
if (_focused_ic == ic)
2674
slot_start_helper(IMEngineInstanceBase *si,
2675
const String &helper_uuid)
2677
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2678
EINA_SAFETY_ON_NULL_RETURN(ic);
2679
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
2681
SCIM_DEBUG_FRONTEND(1) << __func__ << " helper= " << helper_uuid << " context="
2682
<< ic->id << " ic=" << ic
2683
<< " ic-uuid=" << ic->impl->si->get_factory_uuid() << "...\n";
2685
_panel_client.start_helper(ic->id, helper_uuid);
2689
slot_stop_helper(IMEngineInstanceBase *si,
2690
const String &helper_uuid)
2692
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2693
EINA_SAFETY_ON_NULL_RETURN(ic);
2695
SCIM_DEBUG_FRONTEND(1) << __func__ << " helper= " << helper_uuid << " context=" << ic->id << " ic=" << ic << "...\n";
2697
_panel_client.stop_helper(ic->id, helper_uuid);
2701
slot_send_helper_event(IMEngineInstanceBase *si,
2702
const String &helper_uuid,
2703
const Transaction &trans)
2705
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2706
EINA_SAFETY_ON_NULL_RETURN(ic);
2707
EINA_SAFETY_ON_NULL_RETURN(ic->impl);
2709
SCIM_DEBUG_FRONTEND(1) << __func__ << " helper= " << helper_uuid << " context="
2710
<< ic->id << " ic=" << ic
2711
<< " ic-uuid=" << ic->impl->si->get_factory_uuid() << "...\n";
2713
_panel_client.send_helper_event(ic->id, helper_uuid, trans);
2717
slot_get_surrounding_text(IMEngineInstanceBase *si,
2723
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2725
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2726
EINA_SAFETY_ON_NULL_RETURN_VAL(ic, false);
2727
EINA_SAFETY_ON_NULL_RETURN_VAL(ic->impl, false);
2729
if (_focused_ic != ic)
2732
char *surrounding = NULL;
2734
if (ecore_imf_context_surrounding_get(_focused_ic->ctx, &surrounding, &cursor_index))
2736
SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
2737
SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
2741
if (cursor_index < 0)
2748
WideString before(utf8_mbstowcs(String(surrounding, surrounding + cursor_index)));
2749
WideString after(utf8_mbstowcs(String(surrounding + cursor_index)));
2754
if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length())
2755
before = WideString(before.begin() + (before.length() - maxlen_before), before.end());
2756
else if (maxlen_before == 0) before = WideString();
2757
if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length())
2758
after = WideString(after.begin(), after.begin() + maxlen_after);
2759
else if (maxlen_after == 0) after = WideString();
2760
text = before + after;
2761
cursor = before.length();
2769
slot_delete_surrounding_text(IMEngineInstanceBase *si,
2773
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2775
EcoreIMFContextISF *ic = static_cast<EcoreIMFContextISF *>(si->get_frontend_data());
2776
EINA_SAFETY_ON_NULL_RETURN_VAL(ic, false);
2778
if (_focused_ic != ic)
2781
Ecore_IMF_Event_Delete_Surrounding ev;
2782
ev.ctx = _focused_ic->ctx;
2785
ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_DELETE_SURROUNDING, &ev);
2791
reload_config_callback(const ConfigPointer &config)
2793
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2795
_frontend_hotkey_matcher.load_hotkeys(config);
2796
_imengine_hotkey_matcher.load_hotkeys(config);
2800
scim_string_to_key(key,
2801
config->read(String(SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
2802
String("Shift+Control+Alt+Lock")));
2804
_valid_key_mask = (key.mask > 0)?(key.mask):0xFFFF;
2805
_valid_key_mask |= SCIM_KEY_ReleaseMask;
2806
// Special treatment for two backslash keys on jp106 keyboard.
2807
_valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
2809
_on_the_spot = config->read(String(SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
2810
_shared_input_method = config->read(String(SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
2812
// Get keyboard layout setting
2813
// Flush the global config first, in order to load the new configs from disk.
2814
scim_global_config_flush();
2816
_keyboard_layout = scim_get_default_keyboard_layout();
2820
fallback_commit_string_cb(IMEngineInstanceBase *si EINA_UNUSED,
2821
const WideString &str)
2823
SCIM_DEBUG_FRONTEND(1) << __func__ << "...\n";
2827
ecore_imf_context_event_callback_call(_focused_ic->ctx, ECORE_IMF_CALLBACK_COMMIT, (void *)utf8_wcstombs(str).c_str());