1 /***************************************************************************
2 * Copyright (C) 2008~2010 by Zealot.Hoi *
3 * Copyright (C) 2010~2012 by CSSlayer *
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 of the License, or *
8 * (at your option) 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 *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <memory.h>
23 #include <string.h>
24 #include <strings.h>
25 #include <ctype.h>
26 #include <limits.h>
27 #include <libintl.h>
28 #include <sys/socket.h>
29 #include <dbus/dbus.h>
30
31 #include "config.h"
32 #include "fcitx/ui.h"
33 #include "fcitx-utils/log.h"
34 #include "module/dbus/fcitx-dbus.h"
35 #include "fcitx/instance.h"
36 #include "fcitx/module.h"
37 #include "fcitx/frontend.h"
38 #include "fcitx/hook.h"
39 #include "fcitx-utils/utils.h"
40 #include "fcitx/candidate.h"
41
42 #define FCITX_KIMPANEL_INTERFACE "org.kde.kimpanel.inputmethod"
43 #define FCITX_KIMPANEL_PATH "/kimpanel"
44
45 #define GetMenuItem(m, i) ((FcitxMenuItem*) utarray_eltptr(&(m)->shell, (i)))
46
CheckAddPrefix(const char ** name)47 static inline boolean CheckAddPrefix( const char** name) {
48 boolean result = !((*name)[0] == '\0' || (*name)[0] == '/' || (*name)[0] == '@');
49 if ((*name)[0] == '@') {
50 (*name) += 1;
51 }
52
53 return result;
54 }
55
56 const char * kimpanel_introspection_xml =
57 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
58 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">"
59 "<node name=\"" FCITX_KIMPANEL_PATH "\">"
60 "<interface name=\"org.freedesktop.DBus.Introspectable\">"
61 "<method name=\"Introspect\">"
62 "<arg name=\"data\" direction=\"out\" type=\"s\"/>"
63 "</method>"
64 "</interface>"
65 "<interface name=\"" FCITX_KIMPANEL_INTERFACE "\">"
66 "<signal name=\"ExecDialog\">"
67 "<arg name=\"prop\" direction=\"in\" type=\"s\"/>"
68 "</signal>"
69 "<signal name=\"ExecMenu\">"
70 "<arg name=\"prop\" direction=\"in\" type=\"as\"/>"
71 "</signal>"
72 "<signal name=\"RegisterProperties\">"
73 "<arg name=\"prop\" direction=\"in\" type=\"as\"/>"
74 "</signal>"
75 "<signal name=\"UpdateProperty\">"
76 "<arg name=\"prop\" direction=\"in\" type=\"s\"/>"
77 "</signal>"
78 "<signal name=\"RemoveProperty\">"
79 "<arg name=\"prop\" direction=\"in\" type=\"s\"/>"
80 "</signal>"
81 "<signal name=\"ShowAux\">"
82 "<arg name=\"toshow\" direction=\"in\" type=\"b\"/>"
83 "</signal>"
84 "<signal name=\"ShowPreedit\">"
85 "<arg name=\"toshow\" direction=\"in\" type=\"b\"/>"
86 "</signal>"
87 "<signal name=\"ShowLookupTable\">"
88 "<arg name=\"toshow\" direction=\"in\" type=\"b\"/>"
89 "</signal>"
90 "<signal name=\"UpdateLookupTable\">"
91 "<arg name=\"label\" direction=\"in\" type=\"as\"/>"
92 "<arg name=\"text\" direction=\"in\" type=\"as\"/>"
93 "</signal>"
94 "<signal name=\"UpdateLookupTableCursor\">"
95 "<arg name=\"cursor\" direction=\"in\" type=\"i\"/>"
96 "</signal>"
97 "<signal name=\"UpdatePreeditCaret\">"
98 "<arg name=\"position\" direction=\"in\" type=\"i\"/>"
99 "</signal>"
100 "<signal name=\"UpdatePreeditText\">"
101 "<arg name=\"text\" direction=\"in\" type=\"s\"/>"
102 "<arg name=\"attr\" direction=\"in\" type=\"s\"/>"
103 "</signal>"
104 "<signal name=\"UpdateAux\">"
105 "<arg name=\"text\" direction=\"in\" type=\"s\"/>"
106 "<arg name=\"attr\" direction=\"in\" type=\"s\"/>"
107 "</signal>"
108 "<signal name=\"UpdateSpotLocation\">"
109 "<arg name=\"x\" direction=\"in\" type=\"i\"/>"
110 "<arg name=\"y\" direction=\"in\" type=\"i\"/>"
111 "</signal>"
112 "<signal name=\"UpdateScreen\">"
113 "<arg name=\"screen\" direction=\"in\" type=\"i\"/>"
114 "</signal>"
115 "<signal name=\"Enable\">"
116 "<arg name=\"toenable\" direction=\"in\" type=\"b\"/>"
117 "</signal>"
118 "</interface>"
119 "</node>";
120
121 typedef struct _FcitxKimpanelUI {
122 FcitxInstance* owner;
123 FcitxAddon* addon;
124 DBusConnection* conn;
125 int iOffsetY;
126 int iOffsetX;
127 FcitxMessages* messageUp;
128 FcitxMessages* messageDown;
129 int iCursorPos;
130 int lastUpdateY;
131 int lastUpdateX;
132 int version;
133 int lastUpdateW;
134 int lastUpdateH;
135 int lastCursor;
136 boolean hasSetLookupTable;
137 boolean hasSetRelativeSpotRect;
138 } FcitxKimpanelUI;
139
140 static void* KimpanelCreate(FcitxInstance* instance);
141 static void KimpanelCloseInputWindow(void* arg);
142 static void KimpanelShowInputWindow(void* arg);
143 static void KimpanelMoveInputWindow(void* arg);
144 static void KimpanelRegisterMenu(void *arg, FcitxUIMenu* menu);
145 static void KimpanelUpdateStatus(void *arg, FcitxUIStatus* status);
146 static void KimpanelRegisterStatus(void *arg, FcitxUIStatus* status);
147 static void KimpanelRegisterComplexStatus(void* arg, FcitxUIComplexStatus* status);
148 static void KimpanelUpdateComplexStatus(void* arg, FcitxUIComplexStatus* status);
149 static void KimpanelOnInputFocus(void *arg);
150 static void KimpanelOnInputUnFocus(void *arg);
151 static void KimpanelOnTriggerOn(void *arg);
152 static void KimpanelOnTriggerOff(void *arg);
153 static void KimpanelSuspend(void* arg);
154 static void KimpanelDestroy(void* arg);
155 static void KimpanelOwnerChanged(void* user_data, void* arg, const char* serviceName, const char* oldName, const char* newName);
156
157 static void KimUpdateLookupTableCursor(FcitxKimpanelUI* kimpanel, int cursor);
158 static void KimShowAux(FcitxKimpanelUI* kimpanel, boolean toShow);
159 static void KimShowPreedit(FcitxKimpanelUI* kimpanel, boolean toShow);
160 static void KimUpdateSpotLocation(FcitxKimpanelUI* kimpanel, int x, int y);
161 static void KimSetSpotRect(FcitxKimpanelUI* kimpanel, int x, int y, int w, int h, boolean relative);
162 static void KimShowLookupTable(FcitxKimpanelUI* kimpanel, boolean toShow);
163 static void KimUpdateLookupTable(FcitxKimpanelUI* kimpanel, char *labels[], int nLabel, char *texts[], int nText, boolean has_prev, boolean has_next);
164 static void KimSetLookupTable(FcitxKimpanelUI* kimpanel,
165 char *labels[], int nLabel,
166 char *texts[], int nText,
167 boolean has_prev,
168 boolean has_next,
169 int cursor,
170 int layout);
171 static void KimUpdatePreeditText(FcitxKimpanelUI* kimpanel, char *text);
172 static void KimUpdateAux(FcitxKimpanelUI* kimpanel, char *text);
173 static void KimUpdatePreeditCaret(FcitxKimpanelUI* kimpanel, int position);
174 static void KimEnable(FcitxKimpanelUI* kimpanel, boolean toEnable);
175 static void KimRegisterProperties(FcitxKimpanelUI* kimpanel, char *props[], int n);
176 static void KimUpdateProperty(FcitxKimpanelUI* kimpanel, char *prop);
177 static DBusHandlerResult KimpanelDBusEventHandler(DBusConnection *connection, DBusMessage *message, void *user_data);
178 static DBusHandlerResult KimpanelDBusFilter(DBusConnection *connection, DBusMessage *message, void *user_data);
179 static int CalKimCursorPos(FcitxKimpanelUI *kimpanel);
180 static void KimpanelInputIMChanged(void *arg);
181 static char* Status2String(FcitxInstance* instance, FcitxUIStatus* status);
182 static char* ComplexStatus2String(FcitxInstance* instance, FcitxUIComplexStatus* status);
183 static void KimpanelRegisterAllStatus(FcitxKimpanelUI* kimpanel);
184 static void KimpanelSetIMStatus(FcitxKimpanelUI* kimpanel);
185 static void KimExecMenu(FcitxKimpanelUI* kimpanel, char *props[], int n);
186 static void KimpanelServiceExistCallback(DBusPendingCall *call, void *data);
187 static void KimpanelIntrospect(FcitxKimpanelUI* kimpanel);
188 static void KimpanelIntrospectCallback(DBusPendingCall *call, void *data);
189
190 #define KIMPANEL_BUFFER_SIZE 4096
191 #ifndef DBUS_TIMEOUT_USE_DEFAULT
192 # define DBUS_TIMEOUT_USE_DEFAULT (-1)
193 #endif
194
195 FCITX_DEFINE_PLUGIN(fcitx_kimpanel_ui, ui, FcitxUI) = {
196 KimpanelCreate,
197 KimpanelCloseInputWindow,
198 KimpanelShowInputWindow,
199 KimpanelMoveInputWindow,
200 KimpanelUpdateStatus,
201 KimpanelRegisterStatus,
202 KimpanelRegisterMenu,
203 KimpanelOnInputFocus,
204 KimpanelOnInputUnFocus,
205 KimpanelOnTriggerOn,
206 KimpanelOnTriggerOff,
207 NULL,
208 NULL,
209 NULL,
210 KimpanelSuspend,
211 NULL,
212 KimpanelDestroy,
213 KimpanelRegisterComplexStatus,
214 KimpanelUpdateComplexStatus,
215 NULL
216 };
217
218 #define INDICATOR_KEYBOARD_PREFIX "@indicator-keyboard-"
219 #define INDICATOR_KEYBOARD_LENGTH (strlen(INDICATOR_KEYBOARD_PREFIX))
220
221 static inline boolean
isUnity()222 isUnity()
223 {
224 return fcitx_utils_strcmp0(getenv("XDG_CURRENT_DESKTOP"), "Unity") == 0;
225 }
226
SetIMMenu(FcitxIM * pim,char ** prop)227 static void SetIMMenu(FcitxIM *pim, char** prop)
228 {
229 char layout[] = INDICATOR_KEYBOARD_PREFIX "Xx";
230 const char *icon = "";
231 if (strncmp(pim->uniqueName, "fcitx-keyboard-",
232 strlen("fcitx-keyboard-")) != 0) {
233 icon = pim->strIconName;
234 } else if (isUnity()) {
235 layout[INDICATOR_KEYBOARD_LENGTH] = toupper(pim->langCode[0]);
236 layout[INDICATOR_KEYBOARD_LENGTH + 1] = tolower(pim->langCode[1]);
237 icon = layout;
238 }
239 boolean result = CheckAddPrefix(&icon);
240 fcitx_utils_alloc_cat_str(*prop, "/Fcitx/im/", pim->uniqueName, ":",
241 pim->strName,
242 result ? ":fcitx-" : ":", icon, ":", pim->strName);
243 }
244
SetIMIcon(FcitxInstance * instance,char ** prop)245 static void SetIMIcon(FcitxInstance* instance, char** prop)
246 {
247 char layout[] = INDICATOR_KEYBOARD_PREFIX "Xx";
248 const char* icon;
249 char* imname;
250 char* description;
251 char temp[LANGCODE_LENGTH + 1] = { '\0', };
252 FCITX_UNUSED(temp);
253 FcitxInputContext* ic = FcitxInstanceGetCurrentIC(instance);
254 if (ic == NULL) {
255 icon = "kbd";
256 imname = _("No input window");
257 description = _("No input window");
258 } else if (FcitxInstanceGetCurrentStatev2(instance) == IS_ACTIVE) {
259 FcitxIM* im = FcitxInstanceGetCurrentIM(instance);
260 if (im) {
261 if (strncmp(im->uniqueName, "fcitx-keyboard-",
262 strlen("fcitx-keyboard-")) == 0) {
263 if (isUnity()) {
264 layout[INDICATOR_KEYBOARD_LENGTH] =
265 toupper(im->langCode[0]);
266 layout[INDICATOR_KEYBOARD_LENGTH + 1] =
267 tolower(im->langCode[1]);
268 icon = layout;
269 } else {
270 icon = "";
271 }
272 imname = im->uniqueName + strlen("fcitx-keyboard-");
273 }
274 else
275 {
276 icon = im->strIconName;
277 imname = im->strName;
278 }
279 description = im->strName;
280 } else {
281 icon = "kbd";
282 imname = _("Disabled");
283 description = _("Input Method Disabled");
284 }
285 } else {
286 icon = "kbd";
287 imname = _("Disabled");
288 description = _("Input Method Disabled");
289 }
290 /* add fcitx- prefix, unless icon name is an absolute path */
291
292 char *icon_prefix;
293 boolean result = CheckAddPrefix(&icon);
294 if (result) {
295 icon_prefix = ":fcitx-";
296 } else {
297 icon_prefix = ":";
298 }
299 fcitx_utils_alloc_cat_str(*prop, "/Fcitx/im:", imname, icon_prefix, icon,
300 ":", description, ":menu");
301 }
302
KimpanelCreate(FcitxInstance * instance)303 void* KimpanelCreate(FcitxInstance* instance)
304 {
305 FcitxKimpanelUI *kimpanel = fcitx_utils_malloc0(sizeof(FcitxKimpanelUI));
306
307 kimpanel->addon = FcitxAddonsGetAddonByName(FcitxInstanceGetAddons(instance), "fcitx-kimpanel-ui");
308 kimpanel->lastCursor = -2;
309 kimpanel->version = 1;
310 kimpanel->iCursorPos = 0;
311 kimpanel->owner = instance;
312 kimpanel->conn = FcitxDBusGetConnection(instance);
313
314 DBusError err;
315 dbus_error_init(&err);
316 do {
317 if (kimpanel->conn == NULL) {
318 FcitxLog(ERROR, "DBus Not initialized");
319 break;
320 }
321
322 // add a rule to receive signals from kimpanel
323 dbus_bus_add_match(kimpanel->conn,
324 "type='signal',sender='org.kde.impanel',interface='org.kde.impanel'",
325 &err);
326 dbus_connection_flush(kimpanel->conn);
327 if (dbus_error_is_set(&err)) {
328 FcitxLog(ERROR, "Match Error (%s)", err.message);
329 break;
330 }
331 dbus_bus_add_match(kimpanel->conn,
332 "type='signal',sender='org.kde.impanel',interface='org.kde.impanel2'",
333 &err);
334 dbus_connection_flush(kimpanel->conn);
335 if (dbus_error_is_set(&err)) {
336 FcitxLog(ERROR, "Match Error (%s)", err.message);
337 break;
338 }
339
340 int id = FcitxDBusWatchName(instance, "org.kde.impanel", kimpanel,
341 KimpanelOwnerChanged, NULL, NULL);
342 if (id == 0) {
343 break;
344 }
345
346 if (!dbus_connection_add_filter(kimpanel->conn, KimpanelDBusFilter, kimpanel, NULL)) {
347 FcitxLog(ERROR, "No memory");
348 break;
349 }
350
351 DBusObjectPathVTable vtable = {NULL, &KimpanelDBusEventHandler, NULL, NULL, NULL, NULL };
352
353 dbus_connection_register_object_path(kimpanel->conn, FCITX_KIMPANEL_PATH, &vtable, kimpanel);
354
355 kimpanel->messageUp = FcitxMessagesNew();
356 kimpanel->messageDown = FcitxMessagesNew();
357
358 FcitxIMEventHook imchangehk;
359 imchangehk.arg = kimpanel;
360 imchangehk.func = KimpanelInputIMChanged;
361 FcitxInstanceRegisterIMChangedHook(instance, imchangehk);
362
363 const char* kimpanelServiceName = "org.kde.impanel";
364 DBusMessage* message = dbus_message_new_method_call(DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS, "NameHasOwner");
365 dbus_message_append_args(message, DBUS_TYPE_STRING, &kimpanelServiceName, DBUS_TYPE_INVALID);
366
367 DBusPendingCall *call = NULL;
368 dbus_bool_t reply =
369 dbus_connection_send_with_reply(kimpanel->conn, message,
370 &call, DBUS_TIMEOUT_USE_DEFAULT);
371 if (reply == TRUE) {
372 dbus_pending_call_set_notify(call,
373 KimpanelServiceExistCallback,
374 kimpanel,
375 NULL);
376 dbus_pending_call_unref(call);
377 }
378 dbus_connection_flush(kimpanel->conn);
379 dbus_message_unref(message);
380
381 KimpanelRegisterAllStatus(kimpanel);
382 dbus_error_free(&err);
383 return kimpanel;
384 } while (0);
385
386 dbus_error_free(&err);
387 free(kimpanel);
388 return NULL;
389 }
390
KimpanelRegisterAllStatus(FcitxKimpanelUI * kimpanel)391 void KimpanelRegisterAllStatus(FcitxKimpanelUI* kimpanel)
392 {
393 FcitxInstance* instance = kimpanel->owner;
394 UT_array* uistats = FcitxInstanceGetUIStats(instance);
395 UT_array* uicompstats = FcitxInstanceGetUIComplexStats(instance);
396 char **prop = fcitx_utils_malloc0(sizeof(char*) * (2 + utarray_len(uistats) + utarray_len(uicompstats)));
397
398 char *fcitx = _("Fcitx");
399 fcitx_utils_alloc_cat_str(prop[0], "/Fcitx/logo:", fcitx, ":fcitx:", fcitx, ":menu");
400 SetIMIcon(instance, &prop[1]);
401
402 int count = 2;
403
404 FcitxUIComplexStatus *compstatus;
405 for (compstatus = (FcitxUIComplexStatus *) utarray_front(uicompstats);
406 compstatus != NULL;
407 compstatus = (FcitxUIComplexStatus *) utarray_next(uicompstats, compstatus)) {
408 if (!compstatus->visible)
409 continue;
410 prop[count] = ComplexStatus2String(instance, compstatus);
411 count ++;
412 }
413
414 FcitxUIStatus *status;
415 for (status = (FcitxUIStatus *) utarray_front(uistats);
416 status != NULL;
417 status = (FcitxUIStatus *) utarray_next(uistats, status)) {
418 if (!status->visible)
419 continue;
420 prop[count] = Status2String(instance, status);
421 count ++;
422 }
423
424 KimRegisterProperties(kimpanel, prop, count);
425
426 while (count --)
427 free(prop[count]);
428
429 free(prop);
430 }
431
KimpanelSetIMStatus(FcitxKimpanelUI * kimpanel)432 void KimpanelSetIMStatus(FcitxKimpanelUI* kimpanel)
433 {
434 FcitxInstance* instance = kimpanel->owner;
435 char* status = NULL;
436
437 SetIMIcon(instance, &status);
438 KimUpdateProperty(kimpanel, status);
439 free(status);
440 }
441
KimpanelInputIMChanged(void * arg)442 void KimpanelInputIMChanged(void* arg)
443 {
444 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
445 if (kimpanel->addon != FcitxInstanceGetCurrentUI(kimpanel->owner))
446 return;
447 KimpanelSetIMStatus(kimpanel);
448 }
449
KimpanelOnInputFocus(void * arg)450 void KimpanelOnInputFocus(void* arg)
451 {
452 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
453 KimEnable(kimpanel, (FcitxInstanceGetCurrentStatev2(kimpanel->owner) == IS_ACTIVE));
454 KimpanelSetIMStatus(kimpanel);
455 }
456
KimpanelOnInputUnFocus(void * arg)457 void KimpanelOnInputUnFocus(void* arg)
458 {
459 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
460 KimEnable(kimpanel, (FcitxInstanceGetCurrentStatev2(kimpanel->owner) == IS_ACTIVE));
461 KimpanelSetIMStatus(kimpanel);
462 }
463
KimpanelOnTriggerOff(void * arg)464 void KimpanelOnTriggerOff(void* arg)
465 {
466 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
467 KimEnable(kimpanel, false);
468 KimpanelSetIMStatus(kimpanel);
469 }
470
KimpanelOnTriggerOn(void * arg)471 void KimpanelOnTriggerOn(void* arg)
472 {
473 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
474 KimEnable(kimpanel, true);
475 KimpanelSetIMStatus(kimpanel);
476 }
477
KimpanelCloseInputWindow(void * arg)478 void KimpanelCloseInputWindow(void* arg)
479 {
480 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
481 FcitxLog(DEBUG, "KimpanelCloseInputWindow");
482 /* why kimpanel sucks, there is not obvious method to close it */
483 KimShowAux(kimpanel, false);
484 KimShowPreedit(kimpanel, false);
485 KimShowLookupTable(kimpanel, false);
486 }
487
KimpanelMoveInputWindow(void * arg)488 void KimpanelMoveInputWindow(void* arg)
489 {
490 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
491 FcitxLog(DEBUG, "KimpanelMoveInputWindow");
492 kimpanel->iOffsetX = 12;
493 kimpanel->iOffsetY = 0;
494
495 int x = 0, y = 0, w = 0, h = 0;
496
497 FcitxInputContext* ic = FcitxInstanceGetCurrentIC(kimpanel->owner);
498 if (!ic) {
499 return;
500 }
501 FcitxInstanceGetWindowRect(kimpanel->owner, ic, &x, &y, &w, &h);
502
503 if (kimpanel->version == 1)
504 KimUpdateSpotLocation(kimpanel, x, y + h);
505 else
506 KimSetSpotRect(kimpanel, x, y, w, h, !!(ic->contextCaps & CAPACITY_RELATIVE_CURSOR_RECT));
507 }
508
KimpanelRegisterMenu(void * arg,FcitxUIMenu * menu)509 void KimpanelRegisterMenu(void* arg, FcitxUIMenu* menu)
510 {
511 FCITX_UNUSED(arg);
512 FCITX_UNUSED(menu);
513 return;
514 }
515
KimpanelRegisterStatus(void * arg,FcitxUIStatus * status)516 void KimpanelRegisterStatus(void* arg, FcitxUIStatus* status)
517 {
518 FCITX_UNUSED(status);
519 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
520 KimpanelRegisterAllStatus(kimpanel);
521 return ;
522 }
523
KimpanelRegisterComplexStatus(void * arg,FcitxUIComplexStatus * status)524 void KimpanelRegisterComplexStatus(void* arg, FcitxUIComplexStatus* status)
525 {
526 FCITX_UNUSED(status);
527 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*)arg;
528 KimpanelRegisterAllStatus(kimpanel);
529 return ;
530 }
531
Status2String(FcitxInstance * instance,FcitxUIStatus * status)532 char* Status2String(FcitxInstance* instance, FcitxUIStatus* status)
533 {
534 char *result;
535 FcitxUIMenu *menu = FcitxUIGetMenuByStatusName(instance, status->name);
536 fcitx_utils_alloc_cat_str(result, "/Fcitx/", status->name, ":",
537 status->shortDescription, ":fcitx-", status->name,
538 ((status->getCurrentStatus(status->arg)) ?
539 "-active:" : "-inactive:"),
540 status->longDescription,
541 menu ? ":menu" : ":");
542 return result;
543 }
544
545
ComplexStatus2String(FcitxInstance * instance,FcitxUIComplexStatus * status)546 char* ComplexStatus2String(FcitxInstance* instance, FcitxUIComplexStatus* status)
547 {
548 const char* icon = status->getIconName(status->arg);
549 char *str;
550 boolean result = CheckAddPrefix(&icon);
551 FcitxUIMenu *menu = FcitxUIGetMenuByStatusName(instance, status->name);
552 fcitx_utils_alloc_cat_str(str, "/Fcitx/", status->name, ":",
553 status->shortDescription,
554 (result ? ":fcitx-" : ":"),
555 icon, ":",
556 status->longDescription,
557 menu ? ":menu" : ":"
558 );
559 return str;
560 }
561
KimpanelShowInputWindow(void * arg)562 void KimpanelShowInputWindow(void* arg)
563 {
564 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
565 FcitxInstance* instance = kimpanel->owner;
566 FcitxInputState* input = FcitxInstanceGetInputState(instance);
567 FcitxCandidateWordList* candList = FcitxInputStateGetCandidateList(input);
568 kimpanel->iCursorPos = FcitxUINewMessageToOldStyleMessage(instance, kimpanel->messageUp, kimpanel->messageDown);
569 FcitxMessages* messageDown = kimpanel->messageDown;
570 FcitxMessages* messageUp = kimpanel->messageUp;
571 FcitxLog(DEBUG, "KimpanelShowInputWindow");
572 KimpanelMoveInputWindow(kimpanel);
573
574 boolean hasPrev = FcitxCandidateWordHasPrev(candList);
575 boolean hasNext = FcitxCandidateWordHasNext(candList);
576 FcitxCandidateLayoutHint layout = FcitxCandidateWordGetLayoutHint(candList);
577
578 int n = FcitxMessagesGetMessageCount(messageDown);
579 int nLabels = 0;
580 int nTexts = 0;
581 char *label[33];
582 char *text[33];
583 char cmb[KIMPANEL_BUFFER_SIZE] = "";
584 int i;
585 int pos = -1;
586
587 if (n) {
588 for (i = 0; i < n; i++) {
589 FcitxLog(DEBUG, "Type: %d Text: %s" , FcitxMessagesGetMessageType(messageDown, i), FcitxMessagesGetMessageString(messageDown, i));
590
591 if (FcitxMessagesGetMessageType(messageDown, i) == MSG_INDEX) {
592 if (nLabels) {
593 text[nTexts++] = strdup(cmb);
594 }
595 char *needfree = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(messageDown, i));
596 char *msgstr;
597 if (needfree)
598 msgstr = needfree;
599 else
600 msgstr = strdup(FcitxMessagesGetMessageString(messageDown, i));
601
602 label[nLabels++] = msgstr;
603 strcpy(cmb, "");
604 } else {
605 char *needfree = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(messageDown, i));
606 char *msgstr;
607 if (needfree)
608 msgstr = needfree;
609 else
610 msgstr = FcitxMessagesGetMessageString(messageDown, i);
611
612 if (strlen(cmb) + strlen(msgstr) + 1 < KIMPANEL_BUFFER_SIZE)
613 strcat(cmb, msgstr);
614 if (needfree)
615 free(needfree);
616 if (FcitxMessagesGetMessageType(messageDown, i) == MSG_FIRSTCAND)
617 pos = nTexts;
618 }
619 }
620 text[nTexts++] = strdup(cmb);
621 if (nLabels < nTexts) {
622 for (; nLabels < nTexts; nLabels++) {
623 label[nLabels] = strdup("");
624 }
625 } else if (nTexts < nLabels) {
626 for (; nTexts < nLabels; nTexts++) {
627 text[nTexts] = strdup("");
628 }
629 }
630 FcitxLog(DEBUG, "Labels %d, Texts %d, CMB:%s", nLabels, nTexts, cmb);
631 if (nTexts == 0) {
632 KimShowLookupTable(kimpanel, false);
633 } else {
634 if (kimpanel->hasSetLookupTable)
635 KimSetLookupTable(kimpanel, label, nLabels, text, nTexts, hasPrev, hasNext, pos, layout);
636 else
637 KimUpdateLookupTable(kimpanel, label, nLabels, text, nTexts, hasPrev, hasNext);
638 KimShowLookupTable(kimpanel, true);
639 }
640 for (i = 0; i < nTexts; i++)
641 free(text[i]);
642 for (i = 0; i < nLabels; i++)
643 free(label[i]);
644 } else {
645 if (kimpanel->hasSetLookupTable)
646 KimSetLookupTable(kimpanel, NULL, 0, NULL, 0, hasNext, hasNext, pos, layout);
647 else
648 KimUpdateLookupTable(kimpanel, NULL, 0, NULL, 0, hasPrev, hasNext);
649 KimShowLookupTable(kimpanel, false);
650 }
651
652 if (!kimpanel->hasSetLookupTable)
653 KimUpdateLookupTableCursor(kimpanel, pos);
654
655 n = FcitxMessagesGetMessageCount(messageUp);
656 char aux[MESSAGE_MAX_LENGTH] = "";
657 char empty[MESSAGE_MAX_LENGTH] = "";
658 if (n) {
659 for (i = 0; i < n; i++) {
660
661 char *needfree = FcitxInstanceProcessOutputFilter(instance, FcitxMessagesGetMessageString(messageUp, i));
662 char *msgstr;
663 if (needfree)
664 msgstr = needfree;
665 else
666 msgstr = FcitxMessagesGetMessageString(messageUp, i);
667
668 strcat(aux, msgstr);
669 if (needfree)
670 free(needfree);
671 FcitxLog(DEBUG, "updateMesssages Up:%s", aux);
672 }
673 if (FcitxInputStateGetShowCursor(input)) {
674 KimUpdatePreeditText(kimpanel, aux);
675 KimUpdateAux(kimpanel, empty);
676 KimShowPreedit(kimpanel, true);
677 KimUpdatePreeditCaret(kimpanel, CalKimCursorPos(kimpanel));
678 KimShowAux(kimpanel, false);
679 } else {
680 KimUpdatePreeditText(kimpanel, empty);
681 KimUpdateAux(kimpanel, aux);
682 KimShowPreedit(kimpanel, false);
683 KimShowAux(kimpanel, true);
684 }
685 } else {
686 KimShowPreedit(kimpanel, false);
687 KimShowAux(kimpanel, false);
688 }
689
690 }
691
KimpanelUpdateStatus(void * arg,FcitxUIStatus * status)692 void KimpanelUpdateStatus(void* arg, FcitxUIStatus* status)
693 {
694 FCITX_UNUSED(status);
695 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
696 KimpanelRegisterAllStatus(kimpanel);
697 return ;
698 }
699
KimpanelUpdateComplexStatus(void * arg,FcitxUIComplexStatus * status)700 void KimpanelUpdateComplexStatus(void* arg, FcitxUIComplexStatus* status)
701 {
702 FCITX_UNUSED(status);
703 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
704 KimpanelRegisterAllStatus(kimpanel);
705 return ;
706 }
707
708 static DBusHandlerResult
KimpanelDBusEventHandler(DBusConnection * connection,DBusMessage * msg,void * arg)709 KimpanelDBusEventHandler(DBusConnection *connection,
710 DBusMessage *msg, void *arg)
711 {
712 FCITX_UNUSED(connection);
713 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*)arg;
714
715 if (dbus_message_is_method_call(msg, DBUS_INTERFACE_INTROSPECTABLE, "Introspect")) {
716 DBusMessage *reply = dbus_message_new_method_return(msg);
717
718 dbus_message_append_args(reply, DBUS_TYPE_STRING, &kimpanel_introspection_xml, DBUS_TYPE_INVALID);
719 dbus_connection_send(kimpanel->conn, reply, NULL);
720 dbus_message_unref(reply);
721 return DBUS_HANDLER_RESULT_HANDLED;
722 }
723 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
724 }
725
KimpanelReset(FcitxKimpanelUI * kimpanel)726 void KimpanelReset(FcitxKimpanelUI* kimpanel)
727 {
728 kimpanel->lastCursor = -2;
729 kimpanel->lastUpdateH = -2;
730 kimpanel->lastUpdateW = -2;
731 kimpanel->lastUpdateX = -2;
732 kimpanel->lastUpdateY = -2;
733 }
734
KimpanelDBusFilter(DBusConnection * connection,DBusMessage * msg,void * user_data)735 DBusHandlerResult KimpanelDBusFilter(DBusConnection* connection, DBusMessage* msg, void* user_data)
736 {
737 FCITX_UNUSED(connection);
738 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) user_data;
739 FcitxInstance* instance = kimpanel->owner;
740 FcitxInputState* input = FcitxInstanceGetInputState(kimpanel->owner);
741 int int0;
742 const char* s0 = NULL;
743 if (dbus_message_is_signal(msg, "org.kde.impanel", "MovePreeditCaret")) {
744 FcitxLog(DEBUG, "MovePreeditCaret");
745 DBusError error;
746 dbus_error_init(&error);
747 dbus_message_get_args(msg, &error, DBUS_TYPE_INT32, &int0 , DBUS_TYPE_INVALID);
748 dbus_error_free(&error);
749 return DBUS_HANDLER_RESULT_HANDLED;
750 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "SelectCandidate")) {
751 FcitxLog(DEBUG, "SelectCandidate: ");
752 DBusError error;
753 dbus_error_init(&error);
754 if (dbus_message_get_args(msg, &error, DBUS_TYPE_INT32, &int0 , DBUS_TYPE_INVALID)) {
755 FcitxInstanceChooseCandidateByIndex(instance, int0);
756 }
757 dbus_error_free(&error);
758 return DBUS_HANDLER_RESULT_HANDLED;
759 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "LookupTablePageUp")) {
760 FcitxLog(DEBUG, "LookupTablePageUp");
761 if (FcitxCandidateWordPageCount(FcitxInputStateGetCandidateList(input)) != 0) {
762 FcitxCandidateWordGoPrevPage(FcitxInputStateGetCandidateList(input));
763 FcitxInstanceProcessInputReturnValue(instance, IRV_DISPLAY_CANDWORDS);
764 }
765 return DBUS_HANDLER_RESULT_HANDLED;
766 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "LookupTablePageDown")) {
767 FcitxLog(DEBUG, "LookupTablePageDown");
768 if (FcitxCandidateWordPageCount(FcitxInputStateGetCandidateList(input)) != 0) {
769 FcitxCandidateWordGoNextPage(FcitxInputStateGetCandidateList(input));
770 FcitxInstanceProcessInputReturnValue(instance, IRV_DISPLAY_CANDWORDS);
771 }
772 return DBUS_HANDLER_RESULT_HANDLED;
773 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "TriggerProperty")) {
774 FcitxLog(DEBUG, "TriggerProperty: ");
775 DBusError error;
776 dbus_error_init(&error);
777 if (dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &s0 , DBUS_TYPE_INVALID)) {
778 if (strlen(s0) > strlen("/Fcitx/")) {
779 s0 += strlen("/Fcitx/");
780 if (strcmp("logo", s0) == 0) {
781 char *prop[3];
782 char *trans_str = _("Toggle Input Method");
783 fcitx_utils_alloc_cat_str(prop[0], "/Fcitx/logo/toggle:",
784 trans_str, "::", trans_str);
785 trans_str = _("Configure Current Input Method");
786 fcitx_utils_alloc_cat_str(prop[1],
787 "/Fcitx/logo/configureim:",
788 trans_str, ":configure:",
789 trans_str);
790 trans_str = _("Restart");
791 fcitx_utils_alloc_cat_str(prop[2], "/Fcitx/logo/restart:",
792 trans_str, ":view-refresh:",
793 trans_str);
794 KimExecMenu(kimpanel, prop, 3);
795 int i;
796 for (i = 0;i < 3;i++) {
797 free(prop[i]);
798 }
799 } else if (strncmp("logo/", s0, strlen("logo/")) == 0) {
800 s0 += strlen("logo/");
801 if (strcmp(s0, "toggle") == 0)
802 FcitxInstanceChangeIMState(instance, FcitxInstanceGetCurrentIC(instance));
803 else if (strcmp(s0, "configureim") == 0) {
804 FcitxIM* im = FcitxInstanceGetCurrentIM(kimpanel->owner);
805 if (im && im->owner) {
806 fcitx_utils_launch_configure_tool_for_addon(im->uniqueName);
807 }
808 else
809 fcitx_utils_launch_configure_tool();
810 }
811 else if (strcmp(s0, "restart") == 0) {
812 FcitxInstanceRestart(instance);
813 }
814 } else if (strcmp("keyboard", s0) == 0) {
815 FcitxInstanceCloseIM(instance,
816 FcitxInstanceGetCurrentIC(instance));
817 } else if (strncmp("im/", s0, strlen("im/")) == 0) {
818 s0 += strlen("im/");
819 FcitxInstanceSwitchIMByName(instance, s0);
820 } else if (strncmp("im", s0, strlen("im")) == 0) {
821 UT_array* imes = FcitxInstanceGetIMEs(instance);
822 FcitxIM* pim;
823 int index = 0;
824 size_t len = utarray_len(imes);
825 char **prop = fcitx_utils_malloc0(len * sizeof(char*));
826 for (pim = (FcitxIM *) utarray_front(imes);
827 pim != NULL;
828 pim = (FcitxIM *) utarray_next(imes, pim)) {
829
830 SetIMMenu(pim, &prop[index]);
831 index ++;
832 }
833 KimExecMenu(kimpanel, prop, len);
834 while (len --)
835 free(prop[len]);
836 free(prop);
837 } else {
838 /* menu */
839 const char* pos;
840 if ((pos = strchr(s0, '/'))) {
841 char* statusName = strndup(s0, pos - s0);
842 FcitxUIMenu* menup = FcitxUIGetMenuByStatusName(instance, statusName);
843 free(statusName);
844 pos ++;
845 int index = 0;
846 sscanf(pos, "%d", &index);
847 if (menup)
848 menup->MenuAction(menup, index);
849 } else {
850 FcitxUIMenu *menu = FcitxUIGetMenuByStatusName(instance, s0);
851 if (menu) {
852 menu->UpdateMenu(menu);
853
854 unsigned int i = 0, index = 0;
855 unsigned int len = utarray_len(&menu->shell);
856 char *prop[len];
857 for (i = 0; i < len; i++) {
858 FcitxMenuItem *menu_item = GetMenuItem(menu, i);
859 if (menu_item->type == MENUTYPE_SIMPLE) {
860 asprintf(&prop[index],
861 "/Fcitx/%s/%d:%s::%s", s0, index,
862 menu_item->tipstr,
863 menu_item->tipstr);
864 index++;
865 }
866 }
867 KimExecMenu(kimpanel, prop, index);
868 while (index--)
869 free(prop[index]);
870 } else {
871 FcitxUIUpdateStatus(instance, s0);
872 }
873 }
874 }
875 }
876 }
877 dbus_error_free(&error);
878 return DBUS_HANDLER_RESULT_HANDLED;
879 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "PanelCreated")) {
880 FcitxLog(DEBUG, "PanelCreated");
881 FcitxUIResumeFromFallback(instance);
882 KimpanelReset(kimpanel);
883 KimpanelRegisterAllStatus(kimpanel);
884 return DBUS_HANDLER_RESULT_HANDLED;
885 } else if (dbus_message_is_signal(msg, "org.kde.impanel2", "PanelCreated2")) {
886 FcitxLog(DEBUG, "PanelCreated2");
887 FcitxUIResumeFromFallback(instance);
888 kimpanel->version = 2;
889 KimpanelReset(kimpanel);
890 KimpanelRegisterAllStatus(kimpanel);
891 KimpanelIntrospect(kimpanel);
892 return DBUS_HANDLER_RESULT_HANDLED;
893 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "Exit")) {
894 FcitxLog(DEBUG, "Exit");
895 FcitxInstanceEnd(instance);
896 return DBUS_HANDLER_RESULT_HANDLED;
897 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "ReloadConfig")) {
898 FcitxLog(DEBUG, "ReloadConfig");
899 FcitxInstanceReloadConfig(instance);
900 return DBUS_HANDLER_RESULT_HANDLED;
901 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "Restart")) {
902 FcitxLog(DEBUG, "Restart");
903 FcitxInstanceRestart(instance);
904 return DBUS_HANDLER_RESULT_HANDLED;
905 } else if (dbus_message_is_signal(msg, "org.kde.impanel", "Configure")) {
906 FcitxLog(DEBUG, "Configure");
907 fcitx_utils_launch_configure_tool();
908 return DBUS_HANDLER_RESULT_HANDLED;
909 }
910
911 return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
912 }
913
KimpanelOwnerChanged(void * user_data,void * arg,const char * serviceName,const char * oldName,const char * newName)914 void KimpanelOwnerChanged(void* user_data, void* arg, const char* serviceName, const char* oldName, const char* newName) {
915 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) user_data;
916 /* old die and no new one */
917 if (strcmp(serviceName, "org.kde.impanel") == 0) {
918 if (strlen(oldName) > 0 && strlen(newName) == 0) {
919 FcitxUISwitchToFallback(kimpanel->owner);
920 }
921 }
922 }
923
KimExecDialog(FcitxKimpanelUI * kimpanel,char * prop)924 void KimExecDialog(FcitxKimpanelUI* kimpanel, char *prop)
925 {
926 dbus_uint32_t serial = 0; // unique number to associate replies with requests
927 DBusMessage* msg;
928
929 // create a signal and check for errors
930 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
931 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
932 "ExecDialog"); // name of the signal
933 if (NULL == msg) {
934 FcitxLog(DEBUG, "Message Null");
935 return;
936 }
937
938 if (dbus_message_append_args(msg, DBUS_TYPE_STRING, &prop, DBUS_TYPE_INVALID)) {
939 dbus_connection_send(kimpanel->conn, msg, &serial);
940 }
941
942 dbus_connection_flush(kimpanel->conn);
943
944 // free the message
945 dbus_message_unref(msg);
946
947 }
948
KimExecMenu(FcitxKimpanelUI * kimpanel,char * props[],int n)949 void KimExecMenu(FcitxKimpanelUI* kimpanel, char *props[], int n)
950 {
951
952 dbus_uint32_t serial = 0; // unique number to associate replies with requests
953 DBusMessage* msg;
954 DBusMessageIter args;
955 int i;
956
957 // create a signal and check for errors
958 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
959 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
960 "ExecMenu"); // name of the signal
961 if (NULL == msg) {
962 FcitxLog(DEBUG, "Message Null");
963 return;
964 }
965
966 for (i = 0; i < n; i++) {
967 if (!fcitx_utf8_check_string(props[i]))
968 return;
969 }
970
971 // append arguments onto signal
972 dbus_message_iter_init_append(msg, &args);
973 DBusMessageIter sub;
974 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &sub);
975 for (i = 0; i < n; i++) {
976 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &props[i])) {
977 FcitxLog(DEBUG, "Out Of Memory!");
978 }
979 }
980 dbus_message_iter_close_container(&args, &sub);
981
982 // send the message and flush the connection
983 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
984 FcitxLog(DEBUG, "Out Of Memory!");
985 }
986 dbus_connection_flush(kimpanel->conn);
987
988 // free the message
989 dbus_message_unref(msg);
990
991 }
992
KimRegisterProperties(FcitxKimpanelUI * kimpanel,char * props[],int n)993 void KimRegisterProperties(FcitxKimpanelUI* kimpanel, char *props[], int n)
994 {
995 dbus_uint32_t serial = 0; // unique number to associate replies with requests
996 DBusMessage* msg;
997 DBusMessageIter args;
998 int i;
999
1000 // create a signal and check for errors
1001 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1002 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1003 "RegisterProperties"); // name of the signal
1004 if (NULL == msg) {
1005 FcitxLog(DEBUG, "Message Null");
1006 return;
1007 }
1008
1009 for (i = 0; i < n; i++) {
1010 if (!fcitx_utf8_check_string(props[i]))
1011 return;
1012 }
1013
1014 // append arguments onto signal
1015 dbus_message_iter_init_append(msg, &args);
1016 DBusMessageIter sub;
1017 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &sub);
1018 for (i = 0; i < n; i++) {
1019 if (!dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &props[i])) {
1020 FcitxLog(DEBUG, "Out Of Memory!");
1021 }
1022 }
1023 dbus_message_iter_close_container(&args, &sub);
1024
1025 // send the message and flush the connection
1026 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1027 FcitxLog(DEBUG, "Out Of Memory!");
1028 }
1029
1030 // free the message
1031 dbus_message_unref(msg);
1032
1033 }
1034
KimUpdateProperty(FcitxKimpanelUI * kimpanel,char * prop)1035 void KimUpdateProperty(FcitxKimpanelUI* kimpanel, char *prop)
1036 {
1037
1038 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1039 DBusMessage* msg;
1040 DBusMessageIter args;
1041
1042 // create a signal and check for errors
1043 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1044 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1045 "UpdateProperty"); // name of the signal
1046 if (NULL == msg) {
1047 FcitxLog(DEBUG, "Message Null");
1048 return;
1049 }
1050
1051 if (!fcitx_utf8_check_string(prop))
1052 return;
1053
1054 // append arguments onto signal
1055 dbus_message_iter_init_append(msg, &args);
1056 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &prop)) {
1057 FcitxLog(DEBUG, "Out Of Memory!");
1058 }
1059
1060 // send the message and flush the connection
1061 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1062 FcitxLog(DEBUG, "Out Of Memory!");
1063 }
1064
1065 // free the message
1066 dbus_message_unref(msg);
1067
1068 }
1069
KimRemoveProperty(FcitxKimpanelUI * kimpanel,char * prop)1070 void KimRemoveProperty(FcitxKimpanelUI* kimpanel, char *prop)
1071 {
1072
1073 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1074 DBusMessage* msg;
1075 DBusMessageIter args;
1076
1077 // create a signal and check for errors
1078 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1079 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1080 "RemoveProperty"); // name of the signal
1081 if (NULL == msg) {
1082 FcitxLog(DEBUG, "Message Null");
1083 return;
1084 }
1085
1086 if (!fcitx_utf8_check_string(prop))
1087 return;
1088
1089 // append arguments onto signal
1090 dbus_message_iter_init_append(msg, &args);
1091 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &prop)) {
1092 FcitxLog(DEBUG, "Out Of Memory!");
1093 }
1094
1095 // send the message and flush the connection
1096 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1097 FcitxLog(DEBUG, "Out Of Memory!");
1098 }
1099
1100 // free the message
1101 dbus_message_unref(msg);
1102
1103 }
1104
KimEnable(FcitxKimpanelUI * kimpanel,boolean toEnable)1105 void KimEnable(FcitxKimpanelUI* kimpanel, boolean toEnable)
1106 {
1107 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1108 DBusMessage* msg;
1109 DBusMessageIter args;
1110
1111 // create a signal and check for errors
1112 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1113 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1114 "Enable"); // name of the signal
1115 if (NULL == msg) {
1116 FcitxLog(DEBUG, "Message Null");
1117 return;
1118 }
1119
1120 // append arguments onto signal
1121 dbus_message_iter_init_append(msg, &args);
1122 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &toEnable)) {
1123 FcitxLog(DEBUG, "Out Of Memory!");
1124 }
1125
1126 // send the message and flush the connection
1127 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1128 FcitxLog(DEBUG, "Out Of Memory!");
1129 }
1130
1131 // free the message
1132 dbus_message_unref(msg);
1133
1134 }
1135
KimShowAux(FcitxKimpanelUI * kimpanel,boolean toShow)1136 void KimShowAux(FcitxKimpanelUI* kimpanel, boolean toShow)
1137 {
1138
1139 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1140 DBusMessage* msg;
1141 DBusMessageIter args;
1142
1143 // create a signal and check for errors
1144 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1145 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1146 "ShowAux"); // name of the signal
1147 if (NULL == msg) {
1148 FcitxLog(DEBUG, "Message Null");
1149 return;
1150 }
1151
1152 // append arguments onto signal
1153 dbus_message_iter_init_append(msg, &args);
1154 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &toShow)) {
1155 FcitxLog(DEBUG, "Out Of Memory!");
1156 }
1157
1158 // send the message and flush the connection
1159 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1160 FcitxLog(DEBUG, "Out Of Memory!");
1161 }
1162
1163 // free the message
1164 dbus_message_unref(msg);
1165
1166 }
1167
KimShowPreedit(FcitxKimpanelUI * kimpanel,boolean toShow)1168 void KimShowPreedit(FcitxKimpanelUI* kimpanel, boolean toShow)
1169 {
1170
1171 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1172 DBusMessage* msg;
1173 DBusMessageIter args;
1174
1175 // create a signal and check for errors
1176 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1177 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1178 "ShowPreedit"); // name of the signal
1179 if (NULL == msg) {
1180 FcitxLog(DEBUG, "Message Null");
1181 return;
1182 }
1183
1184 // append arguments onto signal
1185 dbus_message_iter_init_append(msg, &args);
1186 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &toShow)) {
1187 FcitxLog(DEBUG, "Out Of Memory!");
1188 }
1189
1190 // send the message and flush the connection
1191 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1192 FcitxLog(DEBUG, "Out Of Memory!");
1193 }
1194
1195 // free the message
1196 dbus_message_unref(msg);
1197
1198 }
1199
KimUpdateLookupTableCursor(FcitxKimpanelUI * kimpanel,int cursor)1200 void KimUpdateLookupTableCursor(FcitxKimpanelUI* kimpanel, int cursor)
1201 {
1202 if (kimpanel->lastCursor != cursor)
1203 kimpanel->lastCursor = cursor;
1204 else
1205 return;
1206 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1207 DBusMessage* msg;
1208 DBusMessageIter args;
1209
1210 // create a signal and check for errors
1211 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1212 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1213 "UpdateLookupTableCursor"); // name of the signal
1214 if (NULL == msg) {
1215 FcitxLog(DEBUG, "Message Null");
1216 return;
1217 }
1218
1219 // append arguments onto signal
1220 dbus_message_iter_init_append(msg, &args);
1221 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &cursor)) {
1222 FcitxLog(DEBUG, "Out Of Memory!");
1223 }
1224
1225 // send the message and flush the connection
1226 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1227 FcitxLog(DEBUG, "Out Of Memory!");
1228 }
1229
1230 // free the message
1231 dbus_message_unref(msg);
1232 }
1233
KimShowLookupTable(FcitxKimpanelUI * kimpanel,boolean toShow)1234 void KimShowLookupTable(FcitxKimpanelUI* kimpanel, boolean toShow)
1235 {
1236
1237 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1238 DBusMessage* msg;
1239 DBusMessageIter args;
1240
1241 // create a signal and check for errors
1242 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1243 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1244 "ShowLookupTable"); // name of the signal
1245 if (NULL == msg) {
1246 FcitxLog(DEBUG, "Message Null");
1247 return;
1248 }
1249
1250 // append arguments onto signal
1251 dbus_message_iter_init_append(msg, &args);
1252 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &toShow)) {
1253 FcitxLog(DEBUG, "Out Of Memory!");
1254 }
1255
1256 // send the message and flush the connection
1257 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1258 FcitxLog(DEBUG, "Out Of Memory!");
1259 }
1260
1261 // free the message
1262 dbus_message_unref(msg);
1263
1264 }
1265
KimUpdateLookupTable(FcitxKimpanelUI * kimpanel,char * labels[],int nLabel,char * texts[],int nText,boolean has_prev,boolean has_next)1266 void KimUpdateLookupTable(FcitxKimpanelUI* kimpanel, char *labels[], int nLabel, char *texts[], int nText, boolean has_prev, boolean has_next)
1267 {
1268 int i;
1269 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1270 DBusMessage* msg;
1271 DBusMessageIter args;
1272
1273 // create a signal and check for errors
1274 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1275 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1276 "UpdateLookupTable"); // name of the signal
1277 if (NULL == msg) {
1278 FcitxLog(DEBUG, "Message Null");
1279 return;
1280 }
1281 for (i = 0; i < nLabel; i++) {
1282 if (!fcitx_utf8_check_string(labels[i]))
1283 return;
1284 }
1285 for (i = 0; i < nText; i++) {
1286 if (!fcitx_utf8_check_string(texts[i]))
1287 return;
1288 }
1289 DBusMessageIter subLabel;
1290 DBusMessageIter subText;
1291 DBusMessageIter subAttrs;
1292 // append arguments onto signal
1293 dbus_message_iter_init_append(msg, &args);
1294 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &subLabel);
1295 for (i = 0; i < nLabel; i++) {
1296 if (!dbus_message_iter_append_basic(&subLabel, DBUS_TYPE_STRING,
1297 &labels[i])) {
1298 FcitxLog(DEBUG, "Out Of Memory!");
1299 }
1300 }
1301 dbus_message_iter_close_container(&args, &subLabel);
1302
1303 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &subText);
1304 for (i = 0; i < nText; i++) {
1305 if (!dbus_message_iter_append_basic(&subText, DBUS_TYPE_STRING,
1306 &texts[i])) {
1307 FcitxLog(DEBUG, "Out Of Memory!");
1308 }
1309 }
1310 dbus_message_iter_close_container(&args, &subText);
1311
1312 char *attr = "";
1313 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &subAttrs);
1314 for (i = 0; i < nLabel; i++) {
1315 if (!dbus_message_iter_append_basic(&subAttrs, DBUS_TYPE_STRING, &attr)) {
1316 FcitxLog(DEBUG, "Out Of Memory!");
1317 }
1318 }
1319 dbus_message_iter_close_container(&args, &subAttrs);
1320
1321 dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &has_prev);
1322 dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &has_next);
1323
1324 // send the message and flush the connection
1325 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1326 FcitxLog(DEBUG, "Out Of Memory!");
1327 }
1328
1329 // free the message
1330 dbus_message_unref(msg);
1331
1332 }
1333
KimSetLookupTable(FcitxKimpanelUI * kimpanel,char * labels[],int nLabel,char * texts[],int nText,boolean has_prev,boolean has_next,int cursor,int layout)1334 void KimSetLookupTable(FcitxKimpanelUI* kimpanel,
1335 char *labels[], int nLabel,
1336 char *texts[], int nText,
1337 boolean has_prev,
1338 boolean has_next,
1339 int cursor,
1340 int layout
1341 )
1342 {
1343 int i;
1344 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1345 DBusMessage* msg;
1346 DBusMessageIter args;
1347
1348 // create a signal and check for errors
1349 msg = dbus_message_new_method_call("org.kde.impanel",
1350 "/org/kde/impanel",
1351 "org.kde.impanel2",
1352 "SetLookupTable"); // name of the signal
1353 if (NULL == msg) {
1354 FcitxLog(DEBUG, "Message Null");
1355 return;
1356 }
1357 for (i = 0; i < nLabel; i++) {
1358 if (!fcitx_utf8_check_string(labels[i]))
1359 return;
1360 }
1361 for (i = 0; i < nText; i++) {
1362 if (!fcitx_utf8_check_string(texts[i]))
1363 return;
1364 }
1365 DBusMessageIter subLabel;
1366 DBusMessageIter subText;
1367 DBusMessageIter subAttrs;
1368 // append arguments onto signal
1369 dbus_message_iter_init_append(msg, &args);
1370 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &subLabel);
1371 for (i = 0; i < nLabel; i++) {
1372 if (!dbus_message_iter_append_basic(&subLabel, DBUS_TYPE_STRING, &labels[i])) {
1373 FcitxLog(DEBUG, "Out Of Memory!");
1374 }
1375 }
1376 dbus_message_iter_close_container(&args, &subLabel);
1377
1378 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &subText);
1379 for (i = 0; i < nText; i++) {
1380 if (!dbus_message_iter_append_basic(&subText, DBUS_TYPE_STRING, &texts[i])) {
1381 FcitxLog(DEBUG, "Out Of Memory!");
1382 }
1383 }
1384 dbus_message_iter_close_container(&args, &subText);
1385
1386 char *attr = "";
1387 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, "s", &subAttrs);
1388 for (i = 0; i < nLabel; i++) {
1389 if (!dbus_message_iter_append_basic(&subAttrs, DBUS_TYPE_STRING, &attr)) {
1390 FcitxLog(DEBUG, "Out Of Memory!");
1391 }
1392 }
1393 dbus_message_iter_close_container(&args, &subAttrs);
1394
1395 dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &has_prev);
1396 dbus_message_iter_append_basic(&args, DBUS_TYPE_BOOLEAN, &has_next);
1397 dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &cursor);
1398 dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &layout);
1399
1400 // send the message and flush the connection
1401 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1402 FcitxLog(DEBUG, "Out Of Memory!");
1403 }
1404
1405 // free the message
1406 dbus_message_unref(msg);
1407
1408 }
1409
KimUpdatePreeditCaret(FcitxKimpanelUI * kimpanel,int position)1410 void KimUpdatePreeditCaret(FcitxKimpanelUI* kimpanel, int position)
1411 {
1412
1413 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1414 DBusMessage* msg;
1415 DBusMessageIter args;
1416
1417 // create a signal and check for errors
1418 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1419 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1420 "UpdatePreeditCaret"); // name of the signal
1421 if (NULL == msg) {
1422 FcitxLog(DEBUG, "Message Null");
1423 return;
1424 }
1425
1426 // append arguments onto signal
1427 dbus_message_iter_init_append(msg, &args);
1428 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &position)) {
1429 FcitxLog(DEBUG, "Out Of Memory!");
1430 }
1431
1432 // send the message and flush the connection
1433 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1434 FcitxLog(DEBUG, "Out Of Memory!");
1435 }
1436
1437 // free the message
1438 dbus_message_unref(msg);
1439
1440 }
1441
KimUpdatePreeditText(FcitxKimpanelUI * kimpanel,char * text)1442 void KimUpdatePreeditText(FcitxKimpanelUI* kimpanel, char *text)
1443 {
1444
1445 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1446 DBusMessage* msg;
1447 DBusMessageIter args;
1448
1449 // create a signal and check for errors
1450 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1451 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1452 "UpdatePreeditText"); // name of the signal
1453 if (NULL == msg) {
1454 FcitxLog(DEBUG, "Message Null");
1455 return;
1456 }
1457
1458 char *attr = "";
1459 // append arguments onto signal
1460 dbus_message_iter_init_append(msg, &args);
1461 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &text)) {
1462 FcitxLog(DEBUG, "Out Of Memory!");
1463 }
1464 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &attr)) {
1465 FcitxLog(DEBUG, "Out Of Memory!");
1466 }
1467
1468 // send the message and flush the connection
1469 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1470 FcitxLog(DEBUG, "Out Of Memory!");
1471 }
1472
1473 // free the message
1474 dbus_message_unref(msg);
1475
1476 }
1477
KimUpdateAux(FcitxKimpanelUI * kimpanel,char * text)1478 void KimUpdateAux(FcitxKimpanelUI* kimpanel, char *text)
1479 {
1480
1481 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1482 DBusMessage* msg;
1483 DBusMessageIter args;
1484
1485 // create a signal and check for errors
1486 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1487 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1488 "UpdateAux"); // name of the signal
1489 if (NULL == msg) {
1490 FcitxLog(DEBUG, "Message Null");
1491 return;
1492 }
1493 if (!fcitx_utf8_check_string(text))
1494 return;
1495
1496 char *attr = "";
1497
1498 // append arguments onto signal
1499 dbus_message_iter_init_append(msg, &args);
1500 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &text)) {
1501 FcitxLog(DEBUG, "Out Of Memory!");
1502 }
1503 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &attr)) {
1504 FcitxLog(DEBUG, "Out Of Memory!");
1505 }
1506
1507 // send the message and flush the connection
1508 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1509 FcitxLog(DEBUG, "Out Of Memory!");
1510 }
1511
1512 // free the message
1513 dbus_message_unref(msg);
1514
1515 }
1516
KimUpdateSpotLocation(FcitxKimpanelUI * kimpanel,int x,int y)1517 void KimUpdateSpotLocation(FcitxKimpanelUI* kimpanel, int x, int y)
1518 {
1519 if (kimpanel->lastUpdateX == x && kimpanel->lastUpdateY == y)
1520 return;
1521 kimpanel->lastUpdateX = x;
1522 kimpanel->lastUpdateY = y;
1523 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1524 DBusMessage* msg;
1525 DBusMessageIter args;
1526
1527 // create a signal and check for errors
1528 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1529 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1530 "UpdateSpotLocation"); // name of the signal
1531 if (NULL == msg) {
1532 FcitxLog(DEBUG, "Message Null");
1533 return;
1534 }
1535
1536 // append arguments onto signal
1537 dbus_message_iter_init_append(msg, &args);
1538 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &x)) {
1539 FcitxLog(DEBUG, "Out Of Memory!");
1540 }
1541 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &y)) {
1542 FcitxLog(DEBUG, "Out Of Memory!");
1543 }
1544
1545 // send the message and flush the connection
1546 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1547 FcitxLog(DEBUG, "Out Of Memory!");
1548 }
1549
1550 // free the message
1551 dbus_message_unref(msg);
1552
1553 }
1554
KimSetSpotRect(FcitxKimpanelUI * kimpanel,int x,int y,int w,int h,boolean relative)1555 void KimSetSpotRect(FcitxKimpanelUI* kimpanel, int x, int y, int w, int h, boolean relative)
1556 {
1557 if (kimpanel->lastUpdateX == x && kimpanel->lastUpdateY == y && kimpanel->lastUpdateW == w && kimpanel->lastUpdateH == h)
1558 return;
1559 kimpanel->lastUpdateX = x;
1560 kimpanel->lastUpdateY = y;
1561 kimpanel->lastUpdateW = w;
1562 kimpanel->lastUpdateH = h;
1563 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1564 DBusMessage* msg;
1565
1566 boolean useRelative = kimpanel->hasSetRelativeSpotRect && relative;
1567
1568 // create a signal and check for errors
1569 msg = dbus_message_new_method_call("org.kde.impanel",
1570 "/org/kde/impanel",
1571 "org.kde.impanel2",
1572 useRelative ? "SetRelativeSpotRect" : "SetSpotRect"); // name of the signal
1573 if (NULL == msg) {
1574 FcitxLog(DEBUG, "Message Null");
1575 return;
1576 }
1577
1578 if (!dbus_message_append_args(
1579 msg,
1580 DBUS_TYPE_INT32, &x,
1581 DBUS_TYPE_INT32, &y,
1582 DBUS_TYPE_INT32, &w,
1583 DBUS_TYPE_INT32, &h,
1584 DBUS_TYPE_INVALID
1585 )) {
1586 FcitxLog(DEBUG, "Out Of Memory!");
1587 }
1588
1589 // send the message and flush the connection
1590 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1591 FcitxLog(DEBUG, "Out Of Memory!");
1592 }
1593
1594 // free the message
1595 dbus_message_unref(msg);
1596 }
1597
1598
KimUpdateScreen(FcitxKimpanelUI * kimpanel,int id)1599 void KimUpdateScreen(FcitxKimpanelUI* kimpanel, int id)
1600 {
1601
1602 dbus_uint32_t serial = 0; // unique number to associate replies with requests
1603 DBusMessage* msg;
1604 DBusMessageIter args;
1605
1606 // create a signal and check for errors
1607 msg = dbus_message_new_signal(FCITX_KIMPANEL_PATH, // object name of the signal
1608 FCITX_KIMPANEL_INTERFACE, // interface name of the signal
1609 "UpdateScreen"); // name of the signal
1610 if (NULL == msg) {
1611 FcitxLog(DEBUG, "Message Null");
1612 return;
1613 }
1614
1615 // append arguments onto signal
1616 dbus_message_iter_init_append(msg, &args);
1617 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &id)) {
1618 FcitxLog(DEBUG, "Out Of Memory!");
1619 }
1620
1621 // send the message and flush the connection
1622 if (!dbus_connection_send(kimpanel->conn, msg, &serial)) {
1623 FcitxLog(DEBUG, "Out Of Memory!");
1624 }
1625
1626 // free the message
1627 dbus_message_unref(msg);
1628
1629 }
1630
CalKimCursorPos(FcitxKimpanelUI * kimpanel)1631 int CalKimCursorPos(FcitxKimpanelUI *kimpanel)
1632 {
1633 int i = 0;
1634 unsigned int iChar;
1635 int iCount = 0;
1636 FcitxMessages *messageUp = kimpanel->messageUp;
1637
1638 const char *p1;
1639 const char *pivot;
1640
1641 iChar = kimpanel->iCursorPos;
1642
1643 for (i = 0;i < FcitxMessagesGetMessageCount(messageUp);i++) {
1644 if (kimpanel->iCursorPos && iChar) {
1645 p1 = pivot = FcitxMessagesGetMessageString(messageUp, i);
1646 while (*p1 && p1 < pivot + iChar) {
1647 p1 = p1 + fcitx_utf8_char_len(p1);
1648 iCount ++;
1649 }
1650 if (strlen(FcitxMessagesGetMessageString(messageUp, i)) > iChar) {
1651 iChar = 0;
1652 } else {
1653 iChar -= strlen(FcitxMessagesGetMessageString(messageUp, i));
1654 }
1655 }
1656 }
1657
1658 return iCount;
1659 }
1660
KimpanelServiceExistCallback(DBusPendingCall * call,void * data)1661 void KimpanelServiceExistCallback(DBusPendingCall *call, void *data)
1662 {
1663 FcitxKimpanelUI *kimpanel = (FcitxKimpanelUI*)data;
1664
1665 DBusMessage *msg = dbus_pending_call_steal_reply(call);
1666
1667 if (msg) {
1668 dbus_bool_t has = FALSE;
1669 DBusError error;
1670 dbus_error_init(&error);
1671 dbus_message_get_args(msg, &error,
1672 DBUS_TYPE_BOOLEAN, &has, DBUS_TYPE_INVALID);
1673 dbus_message_unref(msg);
1674 dbus_error_free(&error);
1675 if (!has) {
1676 FcitxUISwitchToFallback(kimpanel->owner);
1677 } else {
1678 KimpanelIntrospect(kimpanel);
1679 }
1680 }
1681 }
1682
KimpanelIntrospect(FcitxKimpanelUI * kimpanel)1683 void KimpanelIntrospect(FcitxKimpanelUI* kimpanel)
1684 {
1685 const char* kimpanelServiceName = "org.kde.impanel";
1686 DBusMessage* message = dbus_message_new_method_call(kimpanelServiceName, "/org/kde/impanel", DBUS_INTERFACE_INTROSPECTABLE, "Introspect");
1687
1688 DBusPendingCall *call = NULL;
1689 dbus_bool_t reply =
1690 dbus_connection_send_with_reply(kimpanel->conn, message,
1691 &call, DBUS_TIMEOUT_USE_DEFAULT);
1692 dbus_message_unref(message);
1693 if (reply == TRUE) {
1694 dbus_pending_call_set_notify(call, KimpanelIntrospectCallback,
1695 kimpanel, NULL);
1696 dbus_pending_call_unref(call);
1697 }
1698 dbus_connection_flush(kimpanel->conn);
1699 }
1700
KimpanelIntrospectCallback(DBusPendingCall * call,void * data)1701 void KimpanelIntrospectCallback(DBusPendingCall *call, void *data)
1702 {
1703 FcitxKimpanelUI *kimpanel = (FcitxKimpanelUI*)data;
1704 DBusMessage *msg = dbus_pending_call_steal_reply(call);
1705
1706 if (msg) {
1707 const char *s;
1708 DBusError error;
1709 dbus_error_init(&error);
1710 if (dbus_message_get_args(msg, &error, DBUS_TYPE_STRING, &s,
1711 DBUS_TYPE_INVALID)) {
1712 if (strstr(s, "org.kde.impanel2")) {
1713 kimpanel->version = 2;
1714 if (strstr(s, "SetLookupTable")) {
1715 kimpanel->hasSetLookupTable = true;
1716 }
1717 if (strstr(s, "SetRelativeSpotRect")) {
1718 kimpanel->hasSetRelativeSpotRect = true;
1719 }
1720 }
1721 }
1722 dbus_message_unref(msg);
1723 dbus_error_free(&error);
1724 }
1725 }
1726
1727
KimpanelSuspend(void * arg)1728 void KimpanelSuspend(void* arg)
1729 {
1730 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
1731 kimpanel->version = 1;
1732 kimpanel->hasSetLookupTable = false;
1733 kimpanel->hasSetRelativeSpotRect = false;
1734 }
1735
1736
KimpanelDestroy(void * arg)1737 void KimpanelDestroy(void* arg)
1738 {
1739 FcitxKimpanelUI* kimpanel = (FcitxKimpanelUI*) arg;
1740 KimpanelCloseInputWindow(kimpanel);
1741 KimRegisterProperties(kimpanel, NULL, 0);
1742 dbus_connection_unregister_object_path(kimpanel->conn, FCITX_KIMPANEL_PATH);
1743 dbus_connection_remove_filter(kimpanel->conn, KimpanelDBusFilter, kimpanel);
1744
1745 dbus_bus_remove_match(kimpanel->conn,
1746 "type='signal',sender='org.kde.impanel',interface='org.kde.impanel'",
1747 NULL);
1748 dbus_bus_remove_match(kimpanel->conn,
1749 "type='signal',sender='org.kde.impanel',interface='org.kde.impanel2'",
1750 NULL);
1751
1752 dbus_connection_flush(kimpanel->conn);
1753
1754 free(kimpanel->messageUp);
1755 free(kimpanel->messageDown);
1756 free(kimpanel);
1757 }
1758
1759 // kate: indent-mode cstyle; space-indent on; indent-width 0;
1760