2 * Copyright © 2013 Intel Corporation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
25 #define PANEL_CHECK_MESSAGE_ERRORS(_msg) \
28 const char *error, *error_msg; \
29 if (eldbus_message_error_get(_msg, &error, &error_msg)) \
31 ERR("DBus message error: %s: %s", error, error_msg); \
34 DBG("Message '%s' with signature '%s'", eldbus_message_member_get(_msg), eldbus_message_signature_get(_msg)); \
37 static Eina_Array *_get_properties_from_message_iter(Eldbus_Message_Iter *iter);
39 struct _ibus_serializable
42 * All messages sent by IBus will start with the sa{sv} signature, but
43 * those fields don't seem useful for us, this struct is used to help
44 * on deserializing those fields
47 Eldbus_Message_Iter *variant;
54 unsigned int start_idx;
64 struct _ibus_lookup_table
66 unsigned int page_size;
67 unsigned int cursor_pos;
68 Eina_Bool cursor_visible;
71 Eina_Array *candidates;
79 struct _ibus_text *label;
80 struct _ibus_text *symbol;
81 struct _ibus_text *tooltip;
86 Eina_Array *sub_properties;
89 static struct _ibus_attr *
90 _get_attr_from_message_iter(Eldbus_Message_Iter *iter)
92 struct _ibus_attr *attr = calloc(1, sizeof(*attr));
94 EINA_SAFETY_ON_NULL_RETURN_VAL(attr, NULL);
96 DBG("Attribute iter signature '%s'", eldbus_message_iter_signature_get(iter));
98 if (!eldbus_message_iter_arguments_get(iter, "uuuu", &attr->type,
99 &attr->value, &attr->start_idx,
102 ERR("Error deserializing IBusAttribute");
111 _free_eina_array(Eina_Array *array, void (* free_func)(void *))
116 while (eina_array_count(array))
117 free_func(eina_array_pop(array));
119 eina_array_free(array);
123 _free_text(struct _ibus_text *text)
128 _free_eina_array(text->attrs, free);
133 static struct _ibus_text *
134 _get_text_from_message_iter(Eldbus_Message_Iter *iter)
136 struct _ibus_serializable ignore = { 0 };
137 struct _ibus_text *text = calloc(1, sizeof(*text));
138 struct _ibus_attr *attr = NULL;
139 Eldbus_Message_Iter *attrs = NULL, *a = NULL;
141 EINA_SAFETY_ON_NULL_RETURN_VAL(text, NULL);
143 DBG("Text iter signature '%s'", eldbus_message_iter_signature_get(iter));
145 if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}sv)", &ignore.text,
146 &ignore.variant, &text->text, &attrs))
148 ERR("Error deserializing IBusText");
154 /* Check for attributes */
157 INF("Text has no attributes");
161 while (eldbus_message_iter_get_and_next(attrs, 'v', &a))
164 text->attrs = eina_array_new(10);
166 if (!(attr = _get_attr_from_message_iter(a)))
173 eina_array_push(text->attrs, attr);
181 _free_lookup_table(struct _ibus_lookup_table *table)
186 _free_eina_array(table->candidates, _free_text);
187 _free_eina_array(table->labels, _free_text);
191 static struct _ibus_lookup_table *
192 _get_lookup_table_from_message_iter(Eldbus_Message_Iter *iter)
194 struct _ibus_serializable ignore = { 0 };
195 struct _ibus_lookup_table *table = calloc(1, sizeof(*table));
196 struct _ibus_text *text = NULL;
197 Eldbus_Message_Iter *candidates = NULL, *labels = NULL, *t = NULL;
199 EINA_SAFETY_ON_NULL_RETURN_VAL(table, NULL);
201 DBG("LookupTable iter signature '%s'", eldbus_message_iter_signature_get(iter));
203 if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}uubbiavav)",
204 &ignore.text, &ignore.variant,
205 &table->page_size, &table->cursor_pos,
206 &table->cursor_visible, &table->round,
207 &table->orientation, &candidates,
210 ERR("Error deserializing IBusLookupTable");
216 DBG("Lookup table:");
217 DBG("\tPage size.......: '%d'", table->page_size);
218 DBG("\tCursor position.: '%d'", table->cursor_pos);
219 DBG("\tCursor visible..: '%d'", table->cursor_visible);
220 DBG("\tRound...........: '%d'", table->round);
221 DBG("\tOrientation.....: '%d'", table->orientation);
222 DBG("\tCandidates......: '%p'", candidates);
223 DBG("\tLabels..........: '%p'", labels);
227 INF("Lookup table has no candidates");
231 while (eldbus_message_iter_get_and_next(candidates, 'v', &t))
233 if (!table->candidates)
234 table->candidates = eina_array_new(10);
236 if (!(text = _get_text_from_message_iter(t)))
238 _free_lookup_table(table);
243 DBG("Appending new candidate %s", text->text);
244 eina_array_push(table->candidates, text);
250 INF("Lookup table has no labels");
254 while (eldbus_message_iter_get_and_next(labels, 'v', &t))
257 table->labels = eina_array_new(10);
259 if (!(text = _get_text_from_message_iter(t)))
261 _free_lookup_table(table);
266 DBG("Appending new label %s", text->text);
267 eina_array_push(table->labels, text);
275 _free_property(struct _ibus_property *property)
281 free(property->icon);
282 _free_text(property->label);
283 _free_text(property->symbol);
284 _free_text(property->tooltip);
285 _free_eina_array(property->sub_properties, _free_property);
289 static struct _ibus_property *
290 _get_property_from_message_iter(Eldbus_Message_Iter *iter)
292 struct _ibus_serializable ignore = { 0 };
293 struct _ibus_property *prop = calloc(1, sizeof(*prop));
294 Eldbus_Message_Iter *label = NULL, *symbol = NULL, *tooltip = NULL, *sub_props = NULL;
296 EINA_SAFETY_ON_NULL_RETURN_VAL(prop, NULL);
298 DBG("Property iter signature '%s'", eldbus_message_iter_signature_get(iter));
300 if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}suvsvbbuvv)",
301 &ignore.text, &ignore.variant,
302 &prop->key, &prop->type,
303 &label, &prop->icon, &tooltip,
304 &prop->sensitive, &prop->visible,
305 &prop->state, &sub_props, &symbol))
307 ERR("Error deserializing IBusProperty");
314 DBG("\tKey.............: '%s'", prop->key);
315 DBG("\tType............: '%d'", prop->type);
316 DBG("\tLabel...........: '%p'", label);
317 DBG("\tIcon............: '%s'", prop->icon);
318 DBG("\tTooltip.........: '%p'", tooltip);
319 DBG("\tSensitive.......: '%d'", prop->sensitive);
320 DBG("\tVisible.........: '%d'", prop->visible);
321 DBG("\tState...........: '%d'", prop->state);
322 DBG("\tSub Properties..: '%p'", sub_props);
323 DBG("\tSymbol..........: '%p'", symbol);
327 INF("Property has no label");
331 if (!(prop->label = _get_text_from_message_iter(label)))
333 _free_property(prop);
341 INF("Property has no symbol");
345 if (!(prop->symbol = _get_text_from_message_iter(symbol)))
347 _free_property(prop);
355 INF("Property has no tooltip");
359 if (!(prop->tooltip = _get_text_from_message_iter(tooltip)))
361 _free_property(prop);
369 INF("Property has no sub properties");
373 prop->sub_properties = _get_properties_from_message_iter(sub_props);
380 _get_properties_from_message_iter(Eldbus_Message_Iter *iter)
382 Eina_Array *properties = NULL;
383 Eldbus_Message_Iter *props = NULL, *prop = NULL;
384 struct _ibus_serializable ignore = { 0 };
385 struct _ibus_property *property = NULL;
387 DBG("PropList iter signature '%s'", eldbus_message_iter_signature_get(iter));
389 if (!eldbus_message_iter_arguments_get(iter, "(sa{sv}av)", &ignore.text, &ignore.variant, &props))
391 ERR("Error deserializing IBusPropList");
397 INF("PropList has no property");
401 while (eldbus_message_iter_get_and_next(props, 'v', &prop))
404 properties = eina_array_new(10);
406 if (!(property = _get_property_from_message_iter(prop)))
408 _free_eina_array(properties, _free_property);
413 DBG("Appending new property %p", property);
414 eina_array_push(properties, property);
421 static Eldbus_Message *
422 _panel_update_preedit_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
424 Eldbus_Message_Iter *text = NULL;
425 unsigned int cursor_pos = 0;
426 Eina_Bool visible = 0;
427 struct _ibus_text *ibus_text;
429 PANEL_CHECK_MESSAGE_ERRORS(msg)
431 if (!eldbus_message_arguments_get(msg, "vub", &text, &cursor_pos, &visible))
433 ERR("Error reading message arguments");
437 DBG("text: '%p', cursor_pos: '%d', visible: '%d')", text, cursor_pos, visible);
439 ibus_text = _get_text_from_message_iter(text);
440 DBG("Preedit text = '%s'", ibus_text->text);
441 _free_text(ibus_text);
446 static Eldbus_Message *
447 _panel_show_preedit_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
449 PANEL_CHECK_MESSAGE_ERRORS(msg)
454 static Eldbus_Message *
455 _panel_hide_preedit_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
457 PANEL_CHECK_MESSAGE_ERRORS(msg)
462 static Eldbus_Message *
463 _panel_update_auxiliary_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
465 Eldbus_Message_Iter *text = NULL;
466 Eina_Bool visible = 0;
467 struct _ibus_text *ibus_text;
469 PANEL_CHECK_MESSAGE_ERRORS(msg)
471 if (!eldbus_message_arguments_get(msg, "vb", &text, &visible))
473 ERR("Error reading message arguments");
477 DBG("text: '%p', visible: '%d'", text, visible);
479 ibus_text = _get_text_from_message_iter(text);
480 DBG("Auxiliary text = '%s'", ibus_text->text);
481 _free_text(ibus_text);
486 static Eldbus_Message *
487 _panel_show_auxiliary_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
489 PANEL_CHECK_MESSAGE_ERRORS(msg)
494 static Eldbus_Message *
495 _panel_hide_auxiliary_text(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
497 PANEL_CHECK_MESSAGE_ERRORS(msg)
502 static Eldbus_Message *
503 _panel_update_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
505 Eldbus_Message_Iter *table = NULL;
506 Eina_Bool visible = 0;
507 struct _ibus_lookup_table *ibus_lookup_table;
509 PANEL_CHECK_MESSAGE_ERRORS(msg)
511 if (!eldbus_message_arguments_get(msg, "vb", &table, &visible))
513 ERR("Error reading message arguments");
517 DBG("table: '%p', visible: '%d'", table, visible);
519 ibus_lookup_table = _get_lookup_table_from_message_iter(table);
520 _free_lookup_table(ibus_lookup_table);
525 static Eldbus_Message *
526 _panel_show_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
528 PANEL_CHECK_MESSAGE_ERRORS(msg)
533 static Eldbus_Message *
534 _panel_hide_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
536 PANEL_CHECK_MESSAGE_ERRORS(msg)
543 static Eldbus_Message *
544 _panel_cursor_up_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
546 PANEL_CHECK_MESSAGE_ERRORS(msg)
553 static Eldbus_Message *
554 _panel_cursor_down_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
556 PANEL_CHECK_MESSAGE_ERRORS(msg)
561 static Eldbus_Message *
562 _panel_page_up_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
564 PANEL_CHECK_MESSAGE_ERRORS(msg)
569 static Eldbus_Message *
570 _panel_page_down_lookup_table(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
572 PANEL_CHECK_MESSAGE_ERRORS(msg)
577 static Eldbus_Message *
578 _panel_register_properties(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
580 Eldbus_Message_Iter *props = NULL;
581 Eina_Array *properties = NULL;
583 PANEL_CHECK_MESSAGE_ERRORS(msg)
585 if (!eldbus_message_arguments_get(msg, "v", &props))
587 ERR("Error reading message arguments");
591 DBG("properties: '%p'", props);
593 properties = _get_properties_from_message_iter(props);
594 _free_eina_array(properties, _free_property);
599 static Eldbus_Message *
600 _panel_update_property(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
602 Eldbus_Message_Iter *prop = NULL;
604 PANEL_CHECK_MESSAGE_ERRORS(msg)
606 if (!eldbus_message_arguments_get(msg, "v", &prop))
608 ERR("Error reading message arguments");
612 DBG("property : '%p'", prop);
613 DBG("Property iter signature: %s", eldbus_message_iter_signature_get(prop));
618 static Eldbus_Message *
619 _panel_focus_in(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
621 PANEL_CHECK_MESSAGE_ERRORS(msg)
626 static Eldbus_Message *
627 _panel_focus_out(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
629 PANEL_CHECK_MESSAGE_ERRORS(msg)
634 static Eldbus_Message *
635 _panel_set_cursor_location(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
637 int x = 0, y = 0, w = 0, h = 0;
639 PANEL_CHECK_MESSAGE_ERRORS(msg)
641 if (!eldbus_message_arguments_get(msg, "iiii", &x, &y, &w, &h))
643 ERR("Error reading message arguments");
647 DBG("x: %d, y: %d, w: %d, h: %d", x, y, w, h);
652 static Eldbus_Message *
653 _panel_reset(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
655 PANEL_CHECK_MESSAGE_ERRORS(msg)
660 static Eldbus_Message *
661 _panel_start_setup(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
663 PANEL_CHECK_MESSAGE_ERRORS(msg)
668 static Eldbus_Message *
669 _panel_state_changed(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
671 PANEL_CHECK_MESSAGE_ERRORS(msg)
676 static Eldbus_Message *
677 _panel_hide_language_bar(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
679 PANEL_CHECK_MESSAGE_ERRORS(msg)
684 static Eldbus_Message *
685 _panel_show_language_bar(const Eldbus_Service_Interface *iface, const Eldbus_Message *msg)
687 PANEL_CHECK_MESSAGE_ERRORS(msg)
692 static const Eldbus_Method _wkb_ibus_panel_methods[] =
694 /* typedef struct _Eldbus_Method
696 * const char *member;
697 * const Eldbus_Arg_Info *in;
698 * const Eldbus_Arg_Info *out;
699 * Eldbus_Method_Cb cb;
700 * unsigned int flags;
703 { .member = "UpdatePreeditText",
704 .in = ELDBUS_ARGS({"v", "text"}, {"u", "cursor_pos"}, {"b", "visible"}),
705 .cb = _panel_update_preedit_text, },
707 { .member = "ShowPreeditText",
708 .cb = _panel_show_preedit_text, },
710 { .member = "HidePreeditText",
711 .cb = _panel_hide_preedit_text, },
713 { .member = "UpdateAuxiliaryText",
714 .in = ELDBUS_ARGS({"v", "text"}, {"b", "visible"}),
715 .cb = _panel_update_auxiliary_text, },
717 { .member = "ShowAuxiliaryText",
718 .cb = _panel_show_auxiliary_text, },
720 { .member = "HideAuxiliaryText",
721 .cb = _panel_hide_auxiliary_text, },
723 { .member = "UpdateLookupTable",
724 .in = ELDBUS_ARGS({"v", "table"}, {"b", "visible"}),
725 .cb = _panel_update_lookup_table, },
727 { .member = "ShowLookupTable",
728 .cb = _panel_show_lookup_table, },
730 { .member = "HideLookupTable",
731 .cb = _panel_hide_lookup_table, },
733 { .member = "CursorUpLookupTable",
734 .cb = _panel_cursor_up_lookup_table, },
736 { .member = "CursorDownLookupTable",
737 .cb = _panel_cursor_down_lookup_table, },
739 { .member = "PageUpLookupTable",
740 .cb = _panel_page_up_lookup_table, },
742 { .member = "PageDownLookupTable",
743 .cb = _panel_page_down_lookup_table, },
745 { .member = "RegisterProperties",
746 .in = ELDBUS_ARGS({"v", "props"}),
747 .cb = _panel_register_properties, },
749 { .member = "UpdateProperty",
750 .in = ELDBUS_ARGS({"v", "prop"}),
751 .cb = _panel_update_property, },
753 { .member = "FocusIn",
754 .in = ELDBUS_ARGS({"o", "ic"}),
755 .cb = _panel_focus_in, },
757 { .member = "FocusOut",
758 .in = ELDBUS_ARGS({"o", "ic"}),
759 .cb = _panel_focus_out, },
761 { .member = "SetCursorLocation",
762 .in = ELDBUS_ARGS({"i", "x"}, {"i", "y"}, {"i", "w"}, {"i", "h"}),
763 .cb = _panel_set_cursor_location, },
766 .cb = _panel_reset, },
768 { .member = "StartSetup",
769 .cb = _panel_start_setup, },
771 { .member = "StateChanged",
772 .cb = _panel_state_changed, },
774 { .member = "HideLanguageBar",
775 .cb = _panel_hide_language_bar, },
777 { .member = "ShowLanguageBar",
778 .cb = _panel_show_language_bar, },
783 static const Eldbus_Signal _wkb_ibus_panel_signals[] =
785 /* typedef struct _Eldbus_Signal
788 * const Eldbus_Arg_Info *args;
789 * unsigned int flags;
792 { .name = "CursorUp", },
794 { .name = "CursorDown", },
796 { .name = "PageUp", },
798 { .name = "PageDown", },
800 { .name = "PropertyActivate",
801 .args = ELDBUS_ARGS({"s", "prop_name"}, {"i", "prop_state"}),
804 { .name = "PropertyShow",
805 .args = ELDBUS_ARGS({"s", "prop_name"}),
808 { .name = "PropertyHide",
809 .args = ELDBUS_ARGS({"s", "prop_name"}),
812 { .name = "CandidateClicked",
813 .args = ELDBUS_ARGS({"u", "index"}, {"u", "button"}, {"u", "state"}),
819 static const Eldbus_Service_Interface_Desc _wkb_ibus_panel_interface =
821 .interface = IBUS_INTERFACE_PANEL,
822 .methods = _wkb_ibus_panel_methods,
823 .signals = _wkb_ibus_panel_signals,
826 Eldbus_Service_Interface *
827 wkb_ibus_panel_register(Eldbus_Connection *conn)
829 return eldbus_service_interface_register(conn, IBUS_PATH_PANEL, &_wkb_ibus_panel_interface);