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 <config.h>
34
35 #include <qsocketnotifier.h>
36 #include <qstring.h>
37 #include <qstringlist.h>
38 #include <qtextcodec.h>
39
40 #include "uim/uim.h"
41 #include "uim/uim-util.h"
42 #include "uim/uim-helper.h"
43 #include "uim/uim-im-switcher.h"
44
45 #include "qhelpermanager.h"
46 #include "quiminputcontext.h"
47 #include "quiminfomanager.h"
48 #include "plugin.h"
49
50 static int im_uim_fd = 0;
51 static QSocketNotifier *notifier = NULL;
52
53 extern QUimInputContext *focusedInputContext;
54 extern bool disableFocusedContext;
55
56 extern QPtrList<QUimInputContext> contextList;
57
QUimHelperManager(QObject * parent,const char * name)58 QUimHelperManager::QUimHelperManager( QObject *parent, const char *name )
59 : QObject( parent, name )
60 {
61 notifier = NULL;
62 im_uim_fd = -1;
63 }
64
~QUimHelperManager()65 QUimHelperManager::~QUimHelperManager()
66 {
67 if ( im_uim_fd != -1 )
68 uim_helper_close_client_fd( im_uim_fd );
69 }
70
checkHelperConnection()71 void QUimHelperManager::checkHelperConnection()
72 {
73 if ( im_uim_fd < 0 )
74 {
75 im_uim_fd = uim_helper_init_client_fd( QUimHelperManager::helper_disconnect_cb );
76
77 if ( im_uim_fd >= 0 )
78 {
79 notifier = new QSocketNotifier( im_uim_fd, QSocketNotifier::Read );
80 QObject::connect( notifier, SIGNAL( activated( int ) ),
81 this, SLOT( slotStdinActivated( int ) ) );
82 }
83 }
84 }
85
slotStdinActivated(int)86 void QUimHelperManager::slotStdinActivated( int /*socket*/ )
87 {
88 QString tmp;
89
90 uim_helper_read_proc( im_uim_fd );
91 while ( ( tmp = QString::fromUtf8( uim_helper_get_message() ) ) )
92 parseHelperStr( tmp );
93 }
94
parseHelperStr(const QString & str)95 void QUimHelperManager::parseHelperStr( const QString &str )
96 {
97 if ( focusedInputContext && !disableFocusedContext )
98 {
99 if ( str.startsWith( "prop_list_get" ) )
100 uim_prop_list_update( focusedInputContext->uimContext() );
101 else if ( str.startsWith( "prop_label_get" ) )
102 uim_prop_label_update( focusedInputContext->uimContext() );
103 else if ( str.startsWith( "prop_activate" ) )
104 {
105 QStringList lines = QStringList::split( "\n", str );
106 uim_prop_activate( focusedInputContext->uimContext(), ( const char* ) lines[ 1 ] );
107 }
108 else if ( str.startsWith( "im_list_get" ) )
109 {
110 sendImList();
111 }
112 else if ( str.startsWith( "commit_string" ) )
113 {
114 QStringList lines = QStringList::split( "\n", str );
115 if ( !lines.isEmpty() && !lines[ 1 ].isEmpty() ) {
116 QString commit_str = QString::null;
117
118 if ( lines[ 1 ].startsWith( "charset" ) ) {
119 /* get charset */
120 QString charset = QStringList::split( "=", lines[ 1 ] ) [ 1 ];
121
122 /* convert to unicode */
123 QTextCodec *codec = QTextCodec::codecForName( charset );
124 if ( codec && !lines[ 2 ].isEmpty() )
125 commit_str = codec->toUnicode( lines[ 2 ] );
126 } else {
127 commit_str = lines[ 1 ];
128 }
129
130 focusedInputContext->commitString( commit_str );
131 }
132 }
133 else if ( str.startsWith( "focus_in" ) )
134 {
135 // We shouldn't do "focusedInputContext = NULL" here, because some
136 // window manager has some focus related bugs.
137 disableFocusedContext = true;
138 }
139 }
140
141 /**
142 * This part should be processed even if not focused
143 */
144 if ( str.startsWith( "im_change" ) )
145 {
146 // for IM switcher
147 parseHelperStrImChange( str );
148 }
149 else if ( str.startsWith( "prop_update_custom" ) )
150 {
151 // for custom api
152 QUimInputContext * cc;
153 QStringList list = QStringList::split( "\n", str );
154 if ( !list.isEmpty() && !list[ 0 ].isEmpty() &&
155 !list[ 1 ].isEmpty() && !list[ 2 ].isEmpty() )
156 {
157 for ( cc = contextList.first(); cc; cc = contextList.next() )
158 {
159 uim_prop_update_custom( cc->uimContext(), list[ 1 ], list[ 2 ] );
160 break; /* all custom variables are global */
161 }
162 }
163 }
164 else if ( str.startsWith( "custom_reload_notify" ) )
165 {
166 uim_prop_reload_configs();
167
168 QUimInfoManager *infoManager =
169 UimInputContextPlugin::getQUimInfoManager();
170 infoManager->initUimInfo();
171 }
172 }
173
parseHelperStrImChange(const QString & str)174 void QUimHelperManager::parseHelperStrImChange( const QString &str )
175 {
176 QUimInputContext * cc;
177 QStringList list = QStringList::split( "\n", str );
178 QString im_name = list[ 1 ];
179 QString im_name_sym = "'" + im_name;
180
181 if ( str.startsWith( "im_change_this_text_area_only" ) )
182 {
183 if ( focusedInputContext )
184 {
185 uim_switch_im( focusedInputContext->uimContext(), ( const char* ) im_name );
186 uim_prop_list_update( focusedInputContext->uimContext() );
187 focusedInputContext->readIMConf();
188 }
189 }
190 else if ( str.startsWith( "im_change_whole_desktop" ) )
191 {
192 for ( cc = contextList.first(); cc; cc = contextList.next() )
193 {
194 uim_switch_im( cc->uimContext(), ( const char* ) im_name );
195 cc->readIMConf();
196 uim_prop_update_custom( cc->uimContext(),
197 "custom-preserved-default-im-name",
198 ( const char* ) im_name_sym );
199 }
200 }
201 else if ( str.startsWith( "im_change_this_application_only" ) )
202 {
203 if ( focusedInputContext )
204 {
205 for ( cc = contextList.first(); cc; cc = contextList.next() )
206 {
207 uim_switch_im( cc->uimContext(), ( const char* ) im_name );
208 cc->readIMConf();
209 uim_prop_update_custom( cc->uimContext(),
210 "custom-preserved-default-im-name",
211 ( const char* ) im_name_sym );
212 }
213 }
214 }
215 }
216
sendImList()217 void QUimHelperManager::sendImList()
218 {
219 if ( !focusedInputContext )
220 return ;
221
222 QString msg = "im_list\ncharset=UTF-8\n";
223 const char* current_im_name = uim_get_current_im_name( focusedInputContext->uimContext() );
224
225 QUimInfoManager *infoManager = UimInputContextPlugin::getQUimInfoManager();
226 QValueList<uimInfo> info = infoManager->getUimInfo();
227 QValueList<uimInfo>::iterator it;
228
229 for ( it = info.begin(); it != info.end(); ++it )
230 {
231 QString leafstr;
232 leafstr.sprintf( "%s\t%s\t%s\t",
233 (const char *)( *it ).name,
234 uim_get_language_name_from_locale( ( *it ).lang ),
235 (const char *)( *it).short_desc );
236
237 if ( QString::compare( ( *it ).name, current_im_name ) == 0 )
238 leafstr.append( "selected" );
239
240 leafstr.append( "\n" );
241
242 msg += leafstr;
243 }
244
245 uim_helper_send_message( im_uim_fd, ( const char* ) msg.utf8() );
246 }
247
send_im_change_whole_desktop(const char * name)248 void QUimHelperManager::send_im_change_whole_desktop( const char *name )
249 {
250 QString msg;
251
252 msg.sprintf("im_change_whole_desktop\n%s\n", name);
253 uim_helper_send_message( im_uim_fd, ( const char* ) msg );
254 }
255
helper_disconnect_cb()256 void QUimHelperManager::helper_disconnect_cb()
257 {
258 im_uim_fd = -1;
259
260 if ( notifier )
261 {
262 delete notifier;
263 notifier = 0;
264 }
265 }
266
update_prop_list_cb(void * ptr,const char * str)267 void QUimHelperManager::update_prop_list_cb( void *ptr, const char *str )
268 {
269 QUimInputContext *ic = ( QUimInputContext* ) ptr;
270 if ( ic != focusedInputContext || disableFocusedContext )
271 return;
272
273 QString msg = "prop_list_update\ncharset=UTF-8\n";
274 msg += QString::fromUtf8( str );
275
276 uim_helper_send_message( im_uim_fd, ( const char* ) msg.utf8() );
277 }
278
update_prop_label_cb(void * ptr,const char * str)279 void QUimHelperManager::update_prop_label_cb( void *ptr, const char *str )
280 {
281 QUimInputContext *ic = ( QUimInputContext* ) ptr;
282 if ( ic != focusedInputContext || disableFocusedContext )
283 return;
284
285 QString msg = "prop_label_update\ncharset=UTF-8\n";
286 msg += QString::fromUtf8( str );
287
288 uim_helper_send_message( im_uim_fd, ( const char* ) msg.utf8() );
289 }
290
291 #include "qhelpermanager.moc"
292