Tizen 2.1 base
[framework/uifw/ise-engine-anthy.git] / src / scim_anthy_helper.cpp
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3  *  Copyright (C) 2005 Takuro Ashie
4  *
5  *  This program is free software; you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation; either version 2, or (at your option)
8  *  any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #define Uses_SCIM_HELPER
21 #define Uses_SCIM_CONFIG_BASE
22 #include <map>
23 #include <scim.h>
24 #include <gtk/gtk.h>
25 #include "scim_anthy_intl.h"
26 #include "scim_anthy_helper.h"
27
28 using namespace scim;
29
30 #define scim_module_init anthy_imengine_helper_LTX_scim_module_init
31 #define scim_module_exit anthy_imengine_helper_LTX_scim_module_exit
32 #define scim_helper_module_number_of_helpers anthy_imengine_helper_LTX_scim_helper_module_number_of_helpers
33 #define scim_helper_module_get_helper_info anthy_imengine_helper_LTX_scim_helper_module_get_helper_info
34 #define scim_helper_module_run_helper anthy_imengine_helper_LTX_scim_helper_module_run_helper
35
36 static gboolean   helper_agent_input_handler  (GIOChannel          *source,
37                                                GIOCondition         condition,
38                                                gpointer             user_data);
39 static void       slot_imengine_event         (const HelperAgent   *agent,
40                                                int                  ic,
41                                                const String        &uuid,
42                                                const Transaction   &trans);
43 static gint       timeout_func                (gpointer             data);
44 static void       timeout_ctx_destroy_func    (gpointer             data);
45
46 static void       run                         (const String        &display,
47                                                const ConfigPointer &config);
48
49 HelperAgent helper_agent;
50
51 HelperInfo helper_info (SCIM_ANTHY_HELPER_UUID,        // uuid
52                         "",                            // name
53                         "",                            // icon
54                         "",
55                         SCIM_HELPER_NEED_SCREEN_INFO);
56
57 class TimeoutContext {
58 public:
59     TimeoutContext (int ic, const String &uuid, uint32 id)
60         : m_ic   (ic),
61           m_uuid (uuid),
62           m_id   (id)
63         {}
64     virtual ~TimeoutContext () {}
65 public:
66     int    m_ic;
67     String m_uuid;
68     uint32 m_id;
69 };
70 typedef std::map <uint32, guint> TimeoutIDList;
71 std::map <int, TimeoutIDList> timeout_ids;
72
73
74 //Module Interface
75 extern "C" {
76     void scim_module_init (void)
77     {
78         bindtextdomain (GETTEXT_PACKAGE, SCIM_ANTHY_LOCALEDIR);
79         bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
80
81         helper_info.name = String (_("Anthy helper"));
82         helper_info.description = String (
83             _("A helper module for Anthy IMEngine."));
84     }
85
86     void scim_module_exit (void)
87     {
88     }
89
90     unsigned int scim_helper_module_number_of_helpers (void)
91     {
92         return 1;
93     }
94
95     bool scim_helper_module_get_helper_info (unsigned int idx, HelperInfo &info)
96     {
97         if (idx == 0) {
98             info = helper_info; 
99             return true;
100         }
101         return false;
102     }
103
104     void scim_helper_module_run_helper (const String &uuid,
105                                         const ConfigPointer &config,
106                                         const String &display)
107     {
108         SCIM_DEBUG_MAIN(1) << "anthy_imengine_helper_LTX_scim_helper_module_run_helper ()\n";
109
110         if (uuid == String (SCIM_ANTHY_HELPER_UUID)) {
111             run (display, config);
112         }
113
114         SCIM_DEBUG_MAIN(1) << "exit anthy_imengine_helper_LTX_scim_helper_module_run_helper ()\n";
115     }
116 }
117
118
119 static gboolean
120 helper_agent_input_handler (GIOChannel *source,
121                             GIOCondition condition,
122                             gpointer user_data)
123 {
124     if (condition == G_IO_IN) {
125         HelperAgent *agent = static_cast<HelperAgent*> (user_data);
126         if (agent && agent->has_pending_event ())
127             agent->filter_event ();
128     } else if (condition == G_IO_ERR || condition == G_IO_HUP) {
129         gtk_main_quit ();
130     }
131     return TRUE;
132 }
133
134 static void
135 slot_exit (const HelperAgent *agent, int ic, const String &uuid)
136 {
137     gtk_main_quit ();
138 }
139
140 static void
141 slot_imengine_event (const HelperAgent *agent, int ic,
142                      const String &uuid, const Transaction &recv)
143 {
144     TransactionReader reader (recv);
145     int cmd;
146
147     if (!reader.get_command (cmd))
148         return;
149
150     switch (cmd) {
151     case SCIM_ANTHY_TRANS_CMD_GET_SELECTION:
152     {
153         GtkClipboard *primary_selection;
154         WideString selection;
155
156         primary_selection = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
157         if (primary_selection) {
158             gchar *text = gtk_clipboard_wait_for_text (primary_selection);
159             if (text) {
160                 selection = utf8_mbstowcs (text);
161                 g_free (text);
162             }
163         }
164
165         Transaction send;
166         send.put_command (SCIM_ANTHY_TRANS_CMD_GET_SELECTION);
167         send.put_data (selection);
168         helper_agent.send_imengine_event (ic, uuid, send);
169
170         break;
171     }
172     case SCIM_ANTHY_TRANS_CMD_TIMEOUT_ADD:
173     {
174         uint32 id, time_msec;
175         if (!reader.get_data (id) || !reader.get_data (time_msec))
176             break;
177         TimeoutContext *ctx = new TimeoutContext (ic, uuid, id);
178         guint timeout_id = gtk_timeout_add_full (time_msec,
179                                                  timeout_func,
180                                                  NULL,
181                                                  (gpointer) ctx,
182                                                  timeout_ctx_destroy_func);
183         timeout_ids[ic][id] = timeout_id;
184         break;
185     }
186     case SCIM_ANTHY_TRANS_CMD_TIMEOUT_REMOVE:
187     {
188         uint32 id;
189         if (reader.get_data (id) &&
190             timeout_ids.find (ic) != timeout_ids.end () &&
191             timeout_ids[ic].find (id) != timeout_ids[ic].end ())
192         {
193             guint tid = timeout_ids[ic][id];
194             gtk_timeout_remove (tid);
195         }
196         break;
197     }
198     default:
199         break;
200     }
201 }
202
203 static gint
204 timeout_func (gpointer data)
205 {
206     TimeoutContext *ctx = static_cast<TimeoutContext*> (data);
207
208     Transaction send;
209     send.put_command (SCIM_ANTHY_TRANS_CMD_TIMEOUT_NOTIFY);
210     send.put_data (ctx->m_id);
211     helper_agent.send_imengine_event (ctx->m_ic, ctx->m_uuid, send);
212
213     return FALSE;
214 }
215
216 static void
217 timeout_ctx_destroy_func (gpointer data)
218 {
219     TimeoutContext *ctx = static_cast<TimeoutContext*> (data);
220     int ic = ctx->m_ic;
221     uint32 id = ctx->m_id;
222
223     if (timeout_ids.find (ic) != timeout_ids.end () &&
224         timeout_ids[ic].find (id) != timeout_ids[ic].end ())
225     {
226         timeout_ids[ic].erase (id);
227     }
228     delete ctx;
229 }
230
231 static void
232 run (const String &display, const ConfigPointer &config)
233 {
234     char **argv = new char * [4];
235     int    argc = 3;
236
237     argv [0] = "anthy-imengine-helper";
238     argv [1] = "--display";
239     argv [2] = const_cast<char *> (display.c_str ());
240     argv [3] = 0;
241  
242     setenv ("DISPLAY", display.c_str (), 1);
243
244     gtk_init (&argc, &argv);
245
246     helper_agent.signal_connect_exit (slot (slot_exit));
247     helper_agent.signal_connect_process_imengine_event (slot (slot_imengine_event));
248
249     // open connection
250     int fd = helper_agent.open_connection (helper_info, display);
251     GIOChannel *ch = g_io_channel_unix_new (fd);
252
253     if (fd >= 0 && ch) {
254         g_io_add_watch (ch, G_IO_IN,
255                         helper_agent_input_handler,
256                         (gpointer) &helper_agent);
257         g_io_add_watch (ch, G_IO_ERR,
258                         helper_agent_input_handler,
259                         (gpointer) &helper_agent);
260         g_io_add_watch (ch, G_IO_HUP,
261                         helper_agent_input_handler,
262                         (gpointer) &helper_agent);
263     }
264
265     gtk_main ();
266
267     // close connection
268     helper_agent.close_connection ();
269     fd = -1;
270 }