1 /** @file gtkimcontextscim.cpp
2 * @brief immodule for GTK2.
4 /* ISF is based on SCIM 1.4.7 and extended for supporting more mobile fitable. */
7 * Smart Common Input Method
9 * Copyright (c) 2002-2005 James Su <suzhe@tsinghua.org.cn>
12 * This library is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU Lesser General Public
14 * License as published by the Free Software Foundation; either
15 * version 2 of the License, or (at your option) any later version.
17 * This library is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public
23 * License along with this program; if not, write to the
24 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
25 * Boston, MA 02111-1307 USA
27 * $Id: gtkimcontextscim.cpp,v 1.170.2.13 2007/06/16 06:23:38 suzhe Exp $
30 #define Uses_SCIM_DEBUG
31 #define Uses_SCIM_BACKEND
32 #define Uses_SCIM_IMENGINE
33 #define Uses_SCIM_IMENGINE_MODULE
34 #define Uses_SCIM_HELPER_MODULE
35 #define Uses_SCIM_CONFIG
36 #define Uses_SCIM_CONFIG_MODULE
37 #define Uses_SCIM_CONFIG_PATH
38 #define Uses_SCIM_TRANSACTION
39 #define Uses_SCIM_HOTKEY
40 #define Uses_SCIM_PANEL_CLIENT
44 #define Uses_STL_IOSTREAM
45 #define Uses_SCIM_UTILITY
47 #include <sys/types.h>
53 #include <gdk/gdkkeysyms.h>
55 #undef GDK_WINDOWING_X11
56 #ifdef GDK_WINDOWING_X11
59 #include <X11/keysym.h>
63 #include <sys/times.h>
64 static struct timeval _scim_start;
66 #include "scim_private.h"
69 #ifdef GDK_WINDOWING_X11
70 #include "scim_x11_utils.h"
75 #include "gtkimcontextscim.h"
77 //#define USING_ISF_MAINWINDOW_AUTOSCROLL
80 #define GTK_TYPE_IM_CONTEXT_SCIM _gtk_type_im_context_scim
81 #define GTK_IM_CONTEXT_SCIM(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_IM_CONTEXT_SCIM, GtkIMContextSCIM))
82 #define GTK_IM_CONTEXT_SCIM_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_IM_CONTEXT_SCIM, GtkIMContextSCIMClass))
83 #define GTK_IS_IM_CONTEXT_SCIM(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_IM_CONTEXT_SCIM))
84 #define GTK_IS_IM_CONTEXT_SCIM_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_IM_CONTEXT_SCIM))
85 #define GTK_IM_CONTEXT_SCIM_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_IM_CONTEXT_SCIM, GtkIMContextSCIMClass))
87 #define SCIM_CONFIG_FRONTEND_GTK_IMMODULE_USE_KEY_SNOOPER "/FrontEnd/GtkIMModule/UseKeySnooper"
88 #define ISE_KEY_FLUSH 0x8001
90 static void gettime (const char* str)
93 double clock_tiks = (double)sysconf (_SC_CLK_TCK);
94 clock_t times_tiks = times (&tiks_buf);
95 double times_secs = (double)times_tiks / clock_tiks;
96 double utime = (double)tiks_buf.tms_utime / clock_tiks;
97 double stime = (double)tiks_buf.tms_stime / clock_tiks;
98 printf ("Times: %3f \t User: %.3f \t System: %.3f \n", (double)times_secs, (double)utime , (double)stime);
102 static void print_time (const char *str_info)
105 struct timeval current_time;
108 gettimeofday (¤t_time, NULL);
109 used_time = 1000000 * (current_time.tv_sec - _scim_start.tv_sec) + current_time.tv_usec - _scim_start.tv_usec;
110 printf (mzc_red "%s : %d usec" mzc_normal ".\n", str_info, used_time);
111 //printf ("Current time : %d sec %d usec\n", current_time.tv_sec, current_time.tv_usec);
117 struct _GtkIMContextSCIMImpl
119 GtkIMContextSCIM *parent;
120 IMEngineInstancePointer si;
121 GdkWindow *client_window;
122 WideString preedit_string;
123 AttributeList preedit_attrlist;
128 gboolean use_preedit;
131 bool preedit_started;
132 bool preedit_updating;
133 bool need_commit_preedit;
135 GtkIMContextSCIMImpl *next;
138 /* Input Context handling functions. */
139 static GtkIMContextSCIMImpl * new_ic_impl (GtkIMContextSCIM *parent);
140 static void delete_ic_impl (GtkIMContextSCIMImpl *impl);
141 static void delete_all_ic_impl ();
143 static GtkIMContextSCIM * find_ic (int siid);
145 /* Methods declaration */
146 static void gtk_im_context_scim_class_init (GtkIMContextSCIMClass *klass,
147 gpointer *klass_data);
148 static void gtk_im_context_scim_init (GtkIMContextSCIM *context_scim,
149 GtkIMContextSCIMClass *klass);
150 static void gtk_im_context_scim_finalize (GObject *obj);
151 static void gtk_im_context_scim_finalize_partial (GtkIMContextSCIM *context_scim);
152 static void gtk_im_context_scim_set_client_window (GtkIMContext *context,
153 GdkWindow *client_window);
154 static gboolean gtk_im_context_scim_filter_keypress (GtkIMContext *context,
156 static void gtk_im_context_scim_reset (GtkIMContext *context);
157 static void gtk_im_context_scim_focus_in (GtkIMContext *context);
158 static void gtk_im_context_scim_focus_out (GtkIMContext *context);
159 static void gtk_im_context_scim_set_cursor_location (GtkIMContext *context,
161 static void gtk_im_context_scim_set_use_preedit (GtkIMContext *context,
162 gboolean use_preedit);
163 static void gtk_im_context_scim_get_preedit_string (GtkIMContext *context,
165 PangoAttrList **attrs,
168 static gboolean gtk_scim_key_snooper (GtkWidget *grab_widget,
172 static void gtk_im_slave_commit_cb (GtkIMContext *context,
174 GtkIMContextSCIM *context_scim);
176 /* private functions */
177 static void panel_slot_reload_config (int context);
178 static void panel_slot_exit (int context);
179 static void panel_slot_update_lookup_table_page_size(int context,
181 static void panel_slot_lookup_table_page_up (int context);
182 static void panel_slot_lookup_table_page_down (int context);
183 static void panel_slot_trigger_property (int context,
184 const String &property);
185 static void panel_slot_process_helper_event (int context,
186 const String &target_uuid,
187 const String &helper_uuid,
188 const Transaction &trans);
189 static void panel_slot_move_preedit_caret (int context,
191 static void panel_slot_select_candidate (int context,
193 static void panel_slot_process_key_event (int context,
194 const KeyEvent &key);
195 static void panel_slot_commit_string (int context,
196 const WideString &wstr);
197 static void panel_slot_forward_key_event (int context,
198 const KeyEvent &key);
199 static void panel_slot_request_help (int context);
200 static void panel_slot_request_factory_menu (int context);
201 static void panel_slot_change_factory (int context,
203 static void panel_slot_reset_keyboard_ise (int context);
204 static void panel_slot_show_preedit_string (int context);
205 static void panel_slot_hide_preedit_string (int context);
206 static void panel_slot_update_preedit_string (int context,
207 const WideString &str,
208 const AttributeList &attrs);
210 static void panel_req_focus_in (GtkIMContextSCIM *ic);
211 static void panel_req_update_screen (GtkIMContextSCIM *ic);
212 static void panel_req_update_factory_info (GtkIMContextSCIM *ic);
213 static void panel_req_update_spot_location (GtkIMContextSCIM *ic);
214 static void panel_req_show_help (GtkIMContextSCIM *ic);
215 static void panel_req_show_factory_menu (GtkIMContextSCIM *ic);
217 /* Panel iochannel handler*/
218 static bool panel_initialize ();
219 static void panel_finalize ();
220 static gboolean panel_iochannel_handler (GIOChannel *source,
221 GIOCondition condition,
224 /* utility functions */
225 static bool filter_hotkeys (GtkIMContextSCIM *ic,
226 const KeyEvent &key);
227 static void turn_on_ic (GtkIMContextSCIM *ic);
228 static void turn_off_ic (GtkIMContextSCIM *ic);
230 static void set_ic_capabilities (GtkIMContextSCIM *ic);
232 static KeyEvent keyevent_gdk_to_scim (const GtkIMContextSCIM *ic,
233 const GdkEventKey &gdkevent);
235 static GdkEventKey keyevent_scim_to_gdk (const GtkIMContextSCIM *ic,
236 const KeyEvent &scimkey, gboolean send_event);
238 static void initialize (void);
240 static void finalize (void);
242 static void open_next_factory (GtkIMContextSCIM *ic);
243 static void open_previous_factory (GtkIMContextSCIM *ic);
244 static void open_specific_factory (GtkIMContextSCIM *ic,
247 static void attach_instance (const IMEngineInstancePointer &si);
250 static void slot_show_preedit_string (IMEngineInstanceBase *si);
251 static void slot_show_aux_string (IMEngineInstanceBase *si);
252 static void slot_show_lookup_table (IMEngineInstanceBase *si);
254 static void slot_hide_preedit_string (IMEngineInstanceBase *si);
255 static void slot_hide_aux_string (IMEngineInstanceBase *si);
256 static void slot_hide_lookup_table (IMEngineInstanceBase *si);
258 static void slot_update_preedit_caret (IMEngineInstanceBase *si,
260 static void slot_update_preedit_string (IMEngineInstanceBase *si,
261 const WideString &str,
262 const AttributeList &attrs);
263 static void slot_update_aux_string (IMEngineInstanceBase *si,
264 const WideString &str,
265 const AttributeList &attrs);
266 static void slot_commit_string (IMEngineInstanceBase *si,
267 const WideString &str);
268 static void slot_forward_key_event (IMEngineInstanceBase *si,
269 const KeyEvent &key);
270 static void slot_update_lookup_table (IMEngineInstanceBase *si,
271 const LookupTable &table);
273 static void slot_register_properties (IMEngineInstanceBase *si,
274 const PropertyList &properties);
275 static void slot_update_property (IMEngineInstanceBase *si,
276 const Property &property);
277 static void slot_beep (IMEngineInstanceBase *si);
278 static void slot_start_helper (IMEngineInstanceBase *si,
279 const String &helper_uuid);
280 static void slot_stop_helper (IMEngineInstanceBase *si,
281 const String &helper_uuid);
282 static void slot_send_helper_event (IMEngineInstanceBase *si,
283 const String &helper_uuid,
284 const Transaction &trans);
285 static bool slot_get_surrounding_text (IMEngineInstanceBase *si,
290 static bool slot_delete_surrounding_text (IMEngineInstanceBase *si,
294 static void reload_config_callback (const ConfigPointer &config);
296 static void fallback_commit_string_cb (IMEngineInstanceBase *si,
297 const WideString &str);
302 /* Local variables declaration */
303 static String _language;
304 static GtkIMContextSCIMImpl *_used_ic_impl_list = 0;
305 static GtkIMContextSCIMImpl *_free_ic_impl_list = 0;
306 static GtkIMContextSCIM *_ic_list = 0;
308 static GType _gtk_type_im_context_scim = 0;
309 static GObjectClass *_parent_klass = 0;
311 static KeyboardLayout _keyboard_layout = SCIM_KEYBOARD_Default;
312 static int _valid_key_mask = SCIM_KEY_AllMasks;
314 static FrontEndHotkeyMatcher _frontend_hotkey_matcher;
315 static IMEngineHotkeyMatcher _imengine_hotkey_matcher;
317 static IMEngineInstancePointer _default_instance;
319 static ConfigModule *_config_module = 0;
320 static ConfigPointer _config;
321 static BackEndPointer _backend;
323 static GtkIMContextSCIM *_focused_ic = 0;
324 static GtkWidget *_focused_widget = 0;
326 static bool _scim_initialized = false;
328 static GdkColor _normal_bg;
329 static GdkColor _normal_text;
330 static GdkColor _active_bg;
331 static GdkColor _active_text;
333 static gint _snooper_id = 0;
334 static bool _snooper_installed = false;
336 static int _instance_count = 0;
337 static int _context_count = 0;
339 static IMEngineFactoryPointer _fallback_factory;
340 static IMEngineInstancePointer _fallback_instance;
342 static PanelClient _panel_client;
344 static GIOChannel *_panel_iochannel = 0;
345 static guint _panel_iochannel_read_source= 0;
346 static guint _panel_iochannel_err_source = 0;
347 static guint _panel_iochannel_hup_source = 0;
349 static bool _on_the_spot = true;
350 static bool _shared_input_method = false;
351 static bool _use_key_snooper = false;
353 static GdkColor *_theme_color = NULL;
355 // A hack to shutdown the immodule cleanly even if im_module_exit () is not called when exiting.
356 class FinalizeHandler
360 SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::FinalizeHandler ()\n";
362 ~FinalizeHandler () {
363 SCIM_DEBUG_FRONTEND(1) << "FinalizeHandler::~FinalizeHandler ()\n";
364 gtk_im_context_scim_shutdown ();
368 static FinalizeHandler _finalize_handler;
370 /* Function Implementations */
372 static GtkIMContextSCIMImpl *
373 new_ic_impl (GtkIMContextSCIM *parent)
375 GtkIMContextSCIMImpl *impl = NULL;
377 if (_free_ic_impl_list != NULL) {
378 impl = _free_ic_impl_list;
379 _free_ic_impl_list = _free_ic_impl_list->next;
381 impl = new GtkIMContextSCIMImpl;
386 impl->next = _used_ic_impl_list;
387 _used_ic_impl_list = impl;
389 impl->parent = parent;
395 delete_ic_impl (GtkIMContextSCIMImpl *impl)
397 GtkIMContextSCIMImpl *rec = _used_ic_impl_list, *last = 0;
399 for (; rec != 0; last = rec, rec = rec->next) {
402 last->next = rec->next;
404 _used_ic_impl_list = rec->next;
406 rec->next = _free_ic_impl_list;
407 _free_ic_impl_list = rec;
411 rec->client_window = 0;
412 rec->preedit_string = WideString ();
413 rec->preedit_attrlist.clear ();
422 delete_all_ic_impl ()
424 GtkIMContextSCIMImpl *it = _used_ic_impl_list;
428 _used_ic_impl_list = it->next;
430 it = _used_ic_impl_list;
433 it = _free_ic_impl_list;
435 _free_ic_impl_list = it->next;
437 it = _free_ic_impl_list;
441 static GtkIMContextSCIM *
444 GtkIMContextSCIMImpl *rec = _used_ic_impl_list;
447 if (rec->parent && rec->parent->id == id)
456 /* Public functions */
458 * gtk_im_context_scim_new
460 * This function will be called by gtk.
461 * Create a instance of type GtkIMContext.
463 * Return value: A pointer to the newly created GtkIMContextSCIM instance
467 gtk_im_context_scim_new (void)
469 print_time ("enter gtk_im_context_scim_new");
470 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_new...\n";
472 GtkIMContextSCIM *result = NULL;
474 result = GTK_IM_CONTEXT_SCIM (g_object_new (GTK_TYPE_IM_CONTEXT_SCIM, NULL));
476 print_time ("exit gtk_im_context_scim_new");
477 return GTK_IM_CONTEXT (result);
481 * gtk_im_context_scim_new
483 * Register the new type GtkIMContextSCIM to glib
487 gtk_im_context_scim_register_type (GTypeModule *type_module)
489 gettimeofday (&_scim_start, NULL);
490 print_time ("enter gtk_im_context_scim_register_type");
491 static const GTypeInfo im_context_scim_info =
493 sizeof (GtkIMContextSCIMClass),
494 (GBaseInitFunc) NULL,
495 (GBaseFinalizeFunc) NULL,
496 (GClassInitFunc) gtk_im_context_scim_class_init,
497 NULL, /* class_finalize */
498 NULL, /* class_data */
499 sizeof (GtkIMContextSCIM),
501 (GtkObjectInitFunc) gtk_im_context_scim_init,
504 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_register_type...\n";
506 if (!_gtk_type_im_context_scim) {
507 _gtk_type_im_context_scim =
508 g_type_module_register_type (type_module,
511 &im_context_scim_info,
514 print_time ("exit gtk_im_context_scim_register_type");
518 * gtk_im_context_scim_shutdown
520 * It will be called when the scim im module is unloaded by gtk. It will do some cleanup
525 gtk_im_context_scim_shutdown (void)
527 print_time ("enter gtk_im_context_scim_shutdown");
528 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_shutdown...\n";
530 if (_scim_initialized) {
531 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_shutdown: call finalize ()...\n";
533 _scim_initialized = false;
535 print_time ("exit gtk_im_context_scim_shutdown");
538 /* Private functions */
540 gtk_im_context_scim_class_init (GtkIMContextSCIMClass *klass,
541 gpointer *klass_data)
543 print_time ("enter gtk_im_context_scim_class_init");
544 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_class_init...\n";
546 GtkIMContextClass *im_context_klass = GTK_IM_CONTEXT_CLASS (klass);
547 GObjectClass *gobject_klass = G_OBJECT_CLASS (klass);
549 _parent_klass = (GObjectClass *) g_type_class_peek_parent (klass);
551 im_context_klass->set_client_window = gtk_im_context_scim_set_client_window;
552 im_context_klass->filter_keypress = gtk_im_context_scim_filter_keypress;
553 im_context_klass->reset = gtk_im_context_scim_reset;
554 im_context_klass->get_preedit_string = gtk_im_context_scim_get_preedit_string;
555 im_context_klass->focus_in = gtk_im_context_scim_focus_in;
556 im_context_klass->focus_out = gtk_im_context_scim_focus_out;
557 im_context_klass->set_cursor_location = gtk_im_context_scim_set_cursor_location;
558 im_context_klass->set_use_preedit = gtk_im_context_scim_set_use_preedit;
559 gobject_klass->finalize = gtk_im_context_scim_finalize;
561 if (!_scim_initialized) {
563 _scim_initialized = true;
565 print_time ("exit gtk_im_context_scim_class_init");
569 gtk_im_context_scim_init (GtkIMContextSCIM *context_scim,
570 GtkIMContextSCIMClass *klass)
572 print_time ("enter gtk_im_context_scim_init");
573 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_init...\n";
575 context_scim->impl = NULL;
577 /* slave exists for using gtk+'s table based input method */
578 context_scim->slave = gtk_im_context_simple_new ();
579 g_signal_connect(G_OBJECT(context_scim->slave),
581 G_CALLBACK(gtk_im_slave_commit_cb),
584 if (_backend.null ()) return;
586 IMEngineInstancePointer si;
588 // Use the default instance if "shared input method" mode is enabled.
589 if (_shared_input_method && !_default_instance.null ()) {
590 si = _default_instance;
591 SCIM_DEBUG_FRONTEND(2) << "use default instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
594 // Not in "shared input method" mode, or no default instance, create an instance.
596 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
597 if (factory.null ()) return;
598 si = factory->create_instance ("UTF-8", _instance_count++);
599 if (si.null ()) return;
600 attach_instance (si);
601 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << si->get_id () << " " << si->get_factory_uuid () << "\n";
604 // If "shared input method" mode is enabled, and there is no default instance,
605 // then store this instance as default one.
606 if (_shared_input_method && _default_instance.null ()) {
607 SCIM_DEBUG_FRONTEND(2) << "update default instance.\n";
608 _default_instance = si;
611 context_scim->impl = new_ic_impl (context_scim);
612 if (context_scim->impl == NULL)
614 std::cerr << "memory allocation failed in " << __FUNCTION__ << "\n";
618 context_scim->impl->si = si;
619 context_scim->impl->client_window = NULL;
620 context_scim->impl->preedit_caret = 0;
621 context_scim->impl->cursor_x = 0;
622 context_scim->impl->cursor_y = 0;
623 context_scim->impl->cursor_top_y = 0;
624 context_scim->impl->is_on = FALSE;
625 context_scim->impl->shared_si = _shared_input_method;
626 context_scim->impl->use_preedit = _on_the_spot;
627 context_scim->impl->preedit_started = false;
628 context_scim->impl->preedit_updating = false;
629 context_scim->impl->need_commit_preedit = false;
631 if (_context_count == 0) _context_count = time (NULL);
632 context_scim->id = _context_count++;
634 context_scim->next = NULL;
636 context_scim->next = _ic_list;
637 _ic_list = context_scim;
639 if (_shared_input_method)
640 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
642 _panel_client.prepare (context_scim->id);
643 _panel_client.register_input_context (context_scim->id, si->get_factory_uuid ());
644 _panel_client.start_default_ise (context_scim->id);
645 set_ic_capabilities (context_scim);
646 _panel_client.send ();
648 SCIM_DEBUG_FRONTEND(2) << "input context created: id = " << context_scim->id << "\n";
649 print_time ("exit gtk_im_context_scim_init");
653 gtk_im_context_scim_finalize_partial (GtkIMContextSCIM *context_scim)
655 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_finalize_partial id=" << context_scim->id << "\n";
657 if (context_scim->impl) {
658 _panel_client.prepare (context_scim->id);
660 if (context_scim == _focused_ic)
661 context_scim->impl->si->focus_out ();
663 // Delete the instance.
665 // In case the instance send out some helper event,
666 // and this context has been focused out,
667 // we need set the focused_ic to this context temporary.
668 GtkIMContextSCIM *old_focused = _focused_ic;
669 _focused_ic = context_scim;
670 context_scim->impl->si.reset ();
671 _focused_ic = old_focused;
673 if (context_scim == _focused_ic) {
674 _panel_client.turn_off (context_scim->id);
675 _panel_client.focus_out (context_scim->id);
678 _panel_client.remove_input_context (context_scim->id);
679 _panel_client.send ();
681 if (context_scim->impl->client_window)
682 g_object_unref (context_scim->impl->client_window);
684 delete_ic_impl (context_scim->impl);
686 context_scim->impl = 0;
689 if (context_scim == _focused_ic)
694 gtk_im_context_scim_finalize (GObject *obj)
696 print_time ("enter gtk_im_context_scim_finalize");
697 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (obj);
699 if (context_scim == NULL)
702 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_finalize id=" << context_scim->id << "\n";
704 if ((_ic_list != NULL))
706 if(context_scim->id != _ic_list->id) {
707 GtkIMContextSCIM * pre = _ic_list;
708 GtkIMContextSCIM * cur = _ic_list->next;
709 while (cur != NULL) {
710 if (cur->id == context_scim->id) {
711 pre->next = cur->next;
718 _ic_list = _ic_list->next;
721 if (_theme_color != NULL) {
722 gdk_color_free (_theme_color);
726 g_signal_handlers_disconnect_by_func(context_scim->slave,
727 (void *)gtk_im_slave_commit_cb,
728 (void *)context_scim);
729 g_object_unref(context_scim->slave);
731 gtk_im_context_scim_finalize_partial (context_scim);
733 _parent_klass->finalize (obj);
734 print_time ("exit gtk_im_context_scim_finalize");
738 * gtk_im_context_scim_set_client_window:
739 * @context: a #GtkIMContext
740 * @window: the client window. This may be %NULL to indicate
741 * that the previous client window no longer exists.
743 * This function will be called by gtk.
744 * Set the client window for the input context; this is the
745 * #GdkWindow in which the input appears. This window is
746 * used in order to correctly position status windows, and may
747 * also be used for purposes internal to the input method.
751 gtk_im_context_scim_set_client_window (GtkIMContext *context,
752 GdkWindow *client_window)
754 print_time ("enter gtk_im_context_scim_set_client_window");
755 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_set_client_window...\n";
757 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (context);
759 if (context_scim && context_scim->impl) {
761 g_object_ref (client_window);
763 if (context_scim->impl->client_window)
764 g_object_unref (context_scim->impl->client_window);
766 context_scim->impl->client_window = client_window;
768 print_time ("exit gtk_im_context_scim_set_client_window");
772 * gtk_im_context_scim_filter_keypress:
773 * @context: a #GtkIMContext
774 * @event: the key event
776 * This function will be called by gtk.
777 * Allow an input method to internally handle key press and release
778 * events. If this function returns %TRUE, then no further processing
779 * should be done for this key event.
781 * Return value: %TRUE if the input method handled the key event.
785 gtk_im_context_scim_filter_keypress (GtkIMContext *context,
788 print_time ("enter gtk_im_context_scim_filter_keypress");
789 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_filter_keypress...\n";
791 if (event->keyval == 255 && (event->keyval & GDK_SHIFT_MASK))
792 return (gboolean)TRUE;
794 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (context);
796 gboolean ret = FALSE;
799 if (!_snooper_installed)
800 ret = gtk_scim_key_snooper (0, event, 0);
802 if (!ret && context_scim->slave)
803 ret = gtk_im_context_filter_keypress (context_scim->slave, event);
806 print_time ("exit gtk_im_context_scim_filter_keypress");
811 * gtk_im_context_scim_reset:
812 * @context: a #GtkIMContext
814 * This function will be called by gtk.
815 * Notify the input method that a change such as a change in cursor
816 * position has been made. This will typically cause the input
817 * method to clear the preedit state.
820 gtk_im_context_scim_reset (GtkIMContext *context)
822 print_time ("enter gtk_im_context_scim_reset");
823 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_reset...\n";
825 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (context);
827 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
828 WideString wstr = context_scim->impl->preedit_string;
830 _panel_client.prepare (context_scim->id);
831 context_scim->impl->si->reset ();
832 _panel_client.send ();
834 if (context_scim->impl->need_commit_preedit)
836 panel_slot_hide_preedit_string (context_scim->id);
839 g_signal_emit_by_name (context_scim, "commit", utf8_wcstombs (wstr).c_str ());
841 _panel_client.prepare (context_scim->id);
842 _panel_client.reset_input_context (context_scim->id);
843 _panel_client.send ();
846 print_time ("exit gtk_im_context_scim_reset");
850 * gtk_im_context_scim_focus_in:
851 * @context: a #GtkIMContext
853 * This function will be called by gtk.
854 * Notify the input method that the widget to which this
855 * input context corresponds has gained focus. The input method
856 * may, for example, change the displayed feedback to reflect
860 gtk_im_context_scim_focus_in (GtkIMContext *context)
862 print_time ("enter gtk_im_context_scim_focus_in");
863 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (context);
866 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_focus_in(" << context_scim->id << ")...\n";
869 if (_focused_ic == context_scim) {
870 SCIM_DEBUG_FRONTEND(1) << "It's already focused.\n";
873 SCIM_DEBUG_FRONTEND(1) << "Focus out previous IC first: " << _focused_ic->id << "\n";
874 gtk_im_context_scim_focus_out (GTK_IM_CONTEXT (_focused_ic));
877 // Only use key snooper when use_key_snooper option is enabled and a gtk main loop is running.
878 if (_use_key_snooper && !_snooper_installed && gtk_main_level () > 0) {
879 SCIM_DEBUG_FRONTEND(2) << "Install key snooper.\n";
880 _snooper_id = gtk_key_snooper_install ((GtkKeySnoopFunc)gtk_scim_key_snooper, NULL);
881 _snooper_installed = true;
884 bool need_cap = false;
885 bool need_reset = false;
886 bool need_reg = false;
888 if (context_scim && context_scim->impl) {
889 _focused_ic = context_scim;
890 _panel_client.prepare (context_scim->id);
892 // Handle the "Shared Input Method" mode.
893 if (_shared_input_method) {
894 SCIM_DEBUG_FRONTEND(2) << "shared input method.\n";
895 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
896 if (!factory.null ()) {
897 if (_default_instance.null () || _default_instance->get_factory_uuid () != factory->get_uuid ()) {
898 _default_instance = factory->create_instance ("UTF-8", _default_instance.null () ? _instance_count++ : _default_instance->get_id ());
899 attach_instance (_default_instance);
900 SCIM_DEBUG_FRONTEND(2) << "create new default instance: " << _default_instance->get_id () << " " << _default_instance->get_factory_uuid () << "\n";
903 context_scim->impl->shared_si = true;
904 context_scim->impl->si = _default_instance;
906 context_scim->impl->is_on = _config->read (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), context_scim->impl->is_on);
907 context_scim->impl->preedit_string.clear ();
908 context_scim->impl->preedit_attrlist.clear ();
909 context_scim->impl->preedit_caret = 0;
910 context_scim->impl->preedit_started = false;
915 } else if (context_scim->impl->shared_si) {
916 SCIM_DEBUG_FRONTEND(2) << "exit shared input method.\n";
917 IMEngineFactoryPointer factory = _backend->get_default_factory (_language, "UTF-8");
918 if (!factory.null ()) {
919 context_scim->impl->si = factory->create_instance ("UTF-8", _instance_count++);
920 context_scim->impl->preedit_string.clear ();
921 context_scim->impl->preedit_attrlist.clear ();
922 context_scim->impl->preedit_caret = 0;
923 context_scim->impl->preedit_started = false;
924 attach_instance (context_scim->impl->si);
927 context_scim->impl->shared_si = false;
928 SCIM_DEBUG_FRONTEND(2) << "create new instance: " << context_scim->impl->si->get_id () << " " << context_scim->impl->si->get_factory_uuid () << "\n";
932 context_scim->impl->si->set_frontend_data (static_cast <void*> (context_scim));
934 if (need_reg) _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
935 if (need_cap) set_ic_capabilities (context_scim);
936 if (need_reset) context_scim->impl->si->reset ();
938 panel_req_focus_in (context_scim);
939 // panel_req_update_screen (context_scim);
940 panel_req_update_spot_location (context_scim);
941 panel_req_update_factory_info (context_scim);
943 if (context_scim->impl->is_on) {
944 _panel_client.turn_on (context_scim->id);
945 // _panel_client.hide_preedit_string (context_scim->id);
946 // _panel_client.hide_aux_string (context_scim->id);
947 // _panel_client.hide_lookup_table (context_scim->id);
948 context_scim->impl->si->focus_in ();
950 _panel_client.turn_off (context_scim->id);
953 if (!context_scim->impl->is_on)
954 turn_on_ic (context_scim);
956 _panel_client.send ();
959 // Get theme color for preedit background color
960 /* if (_theme_color != NULL) {
961 gdk_color_free (_theme_color);
966 if (_theme_color == NULL)
968 GtkWidget *temp_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
969 gtk_widget_realize (temp_window);
970 gtk_widget_style_get (temp_window, "theme-color", &_theme_color, NULL);
971 if (GTK_IS_WIDGET (temp_window))
972 gtk_widget_destroy (temp_window);
976 print_time ("exit gtk_im_context_scim_focus_in");
980 * gtk_im_context_scim_focus_out:
981 * @context: a #GtkIMContext
983 * This function will be called by gtk.
984 * Notify the input method that the widget to which this
985 * input context corresponds has lost focus. The input method
986 * may, for example, change the displayed feedback or reset the contexts
987 * state to reflect this change.
990 gtk_im_context_scim_focus_out (GtkIMContext *context)
992 print_time ("enter gtk_im_context_scim_focus_out");
993 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (context);
996 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_focus_out(" << context_scim->id << ")...\n";
998 if (_snooper_installed) {
999 SCIM_DEBUG_FRONTEND(2) << "Remove key snooper.\n";
1000 gtk_key_snooper_remove (_snooper_id);
1001 _snooper_installed = false;
1004 if (context_scim && context_scim->impl && context_scim == _focused_ic) {
1006 WideString wstr = context_scim->impl->preedit_string;
1009 if (context_scim->impl->need_commit_preedit)
1011 panel_slot_hide_preedit_string (context_scim->id);
1014 g_signal_emit_by_name (context_scim, "commit", utf8_wcstombs (wstr).c_str ());
1016 _panel_client.prepare (context_scim->id);
1017 _panel_client.reset_input_context (context_scim->id);
1018 _panel_client.send ();
1021 _panel_client.prepare (context_scim->id);
1022 context_scim->impl->si->focus_out ();
1023 context_scim->impl->si->reset ();
1024 //if (context_scim->impl->shared_si) context_scim->impl->si->reset ();
1025 _panel_client.focus_out (context_scim->id);
1026 _panel_client.send ();
1029 print_time ("exit gtk_im_context_scim_focus_out");
1033 * gtk_im_context_scim_set_cursor_location:
1034 * @context: a #GtkIMContext
1035 * @area: new location
1037 * This function will be called gtk.
1038 * Notify the input method that a change in cursor
1039 * position has been made. The location is relative to the client
1043 gtk_im_context_scim_set_cursor_location (GtkIMContext *context,
1046 print_time ("enter gtk_im_context_scim_set_cursor_location");
1047 SCIM_DEBUG_FRONTEND(4) << "gtk_im_context_scim_set_cursor_location...\n";
1050 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (context);
1051 #ifdef USING_ISF_MAINWINDOW_AUTOSCROLL
1052 gtk_ise_set_cursor_location (area);
1054 ISF_PROF_DEBUG("last message");
1056 if (context_scim && context_scim->impl && context_scim->impl->client_window && context_scim == _focused_ic) {
1057 // Don't update spot location while updating preedit string.
1058 if (context_scim->impl->preedit_updating)
1061 gdk_window_get_origin(context_scim->impl->client_window, &x, &y);
1062 if (context_scim->impl->cursor_x != x + area->x + area->width ||
1063 context_scim->impl->cursor_y != y + area->y + area->height) {
1064 context_scim->impl->cursor_x = x + area->x + area->width;
1065 context_scim->impl->cursor_y = y + area->y + area->height;
1066 context_scim->impl->cursor_top_y = y + area->y;
1068 // context_scim->impl->cursor_top_y = y + area->y - 4;
1070 _panel_client.prepare (context_scim->id);
1071 panel_req_update_spot_location (context_scim);
1072 _panel_client.send ();
1073 SCIM_DEBUG_FRONTEND(2) << "new cursor location = " << context_scim->impl->cursor_x << "," << context_scim->impl->cursor_y << "\n";
1077 print_time ("exit gtk_im_context_scim_set_cursor_location");
1081 * gtk_im_context_scim_set_use_preedit:
1082 * @context: a #GtkIMContext
1083 * @area: new location
1085 * This function will be called by gtk.
1086 * Notify the input method that a change in cursor
1087 * position has been made. The location is relative to the client
1091 gtk_im_context_scim_set_use_preedit (GtkIMContext *context,
1092 gboolean use_preedit)
1094 print_time ("enter gtk_im_context_scim_set_use_preedit");
1095 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_set_use_preedit = " << (use_preedit ? "true" : "false") << "...\n";
1097 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (context);
1099 if (!_on_the_spot) return;
1101 if (context_scim && context_scim->impl) {
1102 bool old = context_scim->impl->use_preedit;
1103 context_scim->impl->use_preedit = use_preedit;
1104 if (context_scim == _focused_ic) {
1105 _panel_client.prepare (context_scim->id);
1107 if (old != use_preedit)
1108 set_ic_capabilities (context_scim);
1110 if (context_scim->impl->preedit_string.length ())
1111 slot_show_preedit_string (context_scim->impl->si);
1113 _panel_client.send ();
1116 print_time ("exit gtk_im_context_scim_set_use_preedit");
1120 * gtk_im_context_scim_get_preedit_string:
1121 * @context: a #GtkIMContext
1122 * @str: location to store the retrieved string. The
1123 * string retrieved must be freed with g_free ().
1124 * @attrs: location to store the retrieved attribute list.
1125 * When you are done with this list, you must
1126 * unreference it with pango_attr_list_unref().
1127 * @cursor_pos: location to store position of cursor (in characters)
1128 * within the preedit string.
1130 * This function will be called by gtk
1131 * Retrieve the current preedit string for the input context,
1132 * and a list of attributes to apply to the string.
1133 * This string should be displayed inserted at the insertion
1137 gtk_im_context_scim_get_preedit_string (GtkIMContext *context,
1139 PangoAttrList **attrs,
1142 print_time ("enter gtk_im_context_scim_get_preedit_string");
1143 SCIM_DEBUG_FRONTEND(1) << "gtk_im_context_scim_get_preedit_string...\n";
1145 GtkIMContextSCIM *context_scim = GTK_IM_CONTEXT_SCIM (context);
1147 if (context_scim && context_scim->impl && context_scim->impl->is_on) {
1148 String mbs = utf8_wcstombs (context_scim->impl->preedit_string);
1152 *str = g_strdup (mbs.c_str ());
1154 *str = g_strdup ("");
1158 *cursor_pos = context_scim->impl->preedit_caret;
1162 *attrs = pango_attr_list_new ();
1164 if (mbs.length ()) {
1165 guint start_index, end_index;
1166 guint wlen = context_scim->impl->preedit_string.length ();
1168 PangoAttribute *attr = NULL;
1169 AttributeList::const_iterator i;
1170 //bool underline = false;
1171 bool *attrs_flag = new bool [mbs.length ()];
1173 memset (attrs_flag, 0, mbs.length () * sizeof (bool));
1175 for (i = context_scim->impl->preedit_attrlist.begin ();
1176 i != context_scim->impl->preedit_attrlist.end (); ++i) {
1177 start_index = i->get_start ();
1178 end_index = i->get_end ();
1180 if (end_index <= wlen && start_index < end_index && i->get_type () != SCIM_ATTR_DECORATE_NONE) {
1181 start_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_start ()) - mbs.c_str ();
1182 end_index = g_utf8_offset_to_pointer (mbs.c_str (), i->get_end ()) - mbs.c_str ();
1184 if (i->get_type () == SCIM_ATTR_DECORATE) {
1185 if (i->get_value () == scim::SCIM_ATTR_DECORATE_UNDERLINE) {
1186 attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
1189 attr->start_index = start_index;
1190 attr->end_index = end_index;
1191 pango_attr_list_insert (*attrs, attr);
1193 } else if (i->get_value () == SCIM_ATTR_DECORATE_REVERSE) {
1194 attr = pango_attr_foreground_new (_normal_bg.red, _normal_bg.green, _normal_bg.blue);
1197 attr->start_index = start_index;
1198 attr->end_index = end_index;
1199 pango_attr_list_insert (*attrs, attr);
1201 attr = pango_attr_background_new (_normal_text.red, _normal_text.green, _normal_text.blue);
1204 attr->start_index = start_index;
1205 attr->end_index = end_index;
1206 pango_attr_list_insert (*attrs, attr);
1207 } else if (i->get_value () == SCIM_ATTR_DECORATE_HIGHLIGHT) {
1208 attr = pango_attr_foreground_new (_active_text.red, _active_text.green, _active_text.blue);
1211 //attr = pango_attr_foreground_new (65535, 65535, 65535);
1212 attr->start_index = start_index;
1213 attr->end_index = end_index;
1214 pango_attr_list_insert (*attrs, attr);
1216 attr = pango_attr_background_new (_active_bg.red, _active_bg.green, _active_bg.blue);
1219 //attr = pango_attr_background_new (32767, 32767, 32767);
1220 attr->start_index = start_index;
1221 attr->end_index = end_index;
1222 pango_attr_list_insert (*attrs, attr);
1224 } else if (i->get_type () == SCIM_ATTR_FOREGROUND) {
1225 unsigned int color = i->get_value ();
1227 attr = pango_attr_foreground_new (SCIM_RGB_COLOR_RED(color) * 256, SCIM_RGB_COLOR_GREEN(color) * 256, SCIM_RGB_COLOR_BLUE(color) * 256);
1230 attr->start_index = start_index;
1231 attr->end_index = end_index;
1232 pango_attr_list_insert (*attrs, attr);
1233 } else if (i->get_type () == SCIM_ATTR_BACKGROUND) {
1234 unsigned int color = i->get_value ();
1236 attr = pango_attr_background_new (SCIM_RGB_COLOR_RED(color) * 256, SCIM_RGB_COLOR_GREEN(color) * 256, SCIM_RGB_COLOR_BLUE(color) * 256);
1239 attr->start_index = start_index;
1240 attr->end_index = end_index;
1241 pango_attr_list_insert (*attrs, attr);
1244 // Record which character has attribute.
1245 for (guint pos = start_index; pos < end_index; ++pos)
1246 attrs_flag [pos] = 1;
1250 // Add underline for all characters which don't have attribute.
1251 for (guint pos = 0; pos < mbs.length (); ++pos) {
1252 if (!attrs_flag [pos]) {
1253 guint begin_pos = pos;
1255 while (pos < mbs.length () && !attrs_flag [pos])
1258 // use REVERSE style as default
1259 attr = pango_attr_foreground_new (_normal_bg.red, _normal_bg.green, _normal_bg.blue);
1262 attr->start_index = begin_pos;
1263 attr->end_index = pos;
1264 pango_attr_list_insert (*attrs, attr);
1266 attr = pango_attr_background_new (_normal_text.red, _normal_text.green, _normal_text.blue);
1269 attr->start_index = begin_pos;
1270 attr->end_index = pos;
1271 pango_attr_list_insert (*attrs, attr);
1274 attr = pango_attr_underline_new (PANGO_UNDERLINE_SINGLE);
1275 attr->start_index = begin_pos;
1276 attr->end_index = pos;
1277 pango_attr_list_insert (*attrs, attr);
1282 delete [] attrs_flag;
1287 *str = g_strdup ("");
1293 *attrs = pango_attr_list_new ();
1295 print_time ("exit gtk_im_context_scim_get_preedit_string");
1299 gtk_scim_key_snooper (GtkWidget *grab_widget,
1303 SCIM_DEBUG_FRONTEND(3) << "gtk_scim_key_snooper...\n";
1305 gboolean ret = FALSE;
1307 if (_focused_ic && _focused_ic->impl && (event->type == GDK_KEY_PRESS || event->type == GDK_KEY_RELEASE) && !event->send_event) {
1308 _focused_widget = grab_widget;
1310 KeyEvent key = keyevent_gdk_to_scim (_focused_ic, *event);
1312 key.mask &= _valid_key_mask;
1314 key.layout = _keyboard_layout;
1316 _panel_client.prepare (_focused_ic->id);
1318 if (!filter_hotkeys (_focused_ic, key)) {
1319 if (!_focused_ic->impl->is_on || !_focused_ic->impl->si->process_key_event (key)) {
1320 SCIM_DEBUG_FRONTEND(3) << "Failed to process: "
1321 << (!_focused_ic->impl->is_on ? "IC is off" : "IC doesn't process")
1323 ret = _fallback_instance->process_key_event (key);
1331 _panel_client.send ();
1333 _focused_widget = 0;
1335 SCIM_DEBUG_FRONTEND(3) << "Failed snooper: "
1336 << ((!_focused_ic || !_focused_ic->impl) ? "Invalid focused ic" :
1337 (event->send_event ? "send event is set" : "unknown"))
1345 gtk_im_slave_commit_cb (GtkIMContext *context,
1347 GtkIMContextSCIM *context_scim)
1349 g_return_if_fail(str);
1350 g_signal_emit_by_name(context_scim, "commit", str);
1353 /* Panel Slot functions */
1355 panel_slot_reload_config (int context)
1357 SCIM_DEBUG_FRONTEND(1) << "panel_slot_reload_config...\n";
1362 panel_slot_exit (int /* context */)
1364 SCIM_DEBUG_FRONTEND(1) << "panel_slot_exit...\n";
1370 panel_slot_update_lookup_table_page_size (int context, int page_size)
1372 GtkIMContextSCIM *ic = find_ic (context);
1373 SCIM_DEBUG_FRONTEND(1) << "panel_slot_update_lookup_table_page_size context=" << context << " page_size=" << page_size << " ic=" << ic << "\n";
1374 if (ic && ic->impl) {
1375 _panel_client.prepare (ic->id);
1376 ic->impl->si->update_lookup_table_page_size (page_size);
1377 _panel_client.send ();
1382 panel_slot_lookup_table_page_up (int context)
1384 GtkIMContextSCIM *ic = find_ic (context);
1385 SCIM_DEBUG_FRONTEND(1) << "panel_slot_lookup_table_page_up context=" << context << " ic=" << ic << "\n";
1386 if (ic && ic->impl) {
1387 _panel_client.prepare (ic->id);
1388 ic->impl->si->lookup_table_page_up ();
1389 _panel_client.send ();
1394 panel_slot_lookup_table_page_down (int context)
1396 GtkIMContextSCIM *ic = find_ic (context);
1397 SCIM_DEBUG_FRONTEND(1) << "panel_slot_lookup_table_page_down context=" << context << " ic=" << ic << "\n";
1398 if (ic && ic->impl) {
1399 _panel_client.prepare (ic->id);
1400 ic->impl->si->lookup_table_page_down ();
1401 _panel_client.send ();
1406 panel_slot_trigger_property (int context, const String &property)
1408 GtkIMContextSCIM *ic = find_ic (context);
1409 SCIM_DEBUG_FRONTEND(1) << "panel_slot_trigger_property context=" << context << " property=" << property << " ic=" << ic << "\n";
1410 if (ic && ic->impl) {
1411 _panel_client.prepare (ic->id);
1412 ic->impl->si->trigger_property (property);
1413 _panel_client.send ();
1418 panel_slot_process_helper_event (int context, const String &target_uuid, const String &helper_uuid, const Transaction &trans)
1420 GtkIMContextSCIM *ic = find_ic (context);
1421 SCIM_DEBUG_FRONTEND(1) << "panel_slot_process_helper_event context=" << context << " target=" << target_uuid
1422 << " helper=" << helper_uuid << " ic=" << ic << " ic->impl=" << (ic ? ic->impl : 0) << " ic-uuid="
1423 << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "" ) << "\n";
1424 if (ic && ic->impl && ic->impl->si->get_factory_uuid () == target_uuid) {
1425 _panel_client.prepare (ic->id);
1426 SCIM_DEBUG_FRONTEND(2) << "call process_helper_event\n";
1427 ic->impl->si->process_helper_event (helper_uuid, trans);
1428 _panel_client.send ();
1433 panel_slot_move_preedit_caret (int context, int caret_pos)
1435 GtkIMContextSCIM *ic = find_ic (context);
1436 SCIM_DEBUG_FRONTEND(1) << "panel_slot_move_preedit_caret context=" << context << " caret=" << caret_pos << " ic=" << ic << "\n";
1437 if (ic && ic->impl) {
1438 _panel_client.prepare (ic->id);
1439 ic->impl->si->move_preedit_caret (caret_pos);
1440 _panel_client.send ();
1445 panel_slot_select_candidate (int context, int cand_index)
1447 GtkIMContextSCIM *ic = find_ic (context);
1448 SCIM_DEBUG_FRONTEND(1) << "panel_slot_select_candidate context=" << context << " candidate=" << cand_index << " ic=" << ic << "\n";
1449 if (ic && ic->impl) {
1450 _panel_client.prepare (ic->id);
1451 ic->impl->si->select_candidate (cand_index);
1452 _panel_client.send ();
1457 panel_slot_process_key_event (int context, const KeyEvent &key)
1459 GtkIMContextSCIM *ic = find_ic (context);
1460 SCIM_DEBUG_FRONTEND(1) << "panel_slot_process_key_event context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
1462 if (_focused_ic != ic)
1465 if (ic && ic->impl) {
1466 // Just send it to key_snooper and bypass to client directly (because send_event is set to TRUE).
1467 GdkEventKey gdkevent = keyevent_scim_to_gdk (ic, key, FALSE);
1468 gdk_event_put ((GdkEvent *)&gdkevent);
1473 panel_slot_commit_string (int context, const WideString &wstr)
1475 GtkIMContextSCIM *ic = find_ic (context);
1476 SCIM_DEBUG_FRONTEND(1) << "panel_slot_commit_string context=" << context << " str=" << utf8_wcstombs (wstr) << " ic=" << ic << "\n";
1478 if (_focused_ic != ic)
1482 g_signal_emit_by_name (ic, "commit", utf8_wcstombs (wstr).c_str ());
1486 panel_slot_forward_key_event (int context, const KeyEvent &key)
1488 GtkIMContextSCIM *ic = find_ic (context);
1489 SCIM_DEBUG_FRONTEND(1) << "panel_slot_forward_key_event context=" << context << " key=" << key.get_key_string () << " ic=" << ic << "\n";
1491 if (_focused_ic != ic)
1494 if (ic && ic->impl) {
1495 // Just send it to key_snooper and bypass to client directly (because send_event is set to TRUE).
1496 GdkEventKey gdkevent = keyevent_scim_to_gdk (ic, key, TRUE);
1497 gdk_event_put ((GdkEvent *)&gdkevent);
1502 panel_slot_request_help (int context)
1504 GtkIMContextSCIM *ic = find_ic (context);
1505 SCIM_DEBUG_FRONTEND(1) << "panel_slot_request_help context=" << context << " ic=" << ic << "\n";
1506 if (ic && ic->impl) {
1507 _panel_client.prepare (ic->id);
1508 panel_req_show_help (ic);
1509 _panel_client.send ();
1514 panel_slot_request_factory_menu (int context)
1516 GtkIMContextSCIM *ic = find_ic (context);
1517 SCIM_DEBUG_FRONTEND(1) << "panel_slot_request_factory_menu context=" << context << " ic=" << ic << "\n";
1518 if (ic && ic->impl) {
1519 _panel_client.prepare (ic->id);
1520 panel_req_show_factory_menu (ic);
1521 _panel_client.send ();
1526 panel_slot_change_factory (int context, const String &uuid)
1528 GtkIMContextSCIM *ic = find_ic (context);
1529 SCIM_DEBUG_FRONTEND(1) << "panel_slot_change_factory context=" << context << " factory=" << uuid << " ic=" << ic << "\n";
1530 if (ic && ic->impl) {
1531 ic->impl->si->reset ();
1532 _panel_client.prepare (ic->id);
1533 open_specific_factory (ic, uuid);
1534 _panel_client.send ();
1539 panel_slot_reset_keyboard_ise (int context)
1541 GtkIMContextSCIM *ic = find_ic (context);
1542 SCIM_DEBUG_FRONTEND(1) << "panel_slot_reset_keyboard_ise context=" << context << " ic=" << ic << "\n";
1545 WideString wstr = ic->impl->preedit_string;
1546 if (ic->impl->need_commit_preedit)
1548 panel_slot_hide_preedit_string (ic->id);
1551 g_signal_emit_by_name (ic, "commit", utf8_wcstombs (wstr).c_str ());
1553 ic->impl->si->reset ();
1558 panel_slot_show_preedit_string (int context)
1560 GtkIMContextSCIM *ic = find_ic (context);
1561 SCIM_DEBUG_FRONTEND(1) << "panel_slot_show_preedit_string context=" << context << "\n";
1565 if (!ic->impl->is_on)
1566 ic->impl->is_on = true;
1568 if (ic->impl->use_preedit) {
1569 if (!ic->impl->preedit_started) {
1570 KeyEvent key (0xff, SCIM_KEY_ShiftMask);
1572 GdkEventKey gdkevent = keyevent_scim_to_gdk (ic, key, TRUE);
1574 gdk_event_put ((GdkEvent *)&gdkevent);
1576 g_signal_emit_by_name (_focused_ic, "preedit-start");
1577 ic->impl->preedit_started = true;
1578 ic->impl->need_commit_preedit = true;
1585 panel_slot_hide_preedit_string (int context)
1587 GtkIMContextSCIM *ic = find_ic (context);
1588 SCIM_DEBUG_FRONTEND(1) << "panel_slot_hide_preedit_string context=" << context << "\n";
1592 if (!ic->impl->is_on)
1593 ic->impl->is_on = true;
1596 if (ic->impl->preedit_string.length ()) {
1597 ic->impl->preedit_string = WideString ();
1598 ic->impl->preedit_caret = 0;
1599 ic->impl->preedit_attrlist.clear ();
1602 if (ic->impl->use_preedit) {
1603 if (emit) g_signal_emit_by_name (ic, "preedit-changed");
1604 if (ic->impl->preedit_started) {
1605 g_signal_emit_by_name (ic, "preedit-end");
1606 ic->impl->preedit_started = false;
1607 ic->impl->need_commit_preedit = false;
1614 panel_slot_update_preedit_string (int context,
1615 const WideString &str,
1616 const AttributeList &attrs)
1618 GtkIMContextSCIM *ic = find_ic (context);
1619 SCIM_DEBUG_FRONTEND(1) << "panel_slot_update_preedit_string context=" << context << "\n";
1623 if (!ic->impl->is_on)
1624 ic->impl->is_on = true;
1626 if (ic->impl->preedit_string != str || str.length ()) {
1627 ic->impl->preedit_string = str;
1628 ic->impl->preedit_attrlist = attrs;
1630 if (ic->impl->use_preedit) {
1631 if (!ic->impl->preedit_started) {
1632 g_signal_emit_by_name(_focused_ic, "preedit-start");
1633 ic->impl->preedit_started = true;
1634 ic->impl->need_commit_preedit = true;
1636 ic->impl->preedit_caret = str.length ();
1637 ic->impl->preedit_updating = true;
1638 g_signal_emit_by_name(ic, "preedit-changed");
1639 ic->impl->preedit_updating = false;
1645 /* Panel Requestion functions. */
1647 panel_req_update_screen (GtkIMContextSCIM *ic)
1649 #if GDK_MULTIHEAD_SAFE
1650 if (ic->impl->client_window) {
1651 GdkScreen *screen = gdk_drawable_get_screen (GDK_DRAWABLE (ic->impl->client_window));
1653 int number = gdk_screen_get_number (screen);
1654 _panel_client.update_screen (ic->id, number);
1661 panel_req_show_help (GtkIMContextSCIM *ic)
1665 help = String (_("Smart Common Input Method platform ")) +
1666 String (SCIM_VERSION) +
1667 String (_("\n(C) 2002-2005 James Su <suzhe@tsinghua.org.cn>\n\n"));
1669 if (ic && ic->impl) {
1670 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
1672 help += utf8_wcstombs (sf->get_name ());
1673 help += String (_(":\n\n"));
1675 help += utf8_wcstombs (sf->get_help ());
1676 help += String (_("\n\n"));
1678 help += utf8_wcstombs (sf->get_credits ());
1681 _panel_client.show_help (ic->id, help);
1686 panel_req_show_factory_menu (GtkIMContextSCIM *ic)
1688 std::vector<IMEngineFactoryPointer> factories;
1689 std::vector <PanelFactoryInfo> menu;
1691 _backend->get_factories_for_encoding (factories, "UTF-8");
1693 for (size_t i = 0; i < factories.size (); ++ i) {
1694 menu.push_back (PanelFactoryInfo (
1695 factories [i]->get_uuid (),
1696 utf8_wcstombs (factories [i]->get_name ()),
1697 factories [i]->get_language (),
1698 factories [i]->get_icon_file ()));
1702 _panel_client.show_factory_menu (ic->id, menu);
1706 panel_req_update_factory_info (GtkIMContextSCIM *ic)
1708 if (ic && ic->impl && ic == _focused_ic) {
1709 PanelFactoryInfo info;
1710 if (ic->impl->is_on) {
1711 IMEngineFactoryPointer sf = _backend->get_factory (ic->impl->si->get_factory_uuid ());
1713 info = PanelFactoryInfo (sf->get_uuid (), utf8_wcstombs (sf->get_name ()), sf->get_language (), sf->get_icon_file ());
1715 info = PanelFactoryInfo (String (""), String (_("English/Keyboard")), String ("C"), String (SCIM_KEYBOARD_ICON_FILE));
1717 _panel_client.update_factory_info (ic->id, info);
1722 panel_req_focus_in (GtkIMContextSCIM *ic)
1724 _panel_client.focus_in (ic->id, ic->impl->si->get_factory_uuid ());
1728 panel_req_update_spot_location (GtkIMContextSCIM *ic)
1730 _panel_client.update_spot_location (ic->id, ic->impl->cursor_x, ic->impl->cursor_y, ic->impl->cursor_top_y);
1735 filter_hotkeys (GtkIMContextSCIM *ic, const KeyEvent &key)
1739 _frontend_hotkey_matcher.push_key_event (key);
1740 _imengine_hotkey_matcher.push_key_event (key);
1742 FrontEndHotkeyAction hotkey_action = _frontend_hotkey_matcher.get_match_result ();
1744 if (hotkey_action == SCIM_FRONTEND_HOTKEY_TRIGGER) {
1745 if (!ic->impl->is_on)
1750 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_ON) {
1751 if (!ic->impl->is_on)
1754 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_OFF) {
1755 if (ic->impl->is_on)
1758 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_NEXT_FACTORY) {
1759 open_next_factory (ic);
1761 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_PREVIOUS_FACTORY) {
1762 open_previous_factory (ic);
1764 } else if (hotkey_action == SCIM_FRONTEND_HOTKEY_SHOW_FACTORY_MENU) {
1765 panel_req_show_factory_menu (ic);
1767 } else if (_imengine_hotkey_matcher.is_matched ()) {
1768 ISEInfo info = _imengine_hotkey_matcher.get_match_result ();
1769 ISE_TYPE type = info.type;
1770 if (type == IMENGINE_T)
1771 open_specific_factory (ic, info.uuid);
1772 else if (type == HELPER_T)
1773 _panel_client.start_helper (ic->id, info.uuid);
1782 String display_name;
1785 #if GDK_MULTIHEAD_SAFE
1786 const char *p = gdk_display_get_name (gdk_display_get_default ());
1788 const char *p = getenv ("DISPLAY");
1790 if (p) display_name = String (p);
1793 SCIM_DEBUG_FRONTEND(1) << "panel_initialize..\n";
1795 if (_panel_client.open_connection (_config->get_name (), display_name) >= 0) {
1796 int fd = _panel_client.get_connection_number ();
1797 _panel_iochannel = g_io_channel_unix_new (fd);
1799 _panel_iochannel_read_source = g_io_add_watch (_panel_iochannel, G_IO_IN, panel_iochannel_handler, 0);
1800 _panel_iochannel_err_source = g_io_add_watch (_panel_iochannel, G_IO_ERR, panel_iochannel_handler, 0);
1801 _panel_iochannel_hup_source = g_io_add_watch (_panel_iochannel, G_IO_HUP, panel_iochannel_handler, 0);
1803 SCIM_DEBUG_FRONTEND(2) << " Panel FD= " << fd << "\n";
1806 * When the PanelAgent process crash, the application will try restarting and
1807 * connecting the PanelAgent process.
1808 * After it, it will register the previous input contexts to the PanelAgent.
1810 GtkIMContextSCIM *context_scim = _ic_list;
1811 while (context_scim != NULL) {
1812 _panel_client.prepare (context_scim->id);
1813 _panel_client.register_input_context (context_scim->id, context_scim->impl->si->get_factory_uuid ());
1814 _panel_client.start_default_ise (context_scim->id);
1815 _panel_client.send ();
1816 context_scim = context_scim->next;
1820 _panel_client.prepare (_focused_ic->id);
1821 panel_req_focus_in (_focused_ic);
1822 _panel_client.send ();
1833 _panel_client.close_connection ();
1835 if (_panel_iochannel) {
1836 g_io_channel_unref (_panel_iochannel);
1837 g_source_remove (_panel_iochannel_read_source);
1838 g_source_remove (_panel_iochannel_err_source);
1839 g_source_remove (_panel_iochannel_hup_source);
1840 _panel_iochannel = 0;
1841 _panel_iochannel_read_source = 0;
1842 _panel_iochannel_err_source = 0;
1843 _panel_iochannel_hup_source = 0;
1848 panel_iochannel_handler (GIOChannel *source, GIOCondition condition, gpointer user_data)
1850 if (condition == G_IO_IN) {
1851 if (!_panel_client.filter_event ()) {
1853 panel_initialize ();
1854 return (gboolean)FALSE;
1856 } else if (condition == G_IO_ERR || condition == G_IO_HUP) {
1858 panel_initialize ();
1859 return (gboolean)FALSE;
1861 return (gboolean)TRUE;
1865 turn_on_ic (GtkIMContextSCIM *ic)
1867 if (ic && ic->impl && !ic->impl->is_on) {
1868 ic->impl->is_on = true;
1870 if (ic == _focused_ic) {
1871 panel_req_focus_in (ic);
1872 // panel_req_update_screen (ic);
1873 panel_req_update_spot_location (ic);
1874 panel_req_update_factory_info (ic);
1875 _panel_client.turn_on (ic->id);
1876 // _panel_client.hide_preedit_string (ic->id);
1877 // _panel_client.hide_aux_string (ic->id);
1878 // _panel_client.hide_lookup_table (ic->id);
1879 ic->impl->si->focus_in ();
1882 //Record the IC on/off status
1883 if (_shared_input_method)
1884 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), true);
1886 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
1887 g_signal_emit_by_name(ic, "preedit-start");
1888 g_signal_emit_by_name(ic, "preedit-changed");
1889 ic->impl->preedit_started = true;
1895 turn_off_ic (GtkIMContextSCIM *ic)
1897 if (ic && ic->impl && ic->impl->is_on) {
1898 ic->impl->is_on = false;
1900 if (ic == _focused_ic) {
1901 ic->impl->si->focus_out ();
1903 // panel_req_update_factory_info (ic);
1904 _panel_client.turn_off (ic->id);
1907 //Record the IC on/off status
1908 if (_shared_input_method)
1909 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
1911 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
1912 g_signal_emit_by_name(ic, "preedit-changed");
1913 g_signal_emit_by_name(ic, "preedit-end");
1914 ic->impl->preedit_started = false;
1920 set_ic_capabilities (GtkIMContextSCIM *ic)
1922 if (ic && ic->impl) {
1923 unsigned int cap = SCIM_CLIENT_CAP_ALL_CAPABILITIES;
1925 if (!_on_the_spot || !ic->impl->use_preedit)
1926 cap -= SCIM_CLIENT_CAP_ONTHESPOT_PREEDIT;
1928 ic->impl->si->update_client_capabilities (cap);
1933 keyevent_gdk_to_scim (const GtkIMContextSCIM *ic, const GdkEventKey &gdkevent)
1937 // Use Key Symbole provided by gtk.
1938 key.code = gdkevent.keyval;
1940 #ifdef GDK_WINDOWING_X11
1941 Display *display = 0;
1943 if (ic && ic->impl && ic->impl->client_window)
1944 display = GDK_WINDOW_XDISPLAY (ic->impl->client_window);
1946 display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
1948 key.mask = scim_x11_keymask_x11_to_scim (display, gdkevent.state);
1950 // Special treatment for two backslash keys on jp106 keyboard.
1951 if (key.code == SCIM_KEY_backslash) {
1952 int keysym_size = 0;
1953 KeySym *keysyms = XGetKeyboardMapping (display, gdkevent.hardware_keycode, 1, &keysym_size);
1954 if (keysyms != NULL) {
1955 if (keysyms[0] == XK_backslash &&
1956 (keysym_size > 1 && keysyms[1] == XK_underscore))
1957 key.mask |= SCIM_KEY_QuirkKanaRoMask;
1962 if (gdkevent.state & GDK_SHIFT_MASK) key.mask |=SCIM_KEY_ShiftMask;
1963 if (gdkevent.state & GDK_LOCK_MASK) key.mask |=SCIM_KEY_CapsLockMask;
1964 if (gdkevent.state & GDK_CONTROL_MASK) key.mask |=SCIM_KEY_ControlMask;
1965 if (gdkevent.state & GDK_MOD1_MASK) key.mask |=SCIM_KEY_AltMask;
1966 if (gdkevent.state & GDK_MOD2_MASK) key.mask |=SCIM_KEY_NumLockMask;
1969 if (gdkevent.type == GDK_KEY_RELEASE) key.mask |= SCIM_KEY_ReleaseMask;
1975 get_gdk_keymap (GdkWindow *window)
1977 GdkKeymap *keymap = NULL;
1979 #if GDK_MULTIHEAD_SAFE
1981 keymap = gdk_keymap_get_for_display (gdk_drawable_get_display (window));
1984 keymap = gdk_keymap_get_default ();
1994 struct timezone tz; /* is not used since ages */
1995 gettimeofday (&tv, &tz);
1996 tint = (int) tv.tv_sec * 1000;
1997 tint = tint / 1000 * 1000;
1998 tint = tint + tv.tv_usec / 1000;
1999 return ((guint32) tint);
2003 keyevent_scim_to_gdk (const GtkIMContextSCIM *ic,
2004 const KeyEvent &scimkey, gboolean send_event)
2006 GdkEventKey gdkevent;
2008 #ifdef GDK_WINDOWING_X11
2009 Display *display = 0;
2011 if (ic && ic->impl && ic->impl->client_window)
2012 display = GDK_WINDOW_XDISPLAY (ic->impl->client_window);
2014 display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
2016 gdkevent.state = scim_x11_keymask_scim_to_x11 (display, scimkey.mask);
2019 if (scimkey.is_shift_down ()) gdkevent.state |= GDK_SHIFT_MASK;
2020 if (scimkey.is_caps_lock_down ()) gdkevent.state |= GDK_LOCK_MASK;
2021 if (scimkey.is_control_down ()) gdkevent.state |= GDK_CONTROL_MASK;
2022 if (scimkey.is_alt_down ()) gdkevent.state |= GDK_MOD1_MASK;
2023 if (scimkey.is_num_lock_down ()) gdkevent.state |= GDK_MOD2_MASK;
2026 if (scimkey.is_key_release ()) gdkevent.state |= GDK_RELEASE_MASK;
2028 gdkevent.type = (scimkey.is_key_release () ? GDK_KEY_RELEASE : GDK_KEY_PRESS);
2029 gdkevent.window = ((ic && ic->impl) ? ic->impl->client_window : 0);
2030 gdkevent.send_event = send_event;
2031 gdkevent.time = get_time ();
2032 gdkevent.keyval = scimkey.code;
2033 gdkevent.length = 0;
2034 gdkevent.string = 0;
2035 gdkevent.is_modifier = 0;
2037 GdkKeymap *keymap = get_gdk_keymap (gdkevent.window);
2039 GdkKeymapKey *keys = NULL;
2042 if (gdk_keymap_get_entries_for_keyval (keymap, gdkevent.keyval, &keys, &n_keys)) {
2043 gdkevent.hardware_keycode = keys [0].keycode;
2044 gdkevent.group = keys [0].group;
2046 gdkevent.hardware_keycode = 0;
2050 if (keys) g_free (keys);
2056 check_socket_frontend ()
2058 SocketAddress address;
2059 SocketClient client;
2063 address.set_address (scim_get_default_socket_frontend_address ());
2065 if (!client.connect (address))
2068 if (!scim_socket_open_connection (magic,
2069 String ("ConnectionTester"),
2070 String ("SocketFrontEnd"),
2082 std::vector<String> config_list;
2083 std::vector<String> engine_list;
2084 std::vector<String> helper_list;
2085 std::vector<String> load_engine_list;
2087 std::vector<String>::iterator it;
2089 std::vector<String> debug_mask_list;
2090 int debug_verbose = 0;
2094 bool manual = false;
2098 String config_module_name = "simple";
2104 str = getenv ("GTK_IM_SCIM_DEBUG_VERBOSE");
2107 debug_verbose = atoi (str);
2109 DebugOutput::set_verbose_level (debug_verbose);
2111 str = getenv ("GTK_IM_SCIM_DEBUG_MASK");
2114 scim_split_string_list (debug_mask_list, String (str), ',');
2115 if (debug_mask_list.size ()) {
2116 DebugOutput::disable_debug (SCIM_DEBUG_AllMask);
2117 for (i=0; i<debug_mask_list.size (); i++)
2118 DebugOutput::enable_debug_by_name (debug_mask_list [i]);
2123 SCIM_DEBUG_FRONTEND(1) << "Initializing GTK2 IMModule...\n";
2125 // Get system language.
2126 _language = scim_get_locale_language (scim_get_current_locale ());
2129 // If no Socket FrontEnd is running, then launch one.
2130 // And set manual to false.
2131 bool check_result = check_socket_frontend ();
2132 if (!check_result) {
2133 std::cerr << "Launching a daemon with Socket FrontEnd...\n";
2135 scim_get_imengine_module_list (engine_list);
2136 scim_get_helper_module_list (helper_list);
2138 for (it = engine_list.begin (); it != engine_list.end (); it++) {
2139 if (*it != "socket")
2140 load_engine_list.push_back (*it);
2142 for (it = helper_list.begin (); it != helper_list.end (); it++)
2143 load_engine_list.push_back (*it);
2144 const char *new_argv [] = { "--no-stay", 0 };
2147 (load_engine_list.size () ? scim_combine_string_list (load_engine_list, ',') : "none"),
2153 // If there is one Socket FrontEnd running and it's not manual mode,
2154 // then just use this Socket Frontend.
2156 for (int i = 0; i < 100; ++i) {
2158 config_module_name = "socket";
2159 load_engine_list.clear ();
2160 load_engine_list.push_back ("socket");
2163 scim_usleep (100000);
2164 check_result = check_socket_frontend ();
2169 if (config_module_name != "dummy") {
2170 //load config module
2171 SCIM_DEBUG_FRONTEND(1) << "Loading Config module: " << config_module_name << "...\n";
2172 _config_module = new ConfigModule (config_module_name);
2174 //create config instance
2175 if (_config_module != NULL && _config_module->valid ())
2176 _config = _config_module->create_config ();
2179 if (_config.null ()) {
2180 SCIM_DEBUG_FRONTEND(1) << "Config module cannot be loaded, using dummy Config.\n";
2182 if (_config_module) delete _config_module;
2183 _config_module = NULL;
2185 _config = new DummyConfig ();
2186 config_module_name = "dummy";
2190 gdk_color_parse ("white", &_normal_bg);
2191 gdk_color_parse ("black", &_normal_text);
2192 gdk_color_parse ("black", &_active_bg);
2193 gdk_color_parse ("white", &_active_text);
2195 reload_config_callback (_config);
2196 _config->signal_connect_reload (slot (reload_config_callback));
2199 _backend = new CommonBackEnd (_config, load_engine_list.size () ? load_engine_list : engine_list);
2201 if (_backend.null ()) {
2202 fprintf (stderr, "GTK IM Module : Cannot create BackEnd Object!\n");
2204 _backend->initialize (_config, load_engine_list.size () ? load_engine_list : engine_list, false, false);
2205 _fallback_factory = _backend->get_factory (SCIM_COMPOSE_KEY_FACTORY_UUID);
2208 if (_fallback_factory.null ()) _fallback_factory = new DummyIMEngineFactory ();
2210 _fallback_instance = _fallback_factory->create_instance (String ("UTF-8"), 0);
2211 _fallback_instance->signal_connect_commit_string (slot (fallback_commit_string_cb));
2213 // Attach Panel Client signal.
2214 _panel_client.signal_connect_reload_config (slot (panel_slot_reload_config));
2215 _panel_client.signal_connect_exit (slot (panel_slot_exit));
2216 _panel_client.signal_connect_update_lookup_table_page_size (slot (panel_slot_update_lookup_table_page_size));
2217 _panel_client.signal_connect_lookup_table_page_up (slot (panel_slot_lookup_table_page_up));
2218 _panel_client.signal_connect_lookup_table_page_down (slot (panel_slot_lookup_table_page_down));
2219 _panel_client.signal_connect_trigger_property (slot (panel_slot_trigger_property));
2220 _panel_client.signal_connect_process_helper_event (slot (panel_slot_process_helper_event));
2221 _panel_client.signal_connect_move_preedit_caret (slot (panel_slot_move_preedit_caret));
2222 _panel_client.signal_connect_select_candidate (slot (panel_slot_select_candidate));
2223 _panel_client.signal_connect_process_key_event (slot (panel_slot_process_key_event));
2224 _panel_client.signal_connect_commit_string (slot (panel_slot_commit_string));
2225 _panel_client.signal_connect_forward_key_event (slot (panel_slot_forward_key_event));
2226 _panel_client.signal_connect_request_help (slot (panel_slot_request_help));
2227 _panel_client.signal_connect_request_factory_menu (slot (panel_slot_request_factory_menu));
2228 _panel_client.signal_connect_change_factory (slot (panel_slot_change_factory));
2229 _panel_client.signal_connect_reset_keyboard_ise (slot (panel_slot_reset_keyboard_ise));
2230 _panel_client.signal_connect_show_preedit_string (slot (panel_slot_show_preedit_string));
2231 _panel_client.signal_connect_hide_preedit_string (slot (panel_slot_hide_preedit_string));
2232 _panel_client.signal_connect_update_preedit_string (slot (panel_slot_update_preedit_string));
2234 if (!panel_initialize ()) {
2235 fprintf (stderr, "GTK IM Module : Cannot connect to Panel!\n");
2242 SCIM_DEBUG_FRONTEND(1) << "Finalizing GTK2 IMModule...\n";
2244 if (_snooper_installed) {
2245 gtk_key_snooper_remove(_snooper_id);
2246 _snooper_installed=false;
2250 // Reset this first so that the shared instance could be released correctly afterwards.
2251 _default_instance.reset ();
2253 SCIM_DEBUG_FRONTEND(2) << "Finalize all IC partially.\n";
2254 while (_used_ic_impl_list) {
2255 // In case in "shared input method" mode,
2256 // all contexts share only one instance,
2257 // so we need point the reference pointer correctly before finalizing.
2258 _used_ic_impl_list->si->set_frontend_data (static_cast <void*> (_used_ic_impl_list->parent));
2259 gtk_im_context_scim_finalize_partial (_used_ic_impl_list->parent);
2262 delete_all_ic_impl ();
2264 _fallback_instance.reset ();
2265 _fallback_factory.reset ();
2267 SCIM_DEBUG_FRONTEND(2) << " Releasing BackEnd...\n";
2270 SCIM_DEBUG_FRONTEND(2) << " Releasing Config...\n";
2273 if (_config_module) {
2274 SCIM_DEBUG_FRONTEND(2) << " Deleting _config_module...\n";
2275 delete _config_module;
2280 _focused_widget = 0;
2282 _scim_initialized = false;
2288 open_next_factory (GtkIMContextSCIM *ic)
2290 SCIM_DEBUG_FRONTEND(2) << "open_next_factory context=" << ic->id << "\n";
2291 IMEngineFactoryPointer sf = _backend->get_next_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2295 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2296 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2297 ic->impl->preedit_string = WideString ();
2298 ic->impl->preedit_caret = 0;
2299 attach_instance (ic->impl->si);
2300 _backend->set_default_factory (_language, sf->get_uuid ());
2301 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2302 set_ic_capabilities (ic);
2305 if (_shared_input_method) {
2306 _default_instance = ic->impl->si;
2307 ic->impl->shared_si = true;
2313 open_previous_factory (GtkIMContextSCIM *ic)
2315 SCIM_DEBUG_FRONTEND(2) << "open_previous_factory context=" << ic->id << "\n";
2316 IMEngineFactoryPointer sf = _backend->get_previous_factory ("", "UTF-8", ic->impl->si->get_factory_uuid ());
2320 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2321 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2322 ic->impl->preedit_string = WideString ();
2323 ic->impl->preedit_caret = 0;
2324 attach_instance (ic->impl->si);
2325 _backend->set_default_factory (_language, sf->get_uuid ());
2326 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2327 set_ic_capabilities (ic);
2330 if (_shared_input_method) {
2331 _default_instance = ic->impl->si;
2332 ic->impl->shared_si = true;
2338 open_specific_factory (GtkIMContextSCIM *ic,
2341 if (!(ic && ic->impl))
2344 SCIM_DEBUG_FRONTEND(2) << "open_specific_factory context=" << ic->id << "\n";
2346 // The same input method is selected, just turn on the IC.
2347 if (ic->impl->si && ic->impl->si->get_factory_uuid () == uuid) {
2352 IMEngineFactoryPointer sf = _backend->get_factory (uuid);
2354 if (uuid.length () && !sf.null ()) {
2356 ic->impl->si = sf->create_instance ("UTF-8", ic->impl->si->get_id ());
2357 ic->impl->si->set_frontend_data (static_cast <void*> (ic));
2358 ic->impl->preedit_string = WideString ();
2359 ic->impl->preedit_caret = 0;
2360 attach_instance (ic->impl->si);
2361 _backend->set_default_factory (_language, sf->get_uuid ());
2362 _panel_client.register_input_context (ic->id, sf->get_uuid ());
2363 set_ic_capabilities (ic);
2366 if (_shared_input_method) {
2367 _default_instance = ic->impl->si;
2368 ic->impl->shared_si = true;
2371 // turn_off_ic comment out panel_req_update_factory_info()
2372 // turn_off_ic (ic);
2373 if (ic && ic->impl && ic->impl->is_on) {
2374 ic->impl->is_on = false;
2376 if (ic == _focused_ic) {
2377 ic->impl->si->focus_out ();
2379 panel_req_update_factory_info (ic);
2380 _panel_client.turn_off (ic->id);
2383 //Record the IC on/off status
2384 if (_shared_input_method)
2385 _config->write (String (SCIM_CONFIG_FRONTEND_IM_OPENED_BY_DEFAULT), false);
2387 if (ic->impl->use_preedit && ic->impl->preedit_string.length ()) {
2388 g_signal_emit_by_name(ic, "preedit-changed");
2389 g_signal_emit_by_name(ic, "preedit-end");
2390 ic->impl->preedit_started = false;
2397 attach_instance (const IMEngineInstancePointer &si)
2399 si->signal_connect_show_preedit_string (
2400 slot (slot_show_preedit_string));
2401 si->signal_connect_show_aux_string (
2402 slot (slot_show_aux_string));
2403 si->signal_connect_show_lookup_table (
2404 slot (slot_show_lookup_table));
2406 si->signal_connect_hide_preedit_string (
2407 slot (slot_hide_preedit_string));
2408 si->signal_connect_hide_aux_string (
2409 slot (slot_hide_aux_string));
2410 si->signal_connect_hide_lookup_table (
2411 slot (slot_hide_lookup_table));
2413 si->signal_connect_update_preedit_caret (
2414 slot (slot_update_preedit_caret));
2415 si->signal_connect_update_preedit_string (
2416 slot (slot_update_preedit_string));
2417 si->signal_connect_update_aux_string (
2418 slot (slot_update_aux_string));
2419 si->signal_connect_update_lookup_table (
2420 slot (slot_update_lookup_table));
2422 si->signal_connect_commit_string (
2423 slot (slot_commit_string));
2425 si->signal_connect_forward_key_event (
2426 slot (slot_forward_key_event));
2428 si->signal_connect_register_properties (
2429 slot (slot_register_properties));
2431 si->signal_connect_update_property (
2432 slot (slot_update_property));
2434 si->signal_connect_beep (
2437 si->signal_connect_start_helper (
2438 slot (slot_start_helper));
2440 si->signal_connect_stop_helper (
2441 slot (slot_stop_helper));
2443 si->signal_connect_send_helper_event (
2444 slot (slot_send_helper_event));
2446 si->signal_connect_get_surrounding_text (
2447 slot (slot_get_surrounding_text));
2449 si->signal_connect_delete_surrounding_text (
2450 slot (slot_delete_surrounding_text));
2453 // Implementation of slot functions
2455 * @brief Show the preedit string area.
2457 * The preedit string should be updated by calling
2458 * update_preedit_string before or right after this call.
2460 * @param si the IMEngineInstace pointer
2463 slot_show_preedit_string (IMEngineInstanceBase *si)
2465 SCIM_DEBUG_FRONTEND(1) << "slot_show_preedit_string...\n";
2467 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2469 if (ic && ic->impl && _focused_ic == ic) {
2470 if (ic->impl->use_preedit) {
2471 if (!ic->impl->preedit_started) {
2472 g_signal_emit_by_name (_focused_ic, "preedit-start");
2473 ic->impl->preedit_started = true;
2475 //if (ic->impl->preedit_string.length ())
2476 // g_signal_emit_by_name (_focused_ic, "preedit-changed");
2478 _panel_client.show_preedit_string (ic->id);
2484 * @brief Show the aux string area.
2486 * The aux string should be updated by calling
2487 * update_aux_string before or right after this call.
2489 * The aux string can contain any additional information whatever
2490 * the input method engine want.
2492 * @param si the IMEngineInstace pointer
2495 slot_show_aux_string (IMEngineInstanceBase *si)
2497 SCIM_DEBUG_FRONTEND(1) << "slot_show_aux_string...\n";
2499 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2501 if (ic && ic->impl && _focused_ic == ic)
2502 _panel_client.show_aux_string (ic->id);
2506 * @brief Show the lookup table area.
2508 * The lookup table should be updated by calling
2509 * update_lookup_table before or right after this call.
2511 * @param si the IMEngineInstace pointer
2514 slot_show_lookup_table (IMEngineInstanceBase *si)
2516 SCIM_DEBUG_FRONTEND(1) << "slot_show_lookup_table...\n";
2518 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2520 if (ic && ic->impl && _focused_ic == ic)
2521 _panel_client.show_lookup_table (ic->id);
2525 * @brief Hide the preedit string area.
2527 * @param si the IMEngineInstace pointer
2530 slot_hide_preedit_string (IMEngineInstanceBase *si)
2532 SCIM_DEBUG_FRONTEND(1) << "slot_hide_preedit_string...\n";
2534 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2536 if (ic && ic->impl && _focused_ic == ic) {
2538 if (ic->impl->preedit_string.length ()) {
2539 ic->impl->preedit_string = WideString ();
2540 ic->impl->preedit_caret = 0;
2541 ic->impl->preedit_attrlist.clear ();
2544 if (ic->impl->use_preedit) {
2545 if (emit) g_signal_emit_by_name (ic, "preedit-changed");
2546 if (ic->impl->preedit_started) {
2547 g_signal_emit_by_name (ic, "preedit-end");
2548 ic->impl->preedit_started = false;
2551 _panel_client.hide_preedit_string (ic->id);
2557 * @brief Hide the aux string area.
2559 * @param si the IMEngineInstace pointer
2562 slot_hide_aux_string (IMEngineInstanceBase *si)
2564 SCIM_DEBUG_FRONTEND(1) << "slot_hide_aux_string...\n";
2566 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2568 if (ic && ic->impl && _focused_ic == ic)
2569 _panel_client.hide_aux_string (ic->id);
2573 * @brief Hide the lookup table area.
2575 * @param si the IMEngineInstace pointer
2578 slot_hide_lookup_table (IMEngineInstanceBase *si)
2580 SCIM_DEBUG_FRONTEND(1) << "slot_hide_lookup_table...\n";
2582 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2584 if (ic && ic->impl && _focused_ic == ic)
2585 _panel_client.hide_lookup_table (ic->id);
2589 * @brief Update the preedit caret position in the preedit string.
2591 * @param si the IMEngineInstace pointer
2592 * @param caret - the new position of the preedit caret.
2595 slot_update_preedit_caret (IMEngineInstanceBase *si, int caret)
2597 SCIM_DEBUG_FRONTEND(1) << "slot_update_preedit_caret...\n";
2599 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2601 if (ic && ic->impl && _focused_ic == ic && ic->impl->preedit_caret != caret) {
2602 ic->impl->preedit_caret = caret;
2603 if (ic->impl->use_preedit) {
2604 if (!ic->impl->preedit_started) {
2605 g_signal_emit_by_name(_focused_ic, "preedit-start");
2606 ic->impl->preedit_started = true;
2608 g_signal_emit_by_name(ic, "preedit-changed");
2610 _panel_client.update_preedit_caret (ic->id, caret);
2616 * @brief Update the content of the preedit string,
2618 * @param si the IMEngineInstace pointer
2619 * @param str - the string content
2620 * @param attrs - the string attributes
2623 slot_update_preedit_string (IMEngineInstanceBase *si,
2624 const WideString & str,
2625 const AttributeList & attrs)
2627 SCIM_DEBUG_FRONTEND(1) << "slot_update_preedit_string...\n";
2629 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2631 if (ic && ic->impl && _focused_ic == ic && (ic->impl->preedit_string != str || str.length ())) {
2632 ic->impl->preedit_string = str;
2633 ic->impl->preedit_attrlist = attrs;
2634 if (ic->impl->use_preedit) {
2635 if (!ic->impl->preedit_started) {
2636 g_signal_emit_by_name(_focused_ic, "preedit-start");
2637 ic->impl->preedit_started = true;
2639 ic->impl->preedit_caret = str.length ();
2640 ic->impl->preedit_updating = true;
2641 g_signal_emit_by_name(ic, "preedit-changed");
2642 ic->impl->preedit_updating = false;
2644 _panel_client.update_preedit_string (ic->id, str, attrs);
2650 * @brief Update the content of the aux string,
2652 * @param si the IMEngineInstace pointer
2653 * @param str - the string content
2654 * @param attrs - the string attribute
2657 slot_update_aux_string (IMEngineInstanceBase *si,
2658 const WideString & str,
2659 const AttributeList & attrs)
2661 SCIM_DEBUG_FRONTEND(1) << "slot_update_aux_string...\n";
2663 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2665 if (ic && ic->impl && _focused_ic == ic)
2666 _panel_client.update_aux_string (ic->id, str, attrs);
2670 * @brief Commit a string to the client application.
2672 * The preedit string should be hid before calling
2673 * this method. Otherwise the clients which use
2674 * OnTheSpot input mode will flicker annoyingly.
2676 * @param si the IMEngineInstace pointer
2677 * @param str - the string to be committed.
2680 slot_commit_string (IMEngineInstanceBase *si,
2681 const WideString & str)
2683 SCIM_DEBUG_FRONTEND(1) << "slot_commit_string...\n";
2685 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2688 g_signal_emit_by_name (ic, "commit", utf8_wcstombs (str).c_str ());
2692 * @brief Forward a key event to the client application.
2694 * @param si the IMEngineInstace pointer
2695 * @param key - the key event to be forwarded.
2698 slot_forward_key_event (IMEngineInstanceBase *si,
2699 const KeyEvent & key)
2701 SCIM_DEBUG_FRONTEND(1) << "slot_forward_key_event...\n";
2703 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2705 if (ic && _focused_ic == ic) {
2706 GdkEventKey gdkevent = keyevent_scim_to_gdk (ic, key, TRUE);
2707 if (!_fallback_instance->process_key_event (key) &&
2708 !gtk_im_context_filter_keypress (GTK_IM_CONTEXT (ic->slave), &gdkevent)) {
2710 // To avoid timing issue, we need emit the signal directly, rather than put the event into the queue.
2711 if (_focused_widget) {
2713 g_signal_emit_by_name(_focused_widget, key.is_key_press () ? "key-press-event" : "key-release-event", &gdkevent, &result);
2715 gdk_event_put ((GdkEvent *) &gdkevent);
2722 * @brief Update the content of the lookup table,
2724 * @param si the IMEngineInstace pointer
2725 * @param table - the new LookupTable
2728 slot_update_lookup_table (IMEngineInstanceBase *si,
2729 const LookupTable & table)
2731 SCIM_DEBUG_FRONTEND(1) << "slot_update_lookup_table...\n";
2733 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2735 if (ic && ic->impl && _focused_ic == ic)
2736 _panel_client.update_lookup_table (ic->id, table);
2740 * @brief Register all properties of this IMEngineInstance into the FrontEnd.
2742 * The old properties previously registered by other IMEngineInstance will be discarded,
2743 * so for each time focus_in() is called, all properties should be registered
2744 * no matter whether they had been registered before.
2746 * @param si the IMEngineInstace pointer
2747 * @param properties the PropertyList contains all of the properties.
2750 slot_register_properties (IMEngineInstanceBase *si,
2751 const PropertyList & properties)
2753 SCIM_DEBUG_FRONTEND(1) << "slot_register_properties...\n";
2755 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2757 if (ic && ic->impl && _focused_ic == ic)
2758 _panel_client.register_properties (ic->id, properties);
2762 * @brief Update a registered property.
2764 * Update a property which already registered by register_properties () method.
2766 * @param si the IMEngineInstace pointer
2767 * @param property the property to be updated.
2770 slot_update_property (IMEngineInstanceBase *si,
2771 const Property & property)
2773 SCIM_DEBUG_FRONTEND(1) << "slot_update_property ...\n";
2775 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2777 if (ic && ic->impl && _focused_ic == ic)
2778 _panel_client.update_property (ic->id, property);
2782 * @brief Generate a short beep.
2784 * @param si the IMEngineInstace pointer
2787 slot_beep (IMEngineInstanceBase *si)
2789 SCIM_DEBUG_FRONTEND(1) << "slot_beep ...\n";
2791 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2793 if (ic && ic->impl && _focused_ic == ic)
2798 * @brief Start a Client Helper process.
2800 * @param si the IMEngineInstace pointer
2801 * @param helper_uuid The UUID of the Helper object.
2804 slot_start_helper (IMEngineInstanceBase *si,
2805 const String &helper_uuid)
2807 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2809 SCIM_DEBUG_FRONTEND(1) << "slot_start_helper helper= " << helper_uuid << " context="
2810 << (ic ? ic->id : -1) << " ic=" << ic
2811 << " ic-uuid=" << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
2814 _panel_client.start_helper (ic->id, helper_uuid);
2818 * @brief Stop a Client Helper process which was started by start_helper.
2820 * @param si the IMEngineInstace pointer
2821 * @param helper_uuid The UUID of the Helper object.
2824 slot_stop_helper (IMEngineInstanceBase *si,
2825 const String &helper_uuid)
2827 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2829 SCIM_DEBUG_FRONTEND(1) << "slot_stop_helper helper= " << helper_uuid << " context=" << (ic ? ic->id : -1) << " ic=" << ic << "...\n";
2832 _panel_client.stop_helper (ic->id, helper_uuid);
2836 * @brief Send an events transaction to a client helper process.
2838 * @param si the IMEngineInstace pointer
2839 * @param helper_uuid The UUID of the Helper object.
2840 * @param trans The transaction which contains events.
2843 slot_send_helper_event (IMEngineInstanceBase *si,
2844 const String &helper_uuid,
2845 const Transaction &trans)
2847 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2849 SCIM_DEBUG_FRONTEND(1) << "slot_send_helper_event helper= " << helper_uuid << " context="
2850 << (ic ? ic->id : -1) << " ic=" << ic
2851 << " ic-uuid=" << ((ic && ic->impl) ? ic->impl->si->get_factory_uuid () : "") << "...\n";
2854 _panel_client.send_helper_event (ic->id, helper_uuid, trans);
2858 * @brief Retrieves context around the insertion point.
2860 * @param si the IMEngineInstace pointer
2861 * @param text location to store the context string around the insertion point.
2862 * @param cursor location to store index of the insertion cursor within @text.
2863 * @param maxlen_before the maxmium length of context string to be retrieved
2864 * before the cursor; -1 means unlimited.
2865 * @param maxlen_after the maxmium length of context string to be retrieved
2866 * after the cursor; -1 means unlimited.
2868 * @return true if surrounding text was provided.
2871 slot_get_surrounding_text (IMEngineInstanceBase *si,
2877 SCIM_DEBUG_FRONTEND(1) << "slot_get_surrounding_text ...\n";
2879 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2881 if (ic && ic->impl && _focused_ic == ic) {
2882 gchar *surrounding = NULL;
2884 if (gtk_im_context_get_surrounding (GTK_IM_CONTEXT (_focused_ic), &surrounding, &cursor_index)) {
2885 SCIM_DEBUG_FRONTEND(2) << "Surrounding text: " << surrounding <<"\n";
2886 SCIM_DEBUG_FRONTEND(2) << "Cursor Index : " << cursor_index <<"\n";
2887 WideString before (utf8_mbstowcs (String (surrounding, surrounding + cursor_index)));
2888 WideString after (utf8_mbstowcs (String (surrounding + cursor_index)));
2889 if (maxlen_before > 0 && ((unsigned int)maxlen_before) < before.length ())
2890 before = WideString (before.begin () + (before.length () - maxlen_before), before.end ());
2891 else if (maxlen_before == 0) before = WideString ();
2892 if (maxlen_after > 0 && ((unsigned int)maxlen_after) < after.length ())
2893 after = WideString (after.begin (), after.begin () + maxlen_after);
2894 else if (maxlen_after == 0) after = WideString ();
2895 text = before + after;
2896 cursor = before.length ();
2904 * @brief Ask the client to delete characters around the cursor position.
2906 * @param si the IMEngineInstace pointer
2907 * @param offset offset from cursor position in chars;
2908 * a negative value means start before the cursor.
2909 * @param len number of characters to delete.
2911 * @return true if the signal was handled.
2914 slot_delete_surrounding_text (IMEngineInstanceBase *si,
2918 SCIM_DEBUG_FRONTEND(1) << "slot_delete_surrounding_text ...\n";
2920 GtkIMContextSCIM *ic = static_cast<GtkIMContextSCIM *> (si->get_frontend_data ());
2922 if (ic && ic->impl && _focused_ic == ic)
2923 return gtk_im_context_delete_surrounding (GTK_IM_CONTEXT (_focused_ic), offset, len);
2928 reload_config_callback (const ConfigPointer &config)
2930 SCIM_DEBUG_FRONTEND(1) << "reload_config_callback...\n";
2932 _frontend_hotkey_matcher.load_hotkeys (config);
2933 _imengine_hotkey_matcher.load_hotkeys (config);
2937 scim_string_to_key (key,
2938 config->read (String (SCIM_CONFIG_HOTKEYS_FRONTEND_VALID_KEY_MASK),
2939 String ("Shift+Control+Alt+Lock")));
2941 _valid_key_mask = (key.mask > 0)?(key.mask):0xFFFF;
2942 _valid_key_mask |= SCIM_KEY_ReleaseMask;
2943 // Special treatment for two backslash keys on jp106 keyboard.
2944 _valid_key_mask |= SCIM_KEY_QuirkKanaRoMask;
2946 _on_the_spot = config->read (String (SCIM_CONFIG_FRONTEND_ON_THE_SPOT), _on_the_spot);
2947 _shared_input_method = config->read (String (SCIM_CONFIG_FRONTEND_SHARED_INPUT_METHOD), _shared_input_method);
2948 _use_key_snooper = config->read (String (SCIM_CONFIG_FRONTEND_GTK_IMMODULE_USE_KEY_SNOOPER), _use_key_snooper);
2950 // Get keyboard layout setting
2951 // Flush the global config first, in order to load the new configs from disk.
2952 scim_global_config_flush ();
2954 _keyboard_layout = scim_get_default_keyboard_layout ();
2958 fallback_commit_string_cb (IMEngineInstanceBase *si,
2959 const WideString &str)
2961 if (_focused_ic && _focused_ic->impl)
2962 g_signal_emit_by_name (_focused_ic, "commit", utf8_wcstombs (str).c_str ());
2966 vi:ts=4:expandtab:nowrap