1 /*
2
3 Copyright (c) 2003-2013 uim Project https://github.com/uim/uim
4
5 All rights reserved.
6
7 Redistribution and use in source and binary forms, with or without
8 modification, are permitted provided that the following conditions
9 are met:
10
11 1. Redistributions of source code must retain the above copyright
12 notice, this list of conditions and the following disclaimer.
13 2. Redistributions in binary form must reproduce the above copyright
14 notice, this list of conditions and the following disclaimer in the
15 documentation and/or other materials provided with the distribution.
16 3. Neither the name of authors nor the names of its contributors
17 may be used to endorse or promote products derived from this software
18 without specific prior written permission.
19
20 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND
21 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE
24 FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 SUCH DAMAGE.
31
32 */
33 #include "qhelpermanager.h"
34
35 #include <QtCore/QSocketNotifier>
36 #include <QtCore/QStringList>
37 #include <QtCore/QTextCodec>
38
39 #include "uim/uim.h"
40 #include "uim/uim-helper.h"
41 #include "uim/uim-im-switcher.h"
42 #include "uim/uim-util.h"
43
44 #include "plugin.h"
45 #include "quiminfomanager.h"
46 #if QT_VERSION < 0x050000
47 # include "quiminputcontext.h"
48 #else
49 # include <quimplatforminputcontext.h>
50 #endif
51
52 static int im_uim_fd = 0;
53 static QSocketNotifier *notifier = 0;
54
55 #if QT_VERSION < 0x050000
56 extern QUimInputContext *focusedInputContext;
57 #else
58 extern QUimPlatformInputContext *focusedInputContext;
59 #endif
60 extern bool disableFocusedContext;
61
62 #if QT_VERSION < 0x050000
63 extern QList<QUimInputContext *> contextList;
64 #else
65 extern QList<QUimPlatformInputContext *> contextList;
66 #endif
67
QUimHelperManager(QObject * parent)68 QUimHelperManager::QUimHelperManager( QObject *parent )
69 : QObject( parent )
70 {
71 notifier = 0;
72 im_uim_fd = -1;
73 }
74
~QUimHelperManager()75 QUimHelperManager::~QUimHelperManager()
76 {
77 if ( im_uim_fd != -1 )
78 uim_helper_close_client_fd( im_uim_fd );
79 }
80
checkHelperConnection(uim_context uc)81 void QUimHelperManager::checkHelperConnection(uim_context uc)
82 {
83 if ( im_uim_fd < 0 )
84 {
85 im_uim_fd = uim_helper_init_client_fd( QUimHelperManager::helper_disconnect_cb );
86
87 if ( im_uim_fd >= 0 )
88 {
89 notifier = new QSocketNotifier( im_uim_fd, QSocketNotifier::Read );
90 connect( notifier, SIGNAL( activated( int ) ),
91 this, SLOT( slotStdinActivated() ) );
92 uim_set_uim_fd(uc, im_uim_fd);
93 }
94 }
95 }
96
slotStdinActivated()97 void QUimHelperManager::slotStdinActivated()
98 {
99 char *tmp;
100 uim_helper_read_proc( im_uim_fd );
101 while ((tmp = uim_helper_get_message()))
102 {
103 parseHelperStr(QString::fromUtf8(tmp));
104 free(tmp);
105 }
106 }
107
parseHelperStr(const QString & str)108 void QUimHelperManager::parseHelperStr( const QString &str )
109 {
110 if ( focusedInputContext && !disableFocusedContext )
111 {
112 if ( str.startsWith( QLatin1String( "prop_list_get" ) ) )
113 uim_prop_list_update( focusedInputContext->uimContext() );
114 else if ( str.startsWith( QLatin1String( "prop_label_get" ) ) )
115 uim_prop_label_update( focusedInputContext->uimContext() );
116 else if ( str.startsWith( QLatin1String( "prop_activate" ) ) )
117 {
118 QStringList list = str.split( '\n' );
119 uim_prop_activate( focusedInputContext->uimContext(),
120 list[ 1 ].toUtf8().data() );
121 }
122 else if ( str.startsWith( QLatin1String( "im_list_get" ) ) )
123 {
124 sendImList();
125 }
126 else if ( str.startsWith( QLatin1String( "commit_string" ) ) )
127 {
128 QStringList lines = str.split( '\n' );
129 if ( !lines.isEmpty() && !lines[ 1 ].isEmpty() ) {
130 QString commit_str;
131
132 if ( lines[ 1 ].startsWith( QLatin1String( "charset" ) ) ) {
133 /* get charset */
134 QString charset = lines[ 1 ].split( '=' ) [ 1 ];
135
136 /* convert to unicode */
137 QTextCodec *codec
138 = QTextCodec::codecForName( charset.toLatin1() );
139 if ( codec && !lines[ 2 ].isEmpty() )
140 commit_str = codec->toUnicode( lines[ 2 ].toLatin1() );
141 } else {
142 commit_str = lines[ 1 ];
143 }
144
145 focusedInputContext->commitString( commit_str );
146 }
147 }
148 else if ( str.startsWith( QLatin1String( "focus_in" ) ) )
149 {
150 // We shouldn't do "focusedInputContext = NULL" here, because some
151 // window manager has some focus related bugs.
152 disableFocusedContext = true;
153 }
154 }
155
156 /**
157 * This part should be processed even if not focused
158 */
159 if ( str.startsWith( QLatin1String( "im_change" ) ) )
160 {
161 // for IM switcher
162 parseHelperStrImChange( str );
163 }
164 else if ( str.startsWith( QLatin1String( "prop_update_custom" ) ) )
165 {
166 // for custom api
167 QStringList list = str.split( '\n' );
168 if ( !list.isEmpty() && !list[ 0 ].isEmpty() &&
169 !list[ 1 ].isEmpty() && !list[ 2 ].isEmpty() )
170 {
171 #if QT_VERSION < 0x050000
172 QList<QUimInputContext *>::iterator it;
173 #else
174 QList<QUimPlatformInputContext *>::iterator it;
175 #endif
176 for ( it = contextList.begin(); it != contextList.end(); ++it )
177 {
178 uim_prop_update_custom( ( *it )->uimContext(),
179 list[ 1 ].toUtf8().data(),
180 list[ 2 ].toUtf8().data() );
181 if ( list[ 1 ]
182 == QLatin1String( "candidate-window-position" ) )
183 ( *it )->updatePosition();
184 if ( list[ 1 ]
185 == QLatin1String( "candidate-window-style" ) )
186 ( *it )->updateStyle();
187 break; /* all custom variables are global */
188 }
189 }
190 }
191 else if ( str.startsWith( QLatin1String( "custom_reload_notify" ) ) )
192 {
193 uim_prop_reload_configs();
194
195 QUimInfoManager *infoManager =
196 UimInputContextPlugin::getQUimInfoManager();
197 infoManager->initUimInfo();
198
199 #if QT_VERSION < 0x050000
200 QList<QUimInputContext *>::iterator it;
201 #else
202 QList<QUimPlatformInputContext *>::iterator it;
203 #endif
204 for ( it = contextList.begin(); it != contextList.end(); ++it ) {
205 ( *it )->updatePosition();
206 ( *it )->updateStyle();
207 }
208 }
209 }
210
parseHelperStrImChange(const QString & str)211 void QUimHelperManager::parseHelperStrImChange( const QString &str )
212 {
213 QStringList list = str.split( '\n' );
214 QString im_name = list[ 1 ];
215 QString im_name_sym = '\'' + im_name;
216
217 if ( str.startsWith( QLatin1String( "im_change_this_text_area_only" ) ) )
218 {
219 if ( focusedInputContext )
220 {
221 uim_switch_im( focusedInputContext->uimContext(),
222 im_name.toUtf8().data() );
223 uim_prop_list_update( focusedInputContext->uimContext() );
224 focusedInputContext->updatePosition();
225 }
226 }
227 else if ( str.startsWith( QLatin1String( "im_change_whole_desktop" ) ) )
228 {
229 #if QT_VERSION < 0x050000
230 QList<QUimInputContext *>::iterator it;
231 #else
232 QList<QUimPlatformInputContext *>::iterator it;
233 #endif
234 for ( it = contextList.begin(); it != contextList.end(); ++it )
235 {
236 uim_switch_im( ( *it )->uimContext(), im_name.toUtf8().data() );
237 ( *it )->updatePosition();
238 uim_prop_update_custom( ( *it )->uimContext(),
239 "custom-preserved-default-im-name",
240 im_name_sym.toUtf8().data() );
241 }
242 }
243 else if ( str.startsWith( QLatin1String(
244 "im_change_this_application_only" ) ) )
245 {
246 if ( focusedInputContext )
247 {
248 #if QT_VERSION < 0x050000
249 QList<QUimInputContext *>::iterator it;
250 #else
251 QList<QUimPlatformInputContext *>::iterator it;
252 #endif
253 for ( it = contextList.begin(); it != contextList.end(); ++it )
254 {
255 uim_switch_im( ( *it )->uimContext(), im_name.toUtf8().data() );
256 ( *it )->updatePosition();
257 uim_prop_update_custom( ( *it )->uimContext(),
258 "custom-preserved-default-im-name",
259 im_name_sym.toUtf8().data() );
260 }
261 }
262 }
263 }
264
sendImList()265 void QUimHelperManager::sendImList()
266 {
267 if ( !focusedInputContext )
268 return ;
269
270 QString msg = "im_list\ncharset=UTF-8\n";
271 const char* current_im_name = uim_get_current_im_name( focusedInputContext->uimContext() );
272
273 QUimInfoManager *infoManager = UimInputContextPlugin::getQUimInfoManager();
274 QList<uimInfo> info = infoManager->getUimInfo();
275 QList<uimInfo>::iterator it;
276
277 for ( it = info.begin(); it != info.end(); ++it )
278 {
279 QString leafstr;
280 leafstr.sprintf( "%s\t%s\t%s\t",
281 ( *it ).name.toUtf8().data(),
282 uim_get_language_name_from_locale( ( *it ).lang.toUtf8().data() ),
283 ( *it).short_desc.toUtf8().data() );
284
285 if ( QString::compare( ( *it ).name, current_im_name ) == 0 )
286 leafstr.append( "selected" );
287
288 leafstr.append( "\n" );
289
290 msg += leafstr;
291 }
292
293 uim_helper_send_message( im_uim_fd, msg.toUtf8().data() );
294 }
295
send_im_change_whole_desktop(const char * name)296 void QUimHelperManager::send_im_change_whole_desktop( const char *name )
297 {
298 QString msg;
299
300 msg.sprintf("im_change_whole_desktop\n%s\n", name);
301 uim_helper_send_message( im_uim_fd, msg.toUtf8().data() );
302 }
303
helper_disconnect_cb()304 void QUimHelperManager::helper_disconnect_cb()
305 {
306 im_uim_fd = -1;
307
308 if ( notifier )
309 {
310 delete notifier;
311 notifier = 0;
312 }
313 }
314
update_prop_list_cb(void * ptr,const char * str)315 void QUimHelperManager::update_prop_list_cb( void *ptr, const char *str )
316 {
317 #if QT_VERSION < 0x050000
318 QUimInputContext *ic = static_cast<QUimInputContext*>( ptr );
319 #else
320 QUimPlatformInputContext *ic = static_cast<QUimPlatformInputContext*>( ptr );
321 #endif
322
323 if ( ic != focusedInputContext || disableFocusedContext )
324 return;
325
326 QString msg = "prop_list_update\ncharset=UTF-8\n";
327 msg += QString::fromUtf8( str );
328
329 uim_helper_send_message( im_uim_fd, msg.toUtf8().data() );
330
331 ic->updateIndicator( msg );
332 }
333
update_prop_label_cb(void * ptr,const char * str)334 void QUimHelperManager::update_prop_label_cb( void *ptr, const char *str )
335 {
336 #if QT_VERSION < 0x050000
337 QUimInputContext *ic = static_cast<QUimInputContext*>( ptr );
338 #else
339 QUimPlatformInputContext *ic = static_cast<QUimPlatformInputContext*>( ptr );
340 #endif
341 if ( ic != focusedInputContext || disableFocusedContext )
342 return;
343
344 QString msg = "prop_label_update\ncharset=UTF-8\n";
345 msg += QString::fromUtf8( str );
346
347 uim_helper_send_message( im_uim_fd, msg.toUtf8().data() );
348 }
349