1 /* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2 /* vim:set et sts=4: */
3 /* ibus - The Input Bus
4  * Copyright (c) 2009-2014 Google Inc. All rights reserved.
5  * Copyright (C) 2010-2014 Peng Huang <shawn.p.huang@gmail.com>
6  * Copyright (C) 2017-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
21  * USA
22  */
23 #include "ibusshare.h"
24 #include "ibuspanelservice.h"
25 #include "ibusmarshalers.h"
26 #include "ibusinternal.h"
27 
28 #define IBUS_PANEL_SERVICE_GET_PRIVATE(o)  \
29    (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_PANEL_SERVICE, \
30                                  IBusPanelServicePrivate))
31 
32 enum {
33     UPDATE_PREEDIT_TEXT,
34     UPDATE_AUXILIARY_TEXT,
35     UPDATE_LOOKUP_TABLE,
36     FOCUS_IN,
37     FOCUS_OUT,
38     REGISTER_PROPERTIES,
39     UPDATE_PROPERTY,
40     SET_CURSOR_LOCATION,
41     SET_CURSOR_LOCATION_RELATIVE,
42     CURSOR_UP_LOOKUP_TABLE,
43     CURSOR_DOWN_LOOKUP_TABLE,
44     HIDE_AUXILIARY_TEXT,
45     HIDE_LANGUAGE_BAR,
46     HIDE_LOOKUP_TABLE,
47     HIDE_PREEDIT_TEXT,
48     PAGE_UP_LOOKUP_TABLE,
49     PAGE_DOWN_LOOKUP_TABLE,
50     RESET,
51     SHOW_AUXILIARY_TEXT,
52     SHOW_LANGUAGE_BAR,
53     SHOW_LOOKUP_TABLE,
54     SHOW_PREEDIT_TEXT,
55     START_SETUP,
56     STATE_CHANGED,
57     DESTROY_CONTEXT,
58     SET_CONTENT_TYPE,
59     PANEL_EXTENSION_RECEIVED,
60     PROCESS_KEY_EVENT,
61     COMMIT_TEXT_RECEIVED,
62     CANDIDATE_CLICKED_LOOKUP_TABLE,
63     LAST_SIGNAL,
64 };
65 
66 enum {
67     PROP_0,
68 };
69 
70 static guint            panel_signals[LAST_SIGNAL] = { 0 };
71 
72 /* functions prototype */
73 static void      ibus_panel_service_set_property
74                                    (IBusPanelService       *panel,
75                                     guint                   prop_id,
76                                     const GValue           *value,
77                                     GParamSpec             *pspec);
78 static void      ibus_panel_service_get_property
79                                    (IBusPanelService       *panel,
80                                     guint                   prop_id,
81                                     GValue                 *value,
82                                     GParamSpec             *pspec);
83 static void      ibus_panel_service_real_destroy
84                                    (IBusPanelService       *panel);
85 static void      ibus_panel_service_service_method_call
86                                    (IBusService            *service,
87                                     GDBusConnection        *connection,
88                                     const gchar            *sender,
89                                     const gchar            *object_path,
90                                     const gchar            *interface_name,
91                                     const gchar            *method_name,
92                                     GVariant               *parameters,
93                                     GDBusMethodInvocation  *invocation);
94 static GVariant *ibus_panel_service_service_get_property
95                                    (IBusService            *service,
96                                     GDBusConnection        *connection,
97                                     const gchar            *sender,
98                                     const gchar            *object_path,
99                                     const gchar            *interface_name,
100                                     const gchar            *property_name,
101                                     GError                **error);
102 static gboolean  ibus_panel_service_service_set_property
103                                    (IBusService            *service,
104                                     GDBusConnection        *connection,
105                                     const gchar            *sender,
106                                     const gchar            *object_path,
107                                     const gchar            *interface_name,
108                                     const gchar            *property_name,
109                                     GVariant               *value,
110                                     GError                **error);
111 static void      ibus_panel_service_not_implemented
112                                    (IBusPanelService       *panel);
113 static void      ibus_panel_service_focus_in
114                                    (IBusPanelService       *panel,
115                                     const gchar            *input_context_path);
116 static void      ibus_panel_service_focus_out
117                                    (IBusPanelService       *panel,
118                                     const gchar            *input_context_path);
119 static void      ibus_panel_service_destroy_context
120                                    (IBusPanelService       *panel,
121                                     const gchar            *input_context_path);
122 static void      ibus_panel_service_register_properties
123                                    (IBusPanelService       *panel,
124                                     IBusPropList           *prop_list);
125 static void      ibus_panel_service_set_cursor_location
126                                    (IBusPanelService       *panel,
127                                     gint                    x,
128                                     gint                    y,
129                                     gint                    w,
130                                     gint                    h);
131 static void      ibus_panel_service_set_cursor_location_relative
132                                    (IBusPanelService       *panel,
133                                     gint                    x,
134                                     gint                    y,
135                                     gint                    w,
136                                     gint                    h);
137 static void      ibus_panel_service_update_auxiliary_text
138                                    (IBusPanelService       *panel,
139                                     IBusText               *text,
140                                     gboolean                visible);
141 static void      ibus_panel_service_update_lookup_table
142                                    (IBusPanelService       *panel,
143                                     IBusLookupTable        *lookup_table,
144                                     gboolean                visible);
145 static void      ibus_panel_service_update_preedit_text
146                                    (IBusPanelService       *panel,
147                                     IBusText               *text,
148                                     guint                   cursor_pos,
149                                     gboolean                visible);
150 static void      ibus_panel_service_update_property
151                                    (IBusPanelService       *panel,
152                                     IBusProperty           *prop);
153 static void      ibus_panel_service_set_content_type
154                                    (IBusPanelService       *panel,
155                                     guint                   purpose,
156                                     guint                   hints);
157 static void      ibus_panel_service_panel_extension_received
158                                    (IBusPanelService       *panel,
159                                     IBusExtensionEvent     *event);
160 
161 G_DEFINE_TYPE (IBusPanelService, ibus_panel_service, IBUS_TYPE_SERVICE)
162 
163 static const gchar introspection_xml[] =
164     "<node>"
165     "  <interface name='org.freedesktop.IBus.Panel'>"
166     /* Methods */
167     "    <method name='UpdatePreeditText'>"
168     "      <arg direction='in'  type='v' name='text' />"
169     "      <arg direction='in'  type='u' name='cursor_pos' />"
170     "      <arg direction='in'  type='b' name='visible' />"
171     "    </method>"
172     "    <method name='ShowPreeditText' />"
173     "    <method name='HidePreeditText' />"
174     "    <method name='UpdateAuxiliaryText'>"
175     "      <arg direction='in'  type='v' name='text' />"
176     "      <arg direction='in'  type='b' name='visible' />"
177     "    </method>"
178     "    <method name='ShowAuxiliaryText' />"
179     "    <method name='HideAuxiliaryText' />"
180     "    <method name='UpdateLookupTable'>"
181     "      <arg direction='in' type='v' name='table' />"
182     "      <arg direction='in' type='b' name='visible' />"
183     "    </method>"
184     "    <method name='ShowLookupTable' />"
185     "    <method name='HideLookupTable' />"
186     "    <method name='CursorUpLookupTable' />"
187     "    <method name='CursorDownLookupTable' />"
188     "    <method name='PageUpLookupTable' />"
189     "    <method name='PageDownLookupTable' />"
190     "    <method name='CandidateClickedLookupTable'>"
191     "      <arg direction='in' type='u' name='index' />"
192     "      <arg direction='in' type='u' name='button' />"
193     "      <arg direction='in' type='u' name='state' />"
194     "    </method>"
195     "    <method name='RegisterProperties'>"
196     "      <arg direction='in'  type='v' name='props' />"
197     "    </method>"
198     "    <method name='UpdateProperty'>"
199     "      <arg direction='in'  type='v' name='prop' />"
200     "    </method>"
201     "    <method name='FocusIn'>"
202     "      <arg direction='in'  type='o' name='ic' />"
203     "    </method>"
204     "    <method name='FocusOut'>"
205     "      <arg direction='in'  type='o' name='ic' />"
206     "    </method>"
207     "    <method name='DestroyContext'>"
208     "      <arg direction='in'  type='o' name='ic' />"
209     "    </method>"
210     "    <method name='SetCursorLocation'>"
211     "      <arg direction='in' type='i' name='x' />"
212     "      <arg direction='in' type='i' name='y' />"
213     "      <arg direction='in' type='i' name='w' />"
214     "      <arg direction='in' type='i' name='h' />"
215     "    </method>"
216     "    <method name='SetCursorLocationRelative'>"
217     "      <arg direction='in' type='i' name='x' />"
218     "      <arg direction='in' type='i' name='y' />"
219     "      <arg direction='in' type='i' name='w' />"
220     "      <arg direction='in' type='i' name='h' />"
221     "    </method>"
222     "    <method name='Reset' />"
223     "    <method name='StartSetup' />"
224     "    <method name='StateChanged' />"
225     "    <method name='HideLanguageBar' />"
226     "    <method name='ShowLanguageBar' />"
227     "    <method name='ContentType'>"
228     "      <arg direction='in'  type='u' name='purpose' />"
229     "      <arg direction='in'  type='u' name='hints' />"
230     "    </method>"
231     "    <method name='PanelExtensionReceived'>"
232     "      <arg direction='in' type='v' name='event' />"
233     "    </method>"
234     "    <method name='ProcessKeyEvent'>"
235     "      <arg direction='in'  type='u' name='keyval' />"
236     "      <arg direction='in'  type='u' name='keycode' />"
237     "      <arg direction='in'  type='u' name='state' />"
238     "      <arg direction='out' type='b' />"
239     "    </method>"
240     "    <method name='CommitTextReceived'>"
241     "      <arg direction='in' type='v' name='text' />"
242     "    </method>"
243     /* Signals */
244     "    <signal name='CursorUp' />"
245     "    <signal name='CursorDown' />"
246     "    <signal name='PageUp' />"
247     "    <signal name='PageDown' />"
248     "    <signal name='PropertyActivate'>"
249     "      <arg type='s' name='prop_name' />"
250     "      <arg type='i' name='prop_state' />"
251     "    </signal>"
252     "    <signal name='PropertyShow'>"
253     "      <arg type='s' name='prop_name' />"
254     "    </signal>"
255     "    <signal name='PropertyHide'>"
256     "      <arg type='s' name='prop_name' />"
257     "    </signal>"
258     "    <signal name='CandidateClicked'>"
259     "      <arg type='u' name='index' />"
260     "      <arg type='u' name='button' />"
261     "      <arg type='u' name='state' />"
262     "    </signal>"
263     "    <signal name='CommitText'>"
264     "      <arg type='v' name='text' />"
265     "    </signal>"
266     "    <signal name='PanelExtension'>"
267     "      <arg type='v' name='event' />"
268     "    </signal>"
269     "    <method name='PanelExtensionRegisterKeys'>"
270     "      <arg type='v' name='data' />"
271     "    </method>"
272     "    <signal name='UpdatePreeditTextReceived'>"
273     "      <arg type='v' name='text' />"
274     "      <arg type='u' name='cursor_pos' />"
275     "      <arg type='b' name='visible' />"
276     "    </signal>"
277     "    <signal name='UpdateAuxiliaryTextReceived'>"
278     "      <arg type='v' name='text' />"
279     "      <arg type='b' name='visible' />"
280     "    </signal>"
281     "    <signal name='UpdateLookupTableReceived'>"
282     "      <arg type='v' name='table' />"
283     "      <arg type='b' name='visible' />"
284     "    </signal>"
285     "  </interface>"
286     "</node>";
287 
288 static void
ibus_panel_service_class_init(IBusPanelServiceClass * class)289 ibus_panel_service_class_init (IBusPanelServiceClass *class)
290 {
291     GObjectClass *gobject_class = G_OBJECT_CLASS (class);
292     ibus_panel_service_parent_class =
293             IBUS_SERVICE_CLASS (g_type_class_peek_parent (class));
294 
295     gobject_class->set_property =
296             (GObjectSetPropertyFunc) ibus_panel_service_set_property;
297     gobject_class->get_property =
298             (GObjectGetPropertyFunc) ibus_panel_service_get_property;
299 
300     IBUS_OBJECT_CLASS (gobject_class)->destroy =
301             (IBusObjectDestroyFunc) ibus_panel_service_real_destroy;
302 
303     IBUS_SERVICE_CLASS (class)->service_method_call  =
304             ibus_panel_service_service_method_call;
305     IBUS_SERVICE_CLASS (class)->service_get_property =
306             ibus_panel_service_service_get_property;
307     IBUS_SERVICE_CLASS (class)->service_set_property =
308             ibus_panel_service_service_set_property;
309 
310     ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class),
311                                        introspection_xml);
312 
313     class->focus_in              = ibus_panel_service_focus_in;
314     class->focus_out             = ibus_panel_service_focus_out;
315     class->destroy_context       = ibus_panel_service_destroy_context;
316     class->register_properties   = ibus_panel_service_register_properties;
317     class->set_cursor_location   = ibus_panel_service_set_cursor_location;
318     class->set_cursor_location_relative = ibus_panel_service_set_cursor_location_relative;
319     class->update_lookup_table   = ibus_panel_service_update_lookup_table;
320     class->update_auxiliary_text = ibus_panel_service_update_auxiliary_text;
321     class->update_preedit_text   = ibus_panel_service_update_preedit_text;
322     class->update_property       = ibus_panel_service_update_property;
323     class->set_content_type      = ibus_panel_service_set_content_type;
324     class->panel_extension_received =
325             ibus_panel_service_panel_extension_received;
326 
327     class->cursor_down_lookup_table = ibus_panel_service_not_implemented;
328     class->cursor_up_lookup_table   = ibus_panel_service_not_implemented;
329     class->hide_auxiliary_text      = ibus_panel_service_not_implemented;
330     class->hide_language_bar        = ibus_panel_service_not_implemented;
331     class->hide_lookup_table        = ibus_panel_service_not_implemented;
332     class->hide_preedit_text        = ibus_panel_service_not_implemented;
333     class->page_down_lookup_table   = ibus_panel_service_not_implemented;
334     class->page_up_lookup_table     = ibus_panel_service_not_implemented;
335     class->reset                    = ibus_panel_service_not_implemented;
336     class->show_auxiliary_text      = ibus_panel_service_not_implemented;
337     class->show_language_bar        = ibus_panel_service_not_implemented;
338     class->show_lookup_table        = ibus_panel_service_not_implemented;
339     class->show_preedit_text        = ibus_panel_service_not_implemented;
340     class->start_setup              = ibus_panel_service_not_implemented;
341     class->state_changed            = ibus_panel_service_not_implemented;
342 
343     /* install signals */
344     /**
345      * IBusPanelService::update-preedit-text:
346      * @panel: An #IBusPanelService
347      * @text: A preedit text to be updated.
348      * @cursor_pos: The cursor position of the text.
349      * @visible: Whether the update is visible.
350      *
351      * Emitted when the client application get the ::update-preedit-text.
352      * Implement the member function
353      * IBusPanelServiceClass::update_preedit_text in extended class
354      * to receive this signal.
355      *
356      * <note><para>Argument @user_data is ignored in this function.</para>
357      * </note>
358      */
359     panel_signals[UPDATE_PREEDIT_TEXT] =
360         g_signal_new (I_("update-preedit-text"),
361             G_TYPE_FROM_CLASS (gobject_class),
362             G_SIGNAL_RUN_LAST,
363             G_STRUCT_OFFSET (IBusPanelServiceClass, update_preedit_text),
364             NULL, NULL,
365             _ibus_marshal_VOID__OBJECT_UINT_BOOLEAN,
366             G_TYPE_NONE,
367             3,
368             IBUS_TYPE_TEXT,
369             G_TYPE_UINT,
370             G_TYPE_BOOLEAN);
371 
372     /**
373      * IBusPanelService::update-auxiliary-text:
374      * @panel: An #IBusPanelService
375      * @text: A preedit text to be updated.
376      * @visible: Whether the update is visible.
377      *
378      * Emitted when the client application get the ::update-auxiliary-text.
379      * Implement the member function
380      * IBusPanelServiceClass::update_auxiliary_text in extended class
381      * to receive this signal.
382      *
383      * <note><para>Argument @user_data is ignored in this function.</para>
384      * </note>
385      */
386     panel_signals[UPDATE_AUXILIARY_TEXT] =
387         g_signal_new (I_("update-auxiliary-text"),
388             G_TYPE_FROM_CLASS (gobject_class),
389             G_SIGNAL_RUN_LAST,
390             G_STRUCT_OFFSET (IBusPanelServiceClass, update_auxiliary_text),
391             NULL, NULL,
392             _ibus_marshal_VOID__OBJECT_BOOLEAN,
393             G_TYPE_NONE,
394             2,
395             IBUS_TYPE_TEXT,
396             G_TYPE_BOOLEAN);
397 
398     /**
399      * IBusPanelService::update-lookup-table:
400      * @panel: An #IBusPanelService
401      * @lookup_table: A lookup table to be updated.
402      * @visible: Whether the update is visible.
403      *
404      * Emitted when the client application get the ::update-lookup-table.
405      * Implement the member function
406      * IBusPanelServiceClass::update_lookup_table in extended class
407      * to receive this signal.
408      *
409      * <note><para>Argument @user_data is ignored in this function.</para>
410      * </note>
411      */
412     panel_signals[UPDATE_LOOKUP_TABLE] =
413         g_signal_new (I_("update-lookup-table"),
414             G_TYPE_FROM_CLASS (gobject_class),
415             G_SIGNAL_RUN_LAST,
416             G_STRUCT_OFFSET (IBusPanelServiceClass, update_lookup_table),
417             NULL, NULL,
418             _ibus_marshal_VOID__OBJECT_BOOLEAN,
419             G_TYPE_NONE,
420             2,
421             IBUS_TYPE_LOOKUP_TABLE,
422             G_TYPE_BOOLEAN);
423 
424     /**
425      * IBusPanelService::focus-in:
426      * @panel: An #IBusPanelService
427      * @input_context_path: Object path of InputContext.
428      *
429      * Emitted when the client application get the ::focus-in.
430      * Implement the member function
431      * IBusPanelServiceClass::focus_in in extended class to receive
432      * this signal.
433      *
434      * <note><para>Argument @user_data is ignored in this function.</para>
435      * </note>
436      */
437     panel_signals[FOCUS_IN] =
438         g_signal_new (I_("focus-in"),
439             G_TYPE_FROM_CLASS (gobject_class),
440             G_SIGNAL_RUN_LAST,
441             G_STRUCT_OFFSET (IBusPanelServiceClass, focus_in),
442             NULL, NULL,
443             _ibus_marshal_VOID__STRING,
444             G_TYPE_NONE,
445             1,
446             G_TYPE_STRING);
447 
448     /**
449      * IBusPanelService::focus-out:
450      * @panel: An #IBusPanelService
451      * @input_context_path: Object path of InputContext.
452      *
453      * Emitted when the client application get the ::focus-out.
454      * Implement the member function
455      * IBusPanelServiceClass::focus_out in extended class to receive
456      * this signal.
457      *
458      * <note><para>Argument @user_data is ignored in this function.</para>
459      * </note>
460      */
461     panel_signals[FOCUS_OUT] =
462         g_signal_new (I_("focus-out"),
463             G_TYPE_FROM_CLASS (gobject_class),
464             G_SIGNAL_RUN_LAST,
465             G_STRUCT_OFFSET (IBusPanelServiceClass, focus_out),
466             NULL, NULL,
467             _ibus_marshal_VOID__STRING,
468             G_TYPE_NONE,
469             1,
470             G_TYPE_STRING);
471 
472     /**
473      * IBusPanelService::register-properties:
474      * @panel: An #IBusPanelService
475      * @prop_list: An IBusPropList that contains properties.
476      *
477      * Emitted when the client application get the ::register-properties.
478      * Implement the member function
479      * IBusPanelServiceClass::register_properties in extended class
480      * to receive this signal.
481      *
482      * <note><para>Argument @user_data is ignored in this function.</para>
483      * </note>
484      */
485     panel_signals[REGISTER_PROPERTIES] =
486         g_signal_new (I_("register-properties"),
487             G_TYPE_FROM_CLASS (gobject_class),
488             G_SIGNAL_RUN_LAST,
489             G_STRUCT_OFFSET (IBusPanelServiceClass, register_properties),
490             NULL, NULL,
491             _ibus_marshal_VOID__OBJECT,
492             G_TYPE_NONE,
493             1,
494             IBUS_TYPE_PROP_LIST);
495 
496     /**
497      * IBusPanelService::update-property:
498      * @panel: An #IBusPanelService
499      * @prop: The IBusProperty to be updated.
500      *
501      * Emitted when the client application get the ::update-property.
502      * Implement the member function
503      * IBusPanelServiceClass::update_property in extended class to
504      * receive this signal.
505      *
506      * <note><para>Argument @user_data is ignored in this function.</para>
507      * </note>
508      */
509     panel_signals[UPDATE_PROPERTY] =
510         g_signal_new (I_("update-property"),
511             G_TYPE_FROM_CLASS (gobject_class),
512             G_SIGNAL_RUN_LAST,
513             G_STRUCT_OFFSET (IBusPanelServiceClass, update_property),
514             NULL, NULL,
515             _ibus_marshal_VOID__OBJECT,
516             G_TYPE_NONE,
517             1,
518             IBUS_TYPE_PROPERTY);
519 
520     /**
521      * IBusPanelService::set-cursor-location:
522      * @panel: An #IBusPanelService
523      * @x: X coordinate of the cursor.
524      * @y: Y coordinate of the cursor.
525      * @w: Width of the cursor.
526      * @h: Height of the cursor.
527      *
528      * Emitted when the client application get the ::set-cursor-location.
529      * Implement the member function
530      * IBusPanelServiceClass::set_cursor_location in extended class
531      * to receive this signal.
532      *
533      * <note><para>Argument @user_data is ignored in this function.</para>
534      * </note>
535      */
536     panel_signals[SET_CURSOR_LOCATION] =
537         g_signal_new (I_("set-cursor-location"),
538             G_TYPE_FROM_CLASS (gobject_class),
539             G_SIGNAL_RUN_LAST,
540             G_STRUCT_OFFSET (IBusPanelServiceClass, set_cursor_location),
541             NULL, NULL,
542             _ibus_marshal_VOID__INT_INT_INT_INT,
543             G_TYPE_NONE,
544             4,
545             G_TYPE_INT,
546             G_TYPE_INT,
547             G_TYPE_INT,
548             G_TYPE_INT);
549 
550     /**
551      * IBusPanelService::set-cursor-location-relative:
552      * @panel: An #IBusPanelService
553      * @x: X coordinate of the cursor.
554      * @y: Y coordinate of the cursor.
555      * @w: Width of the cursor.
556      * @h: Height of the cursor.
557      *
558      * Emitted when the client application get the set-cursor-location-relative.
559      * Implement the member function set_cursor_location_relative() in
560      * extended class to receive this signal.
561      *
562      * <note><para>Argument @user_data is ignored in this function.</para>
563      * </note>
564      */
565     panel_signals[SET_CURSOR_LOCATION_RELATIVE] =
566         g_signal_new (I_("set-cursor-location-relative"),
567             G_TYPE_FROM_CLASS (gobject_class),
568             G_SIGNAL_RUN_LAST,
569             G_STRUCT_OFFSET (IBusPanelServiceClass, set_cursor_location_relative),
570             NULL, NULL,
571             _ibus_marshal_VOID__INT_INT_INT_INT,
572             G_TYPE_NONE,
573             4,
574             G_TYPE_INT,
575             G_TYPE_INT,
576             G_TYPE_INT,
577             G_TYPE_INT);
578 
579     /**
580      * IBusPanelService::cursor-up-lookup-table:
581      * @panel: An #IBusPanelService
582      *
583      * Emitted when the client application get the ::cursor-up-lookup-table.
584      * Implement the member function
585      * IBusPanelServiceClass::cursor_up_lookup_table in extended
586      * class to receive this signal.
587      *
588      * <note><para>Argument @user_data is ignored in this function.</para>
589      * </note>
590      */
591     panel_signals[CURSOR_UP_LOOKUP_TABLE] =
592         g_signal_new (I_("cursor-up-lookup-table"),
593             G_TYPE_FROM_CLASS (gobject_class),
594             G_SIGNAL_RUN_LAST,
595             G_STRUCT_OFFSET (IBusPanelServiceClass, cursor_up_lookup_table),
596             NULL, NULL,
597             _ibus_marshal_VOID__VOID,
598             G_TYPE_NONE, 0);
599 
600     /**
601      * IBusPanelService::cursor-down-lookup-table:
602      * @panel: An #IBusPanelService
603      *
604      * Emitted when the client application get the ::cursor-down-lookup-table.
605      * Implement the member function
606      * IBusPanelServiceClass::cursor_down_lookup_table in extended
607      * class to receive this signal.
608      *
609      * <note><para>Argument @user_data is ignored in this function.</para>
610      * </note>
611      */
612     panel_signals[CURSOR_DOWN_LOOKUP_TABLE] =
613         g_signal_new (I_("cursor-down-lookup-table"),
614             G_TYPE_FROM_CLASS (gobject_class),
615             G_SIGNAL_RUN_LAST,
616             G_STRUCT_OFFSET (IBusPanelServiceClass, cursor_down_lookup_table),
617             NULL, NULL,
618             _ibus_marshal_VOID__VOID,
619             G_TYPE_NONE, 0);
620 
621     /**
622      * IBusPanelService::hide-auxiliary-text:
623      * @panel: An #IBusPanelService
624      *
625      * Emitted when the client application get the ::hide-auxiliary-text.
626      * Implement the member function
627      * IBusPanelServiceClass::hide_auxiliary_text in extended class
628      * to receive this signal.
629      *
630      * <note><para>Argument @user_data is ignored in this function.</para>
631      * </note>
632      */
633     panel_signals[HIDE_AUXILIARY_TEXT] =
634         g_signal_new (I_("hide-auxiliary-text"),
635             G_TYPE_FROM_CLASS (gobject_class),
636             G_SIGNAL_RUN_LAST,
637             G_STRUCT_OFFSET (IBusPanelServiceClass, hide_auxiliary_text),
638             NULL, NULL,
639             _ibus_marshal_VOID__VOID,
640             G_TYPE_NONE, 0);
641 
642     /**
643      * IBusPanelService::hide-language-bar:
644      * @panel: An #IBusPanelService
645      *
646      * Emitted when the client application get the ::hide-language-bar.
647      * Implement the member function
648      * IBusPanelServiceClass::hide_language_bar in extended class to
649      * receive this signal.
650      *
651      * <note><para>Argument @user_data is ignored in this function.</para>
652      * </note>
653      */
654     panel_signals[HIDE_LANGUAGE_BAR] =
655         g_signal_new (I_("hide-language-bar"),
656             G_TYPE_FROM_CLASS (gobject_class),
657             G_SIGNAL_RUN_LAST,
658             G_STRUCT_OFFSET (IBusPanelServiceClass, hide_language_bar),
659             NULL, NULL,
660             _ibus_marshal_VOID__VOID,
661             G_TYPE_NONE, 0);
662 
663     /**
664      * IBusPanelService::hide-lookup-table:
665      * @panel: An #IBusPanelService
666      *
667      * Emitted when the client application get the ::hide-lookup-table.
668      * Implement the member function
669      * IBusPanelServiceClass::hide_lookup_table in extended class to
670      * receive this signal.
671      *
672      * <note><para>Argument @user_data is ignored in this function.</para>
673      * </note>
674      */
675     panel_signals[HIDE_LOOKUP_TABLE] =
676         g_signal_new (I_("hide-lookup-table"),
677             G_TYPE_FROM_CLASS (gobject_class),
678             G_SIGNAL_RUN_LAST,
679             G_STRUCT_OFFSET (IBusPanelServiceClass, hide_lookup_table),
680             NULL, NULL,
681             _ibus_marshal_VOID__VOID,
682             G_TYPE_NONE, 0);
683 
684     /**
685      * IBusPanelService::hide-preedit-text:
686      * @panel: An #IBusPanelService
687      *
688      * Emitted when the client application get the ::hide-preedit-text.
689      * Implement the member function
690      * IBusPanelServiceClass::hide_preedit_text in extended class to
691      * receive this signal.
692      *
693      * <note><para>Argument @user_data is ignored in this function.</para>
694      * </note>
695      */
696     panel_signals[HIDE_PREEDIT_TEXT] =
697         g_signal_new (I_("hide-preedit-text"),
698             G_TYPE_FROM_CLASS (gobject_class),
699             G_SIGNAL_RUN_LAST,
700             G_STRUCT_OFFSET (IBusPanelServiceClass, hide_preedit_text),
701             NULL, NULL,
702             _ibus_marshal_VOID__VOID,
703             G_TYPE_NONE, 0);
704 
705     /**
706      * IBusPanelService::page-up-lookup-table:
707      * @panel: An #IBusPanelService
708      *
709      * Emitted when the client application get the ::page-up-lookup-table.
710      * Implement the member function
711      * IBusPanelServiceClass::page_up_lookup_table in extended class
712      * to receive this signal.
713      *
714      * <note><para>Argument @user_data is ignored in this function.</para>
715      * </note>
716      */
717     panel_signals[PAGE_UP_LOOKUP_TABLE] =
718         g_signal_new (I_("page-up-lookup-table"),
719             G_TYPE_FROM_CLASS (gobject_class),
720             G_SIGNAL_RUN_LAST,
721             G_STRUCT_OFFSET (IBusPanelServiceClass, page_up_lookup_table),
722             NULL, NULL,
723             _ibus_marshal_VOID__VOID,
724             G_TYPE_NONE, 0);
725 
726     /**
727      * IBusPanelService::page-down-lookup-table:
728      * @panel: An #IBusPanelService
729      *
730      * Emitted when the client application get the ::page-down-lookup-table.
731      * Implement the member function
732      * IBusPanelServiceClass::page_down_lookup_table in extended
733      * class to receive this signal.
734      *
735      * <note><para>Argument @user_data is ignored in this function.</para>
736      * </note>
737      */
738     panel_signals[PAGE_DOWN_LOOKUP_TABLE] =
739         g_signal_new (I_("page-down-lookup-table"),
740             G_TYPE_FROM_CLASS (gobject_class),
741             G_SIGNAL_RUN_LAST,
742             G_STRUCT_OFFSET (IBusPanelServiceClass, page_down_lookup_table),
743             NULL, NULL,
744             _ibus_marshal_VOID__VOID,
745             G_TYPE_NONE, 0);
746 
747     /**
748      * IBusPanelService::reset:
749      * @panel: An #IBusPanelService
750      *
751      * Emitted when the client application get the ::reset.
752      * Implement the member function
753      * IBusPanelServiceClass::reset in extended class to receive this
754      * signal.
755      *
756      * <note><para>Argument @user_data is ignored in this function.</para>
757      * </note>
758      */
759     panel_signals[RESET] =
760         g_signal_new (I_("reset"),
761             G_TYPE_FROM_CLASS (gobject_class),
762             G_SIGNAL_RUN_LAST,
763             G_STRUCT_OFFSET (IBusPanelServiceClass, reset),
764             NULL, NULL,
765             _ibus_marshal_VOID__VOID,
766             G_TYPE_NONE, 0);
767 
768     /**
769      * IBusPanelService::show-auxiliary-text:
770      * @panel: An #IBusPanelService
771      *
772      * Emitted when the client application get the ::show-auxiliary-text.
773      * Implement the member function
774      * IBusPanelServiceClass::show_auxiliary_text in extended class
775      * to receive this signal.
776      *
777      * <note><para>Argument @user_data is ignored in this function.</para>
778      * </note>
779      */
780     panel_signals[SHOW_AUXILIARY_TEXT] =
781         g_signal_new (I_("show-auxiliary-text"),
782             G_TYPE_FROM_CLASS (gobject_class),
783             G_SIGNAL_RUN_LAST,
784             G_STRUCT_OFFSET (IBusPanelServiceClass, show_auxiliary_text),
785             NULL, NULL,
786             _ibus_marshal_VOID__VOID,
787             G_TYPE_NONE, 0);
788 
789     /**
790      * IBusPanelService::show-language-bar:
791      * @panel: An #IBusPanelService
792      *
793      * Emitted when the client application get the ::show-language-bar.
794      * Implement the member function
795      * IBusPanelServiceClass::show_language_bar in extended class to
796      * receive this signal.
797      *
798      * <note><para>Argument @user_data is ignored in this function.</para>
799      * </note>
800      */
801     panel_signals[SHOW_LANGUAGE_BAR] =
802         g_signal_new (I_("show-language-bar"),
803             G_TYPE_FROM_CLASS (gobject_class),
804             G_SIGNAL_RUN_LAST,
805             G_STRUCT_OFFSET (IBusPanelServiceClass, show_language_bar),
806             NULL, NULL,
807             _ibus_marshal_VOID__VOID,
808             G_TYPE_NONE, 0);
809 
810     /**
811      * IBusPanelService::show-lookup-table:
812      * @panel: An #IBusPanelService
813      *
814      * Emitted when the client application get the ::show-lookup-table.
815      * Implement the member function
816      * IBusPanelServiceClass::show_lookup_table in extended class to
817      * receive this signal.
818      *
819      * <note><para>Argument @user_data is ignored in this function.</para>
820      * </note>
821      */
822     panel_signals[SHOW_LOOKUP_TABLE] =
823         g_signal_new (I_("show-lookup-table"),
824             G_TYPE_FROM_CLASS (gobject_class),
825             G_SIGNAL_RUN_LAST,
826             G_STRUCT_OFFSET (IBusPanelServiceClass, show_lookup_table),
827             NULL, NULL,
828             _ibus_marshal_VOID__VOID,
829             G_TYPE_NONE, 0);
830 
831     /**
832      * IBusPanelService::show-preedit-text:
833      * @panel: An #IBusPanelService
834      *
835      * Emitted when the client application get the ::show-preedit-text.
836      * Implement the member function
837      * IBusPanelServiceClass::show_preedit_text in extended class to
838      * receive this signal.
839      *
840      * <note><para>Argument @user_data is ignored in this function.</para>
841      * </note>
842      */
843     panel_signals[SHOW_PREEDIT_TEXT] =
844         g_signal_new (I_("show-preedit-text"),
845             G_TYPE_FROM_CLASS (gobject_class),
846             G_SIGNAL_RUN_LAST,
847             G_STRUCT_OFFSET (IBusPanelServiceClass, show_preedit_text),
848             NULL, NULL,
849             _ibus_marshal_VOID__VOID,
850             G_TYPE_NONE, 0);
851 
852     /**
853      * IBusPanelService::start-setup:
854      * @panel: An #IBusPanelService
855      *
856      * Emitted when the client application get the ::start-setup.
857      * Implement the member function
858      * IBusPanelServiceClass::start_setup in extended class to
859      * receive this signal.
860      *
861      * <note><para>Argument @user_data is ignored in this function.</para>
862      * </note>
863      */
864     panel_signals[START_SETUP] =
865         g_signal_new (I_("start-setup"),
866             G_TYPE_FROM_CLASS (gobject_class),
867             G_SIGNAL_RUN_LAST,
868             G_STRUCT_OFFSET (IBusPanelServiceClass, start_setup),
869             NULL, NULL,
870             _ibus_marshal_VOID__VOID,
871             G_TYPE_NONE, 0);
872 
873     /**
874      * IBusPanelService::state-changed:
875      * @panel: An #IBusPanelService
876      *
877      * Emitted when the client application get the ::state-changed.
878      * Implement the member function
879      * IBusPanelServiceClass::state_changed in extended class to
880      * receive this signal.
881      *
882      * <note><para>Argument @user_data is ignored in this function.</para>
883      * </note>
884      */
885     panel_signals[STATE_CHANGED] =
886         g_signal_new (I_("state-changed"),
887             G_TYPE_FROM_CLASS (gobject_class),
888             G_SIGNAL_RUN_LAST,
889             G_STRUCT_OFFSET (IBusPanelServiceClass, state_changed),
890             NULL, NULL,
891             _ibus_marshal_VOID__VOID,
892             G_TYPE_NONE, 0);
893 
894     /**
895      * IBusPanelService::destroy-context:
896      * @panel: An #IBusPanelService
897      * @input_context_path: Object path of InputContext.
898      *
899      * Emitted when the client application destroys.
900      * Implement the member function
901      * IBusPanelServiceClass::destroy_context in extended class to
902      * receive this signal.
903      *
904      * <note><para>Argument @user_data is ignored in this function.</para>
905      * </note>
906      */
907     panel_signals[DESTROY_CONTEXT] =
908         g_signal_new (I_("destroy-context"),
909             G_TYPE_FROM_CLASS (gobject_class),
910             G_SIGNAL_RUN_LAST,
911             G_STRUCT_OFFSET (IBusPanelServiceClass, destroy_context),
912             NULL, NULL,
913             _ibus_marshal_VOID__STRING,
914             G_TYPE_NONE,
915             1,
916             G_TYPE_STRING);
917 
918     /**
919      * IBusPanelService::set-content-type:
920      * @panel: An #IBusPanelService
921      * @purpose: Input purpose.
922      * @hints: Input hints.
923      *
924      * Emitted when the client application get the ::set-content-type.
925      * Implement the member function
926      * IBusPanelServiceClass::set_content_type in extended class to
927      * receive this signal.
928      *
929      * <note><para>Argument @user_data is ignored in this function.</para>
930      * </note>
931      */
932     panel_signals[SET_CONTENT_TYPE] =
933         g_signal_new (I_("set-content-type"),
934             G_TYPE_FROM_CLASS (gobject_class),
935             G_SIGNAL_RUN_LAST,
936             G_STRUCT_OFFSET (IBusPanelServiceClass, set_content_type),
937             NULL, NULL,
938             _ibus_marshal_VOID__UINT_UINT,
939             G_TYPE_NONE,
940             2,
941             G_TYPE_UINT,
942             G_TYPE_UINT);
943 
944     /**
945      * IBusPanelService::panel-extension-received:
946      * @panel: An #IBusPanelService
947      * @data: A #GVariant
948      *
949      * Emitted when the client application get the ::panel-extension-received.
950      * Implement the member function
951      * IBusPanelServiceClass::panel_extension_received in extended class to
952      * receive this signal.
953      *
954      * <note><para>Argument @user_data is ignored in this function.</para>
955      * </note>
956      */
957     panel_signals[PANEL_EXTENSION_RECEIVED] =
958         g_signal_new (I_("panel-extension-received"),
959             G_TYPE_FROM_CLASS (gobject_class),
960             G_SIGNAL_RUN_LAST,
961             G_STRUCT_OFFSET (IBusPanelServiceClass, panel_extension_received),
962             NULL, NULL,
963             _ibus_marshal_VOID__OBJECT,
964             G_TYPE_NONE,
965             1,
966             IBUS_TYPE_EXTENSION_EVENT);
967 
968     /**
969      * IBusPanelService::process-key-event:
970      * @panel: An #IBusPanelService
971      * @keyval: Key symbol of the key press.
972      * @keycode: KeyCode of the key press.
973      * @state: Key modifier flags.
974      *
975      * Emitted when a key event is received.
976      * Implement the member function IBusPanelServiceClass::process_key_event
977      * in extended class to receive this signal.
978      * Both the key symbol and keycode are passed to the member function.
979      * See ibus_input_context_process_key_event() for further explanation of
980      * key symbol, keycode and which to use.
981      *
982      * Returns: %TRUE for successfully process the key; %FALSE otherwise.
983      * See also:  ibus_input_context_process_key_event().
984      *
985      * <note><para>Argument @user_data is ignored in this function.</para>
986      * </note>
987      */
988     panel_signals[PROCESS_KEY_EVENT] =
989         g_signal_new (I_("process-key-event"),
990             G_TYPE_FROM_CLASS (gobject_class),
991             G_SIGNAL_RUN_LAST,
992             G_STRUCT_OFFSET (IBusPanelServiceClass, process_key_event),
993             g_signal_accumulator_true_handled, NULL,
994             _ibus_marshal_BOOLEAN__UINT_UINT_UINT,
995             G_TYPE_BOOLEAN,
996             3,
997             G_TYPE_UINT,
998             G_TYPE_UINT,
999             G_TYPE_UINT);
1000 
1001     /**
1002      * IBusPanelService::commit-text-received:
1003      * @panel: An #IBusPanelService
1004      * @text: A #IBusText
1005      *
1006      * Emitted when the client application get the ::commit-text-received.
1007      * Implement the member function
1008      * IBusPanelServiceClass::commit_text_received in extended class to
1009      * receive this signal.
1010      *
1011      * <note><para>Argument @user_data is ignored in this function.</para>
1012      * </note>
1013      */
1014     panel_signals[COMMIT_TEXT_RECEIVED] =
1015         g_signal_new (I_("commit-text-received"),
1016             G_TYPE_FROM_CLASS (gobject_class),
1017             G_SIGNAL_RUN_LAST,
1018             G_STRUCT_OFFSET (IBusPanelServiceClass, commit_text_received),
1019             NULL, NULL,
1020             _ibus_marshal_VOID__OBJECT,
1021             G_TYPE_NONE,
1022             1,
1023             IBUS_TYPE_TEXT);
1024 
1025     panel_signals[CANDIDATE_CLICKED_LOOKUP_TABLE] =
1026         g_signal_new (I_("candidate-clicked-lookup-table"),
1027             G_TYPE_FROM_CLASS (gobject_class),
1028             G_SIGNAL_RUN_LAST,
1029             G_STRUCT_OFFSET (IBusPanelServiceClass,
1030                              candidate_clicked_lookup_table),
1031             NULL, NULL,
1032             _ibus_marshal_VOID__UINT_UINT_UINT,
1033             G_TYPE_NONE,
1034             3,
1035             G_TYPE_UINT,
1036             G_TYPE_UINT,
1037             G_TYPE_UINT);
1038 }
1039 
1040 static void
ibus_panel_service_init(IBusPanelService * panel)1041 ibus_panel_service_init (IBusPanelService *panel)
1042 {
1043 }
1044 
1045 static void
ibus_panel_service_set_property(IBusPanelService * panel,guint prop_id,const GValue * value,GParamSpec * pspec)1046 ibus_panel_service_set_property (IBusPanelService *panel,
1047                                  guint             prop_id,
1048                                  const GValue     *value,
1049                                  GParamSpec       *pspec)
1050 {
1051     switch (prop_id) {
1052     default:
1053         G_OBJECT_WARN_INVALID_PROPERTY_ID (panel, prop_id, pspec);
1054     }
1055 }
1056 
1057 static void
ibus_panel_service_get_property(IBusPanelService * panel,guint prop_id,GValue * value,GParamSpec * pspec)1058 ibus_panel_service_get_property (IBusPanelService *panel,
1059                                  guint             prop_id,
1060                                  GValue           *value,
1061                                  GParamSpec       *pspec)
1062 {
1063     switch (prop_id) {
1064     default:
1065         G_OBJECT_WARN_INVALID_PROPERTY_ID (panel, prop_id, pspec);
1066     }
1067 }
1068 
1069 static void
ibus_panel_service_real_destroy(IBusPanelService * panel)1070 ibus_panel_service_real_destroy (IBusPanelService *panel)
1071 {
1072     IBUS_OBJECT_CLASS(ibus_panel_service_parent_class)->destroy (IBUS_OBJECT (panel));
1073 }
1074 
1075 
1076 static void
_g_object_unref_if_floating(gpointer instance)1077 _g_object_unref_if_floating (gpointer instance)
1078 {
1079     if (g_object_is_floating (instance))
1080         g_object_unref (instance);
1081 }
1082 
1083 static gboolean
ibus_panel_service_service_authorized_method(IBusService * service,GDBusConnection * connection)1084 ibus_panel_service_service_authorized_method (IBusService     *service,
1085                                               GDBusConnection *connection)
1086 {
1087     if (ibus_service_get_connection (service) == connection)
1088         return TRUE;
1089     return FALSE;
1090 }
1091 
1092 static void
ibus_panel_service_service_method_call(IBusService * service,GDBusConnection * connection,const gchar * sender,const gchar * object_path,const gchar * interface_name,const gchar * method_name,GVariant * parameters,GDBusMethodInvocation * invocation)1093 ibus_panel_service_service_method_call (IBusService           *service,
1094                                         GDBusConnection       *connection,
1095                                         const gchar           *sender,
1096                                         const gchar           *object_path,
1097                                         const gchar           *interface_name,
1098                                         const gchar           *method_name,
1099                                         GVariant              *parameters,
1100                                         GDBusMethodInvocation *invocation)
1101 {
1102     IBusPanelService *panel = IBUS_PANEL_SERVICE (service);
1103 
1104     if (g_strcmp0 (interface_name, IBUS_INTERFACE_PANEL) != 0) {
1105         IBUS_SERVICE_CLASS (ibus_panel_service_parent_class)->
1106                 service_method_call (service,
1107                                      connection,
1108                                      sender,
1109                                      object_path,
1110                                      interface_name,
1111                                      method_name,
1112                                      parameters,
1113                                      invocation);
1114         return;
1115     }
1116 
1117     if (!ibus_panel_service_service_authorized_method (service, connection))
1118         return;
1119 
1120     if (g_strcmp0 (method_name, "UpdatePreeditText") == 0) {
1121         GVariant *variant = NULL;
1122         guint cursor = 0;
1123         gboolean visible = FALSE;
1124 
1125         g_variant_get (parameters, "(vub)", &variant, &cursor, &visible);
1126         IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant));
1127         g_variant_unref (variant);
1128 
1129         g_signal_emit (panel, panel_signals[UPDATE_PREEDIT_TEXT], 0, text, cursor, visible);
1130         _g_object_unref_if_floating (text);
1131         g_dbus_method_invocation_return_value (invocation, NULL);
1132         return;
1133     }
1134 
1135     if (g_strcmp0 (method_name, "UpdateAuxiliaryText") == 0) {
1136         GVariant *variant = NULL;
1137         gboolean visible = FALSE;
1138 
1139         g_variant_get (parameters, "(vb)", &variant, &visible);
1140         IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (variant));
1141         g_variant_unref (variant);
1142 
1143         g_signal_emit (panel, panel_signals[UPDATE_AUXILIARY_TEXT], 0, text, visible);
1144         _g_object_unref_if_floating (text);
1145         g_dbus_method_invocation_return_value (invocation, NULL);
1146         return;
1147     }
1148 
1149     if (g_strcmp0 (method_name, "UpdateLookupTable") == 0) {
1150         GVariant *variant = NULL;
1151         gboolean visible = FALSE;
1152 
1153         g_variant_get (parameters, "(vb)", &variant, &visible);
1154         IBusLookupTable *table = IBUS_LOOKUP_TABLE (ibus_serializable_deserialize (variant));
1155         g_variant_unref (variant);
1156 
1157         g_signal_emit (panel, panel_signals[UPDATE_LOOKUP_TABLE], 0, table, visible);
1158         _g_object_unref_if_floating (table);
1159         g_dbus_method_invocation_return_value (invocation, NULL);
1160         return;
1161     }
1162 
1163     if (g_strcmp0 (method_name, "FocusIn") == 0) {
1164         const gchar *path;
1165         g_variant_get (parameters, "(&o)", &path);
1166         g_signal_emit (panel, panel_signals[FOCUS_IN], 0, path);
1167         g_dbus_method_invocation_return_value (invocation, NULL);
1168         return;
1169     }
1170 
1171     if (g_strcmp0 (method_name, "FocusOut") == 0) {
1172         const gchar *path;
1173         g_variant_get (parameters, "(&o)", &path);
1174         g_signal_emit (panel, panel_signals[FOCUS_OUT], 0, path);
1175         g_dbus_method_invocation_return_value (invocation, NULL);
1176         return;
1177     }
1178 
1179     if (g_strcmp0 (method_name, "DestroyContext") == 0) {
1180         const gchar *path;
1181         g_variant_get (parameters, "(&o)", &path);
1182         g_signal_emit (panel, panel_signals[DESTROY_CONTEXT], 0, path);
1183         g_dbus_method_invocation_return_value (invocation, NULL);
1184         return;
1185     }
1186 
1187     if (g_strcmp0 (method_name, "RegisterProperties") == 0) {
1188         GVariant *variant = g_variant_get_child_value (parameters, 0);
1189         IBusPropList *prop_list = IBUS_PROP_LIST (ibus_serializable_deserialize (variant));
1190         g_variant_unref (variant);
1191 
1192         g_signal_emit (panel, panel_signals[REGISTER_PROPERTIES], 0, prop_list);
1193         _g_object_unref_if_floating (prop_list);
1194         g_dbus_method_invocation_return_value (invocation, NULL);
1195         return;
1196     }
1197 
1198     if (g_strcmp0 (method_name, "UpdateProperty") == 0) {
1199         GVariant *variant = g_variant_get_child_value (parameters, 0);
1200         IBusProperty *property = IBUS_PROPERTY (ibus_serializable_deserialize (variant));
1201         g_variant_unref (variant);
1202 
1203         g_signal_emit (panel, panel_signals[UPDATE_PROPERTY], 0, property);
1204         _g_object_unref_if_floating (property);
1205         g_dbus_method_invocation_return_value (invocation, NULL);
1206         return;
1207     }
1208 
1209     if (g_strcmp0 (method_name, "SetCursorLocation") == 0) {
1210         gint x, y, w, h;
1211         g_variant_get (parameters, "(iiii)", &x, &y, &w, &h);
1212         g_signal_emit (panel, panel_signals[SET_CURSOR_LOCATION], 0, x, y, w, h);
1213         g_dbus_method_invocation_return_value (invocation, NULL);
1214         return;
1215     }
1216 
1217     if (g_strcmp0 (method_name, "SetCursorLocationRelative") == 0) {
1218         gint x, y, w, h;
1219         g_variant_get (parameters, "(iiii)", &x, &y, &w, &h);
1220         g_signal_emit (panel, panel_signals[SET_CURSOR_LOCATION_RELATIVE],
1221                        0, x, y, w, h);
1222         g_dbus_method_invocation_return_value (invocation, NULL);
1223         return;
1224     }
1225 
1226     if (g_strcmp0 (method_name, "ContentType") == 0) {
1227         guint purpose, hints;
1228         g_variant_get (parameters, "(uu)", &purpose, &hints);
1229         g_signal_emit (panel, panel_signals[SET_CONTENT_TYPE], 0,
1230                        purpose, hints);
1231         g_dbus_method_invocation_return_value (invocation, NULL);
1232         return;
1233     }
1234 
1235     if (g_strcmp0 (method_name, "PanelExtensionReceived") == 0) {
1236         GVariant *arg0 = NULL;
1237         IBusExtensionEvent *event = NULL;
1238         g_variant_get (parameters, "(v)", &arg0);
1239         if (arg0) {
1240             event = IBUS_EXTENSION_EVENT (ibus_serializable_deserialize (arg0));
1241             g_variant_unref (arg0);
1242         }
1243         if (!event) {
1244             g_dbus_method_invocation_return_error (
1245                     invocation,
1246                     G_DBUS_ERROR,
1247                     G_DBUS_ERROR_FAILED,
1248                     "PanelExtensionReceived method gives NULL");
1249             return;
1250         }
1251         g_signal_emit (panel, panel_signals[PANEL_EXTENSION_RECEIVED], 0,
1252                        event);
1253         _g_object_unref_if_floating (event);
1254         g_dbus_method_invocation_return_value (invocation, NULL);
1255         return;
1256     }
1257     if (g_strcmp0 (method_name, "ProcessKeyEvent") == 0) {
1258         guint keyval, keycode, state;
1259         gboolean retval = FALSE;
1260 
1261         g_variant_get (parameters, "(uuu)", &keyval, &keycode, &state);
1262         g_signal_emit (panel,
1263                        panel_signals[PROCESS_KEY_EVENT],
1264                        0,
1265                        keyval,
1266                        keycode,
1267                        state,
1268                        &retval);
1269         g_dbus_method_invocation_return_value (invocation,
1270                                                g_variant_new ("(b)", retval));
1271         return;
1272     }
1273     if (g_strcmp0 (method_name, "CommitTextReceived") == 0) {
1274         GVariant *arg0 = NULL;
1275         IBusText *text = NULL;
1276 
1277         g_variant_get (parameters, "(v)", &arg0);
1278         if (arg0) {
1279             text = (IBusText *) ibus_serializable_deserialize (arg0);
1280             g_variant_unref (arg0);
1281         }
1282         if (!text) {
1283             g_dbus_method_invocation_return_error (
1284                     invocation,
1285                     G_DBUS_ERROR,
1286                     G_DBUS_ERROR_FAILED,
1287                     "CommitTextReceived method gives NULL");
1288             return;
1289         }
1290         g_signal_emit (panel,
1291                        panel_signals[COMMIT_TEXT_RECEIVED],
1292                        0,
1293                        text);
1294         _g_object_unref_if_floating (text);
1295         return;
1296     }
1297     if (g_strcmp0 (method_name, "CandidateClickedLookupTable") == 0) {
1298         guint index = 0;
1299         guint button = 0;
1300         guint state = 0;
1301         g_variant_get (parameters, "(uuu)", &index, &button, &state);
1302         g_signal_emit (panel,
1303                        panel_signals[CANDIDATE_CLICKED_LOOKUP_TABLE],
1304                        0,
1305                        index, button, state);
1306         return;
1307     }
1308 
1309 
1310     const static struct {
1311         const gchar *name;
1312         const gint signal_id;
1313     } no_arg_methods [] = {
1314         { "CursorUpLookupTable",   CURSOR_UP_LOOKUP_TABLE },
1315         { "CursorDownLookupTable", CURSOR_DOWN_LOOKUP_TABLE },
1316         { "HideAuxiliaryText",     HIDE_AUXILIARY_TEXT },
1317         { "HideLanguageBar",       HIDE_LANGUAGE_BAR },
1318         { "HideLookupTable",       HIDE_LOOKUP_TABLE },
1319         { "HidePreeditText",       HIDE_PREEDIT_TEXT },
1320         { "PageUpLookupTable",     PAGE_UP_LOOKUP_TABLE },
1321         { "PageDownLookupTable",   PAGE_DOWN_LOOKUP_TABLE },
1322         { "Reset",                 RESET },
1323         { "ShowAuxiliaryText",     SHOW_AUXILIARY_TEXT },
1324         { "ShowLanguageBar",       SHOW_LANGUAGE_BAR },
1325         { "ShowLookupTable",       SHOW_LOOKUP_TABLE },
1326         { "ShowPreeditText",       SHOW_PREEDIT_TEXT },
1327         { "StartSetup",            START_SETUP },
1328         { "StateChanged",          STATE_CHANGED },
1329     };
1330 
1331     gint i;
1332     for (i = 0; i < G_N_ELEMENTS (no_arg_methods); i++) {
1333         if (g_strcmp0 (method_name, no_arg_methods[i].name) == 0) {
1334             if (no_arg_methods[i].signal_id >= 0) {
1335                 g_signal_emit (panel, panel_signals[no_arg_methods[i].signal_id], 0);
1336             }
1337             g_dbus_method_invocation_return_value (invocation, NULL);
1338             return;
1339         }
1340     }
1341 
1342     /* should not be reached */
1343     g_return_if_reached ();
1344 }
1345 
1346 static GVariant *
ibus_panel_service_service_get_property(IBusService * service,GDBusConnection * connection,const gchar * sender,const gchar * object_path,const gchar * interface_name,const gchar * property_name,GError ** error)1347 ibus_panel_service_service_get_property (IBusService        *service,
1348                                          GDBusConnection    *connection,
1349                                          const gchar        *sender,
1350                                          const gchar        *object_path,
1351                                          const gchar        *interface_name,
1352                                          const gchar        *property_name,
1353                                          GError            **error)
1354 {
1355     return IBUS_SERVICE_CLASS (ibus_panel_service_parent_class)->
1356                 service_get_property (service,
1357                                       connection,
1358                                       sender,
1359                                       object_path,
1360                                       interface_name,
1361                                       property_name,
1362                                       error);
1363 }
1364 
1365 static gboolean
ibus_panel_service_service_set_property(IBusService * service,GDBusConnection * connection,const gchar * sender,const gchar * object_path,const gchar * interface_name,const gchar * property_name,GVariant * value,GError ** error)1366 ibus_panel_service_service_set_property (IBusService        *service,
1367                                          GDBusConnection    *connection,
1368                                          const gchar        *sender,
1369                                          const gchar        *object_path,
1370                                          const gchar        *interface_name,
1371                                          const gchar        *property_name,
1372                                          GVariant           *value,
1373                                          GError            **error)
1374 {
1375     return IBUS_SERVICE_CLASS (ibus_panel_service_parent_class)->
1376                 service_set_property (service,
1377                                       connection,
1378                                       sender,
1379                                       object_path,
1380                                       interface_name,
1381                                       property_name,
1382                                       value,
1383                                       error);
1384 }
1385 
1386 
1387 static void
ibus_panel_service_not_implemented(IBusPanelService * panel)1388 ibus_panel_service_not_implemented (IBusPanelService *panel)
1389 {
1390     /* g_debug ("not implemented"); */
1391 }
1392 
1393 static void
ibus_panel_service_focus_in(IBusPanelService * panel,const gchar * input_context_path)1394 ibus_panel_service_focus_in (IBusPanelService    *panel,
1395                              const gchar         *input_context_path)
1396 {
1397     ibus_panel_service_not_implemented(panel);
1398 }
1399 
1400 static void
ibus_panel_service_focus_out(IBusPanelService * panel,const gchar * input_context_path)1401 ibus_panel_service_focus_out (IBusPanelService    *panel,
1402                               const gchar         *input_context_path)
1403 {
1404     ibus_panel_service_not_implemented(panel);
1405 }
1406 
1407 static void
ibus_panel_service_destroy_context(IBusPanelService * panel,const gchar * input_context_path)1408 ibus_panel_service_destroy_context (IBusPanelService    *panel,
1409                                     const gchar         *input_context_path)
1410 {
1411     ibus_panel_service_not_implemented(panel);
1412 }
1413 
1414 static void
ibus_panel_service_register_properties(IBusPanelService * panel,IBusPropList * prop_list)1415 ibus_panel_service_register_properties (IBusPanelService *panel,
1416                                         IBusPropList     *prop_list)
1417 {
1418     ibus_panel_service_not_implemented(panel);
1419 }
1420 
1421 static void
ibus_panel_service_set_cursor_location(IBusPanelService * panel,gint x,gint y,gint w,gint h)1422 ibus_panel_service_set_cursor_location (IBusPanelService *panel,
1423                                         gint              x,
1424                                         gint              y,
1425                                         gint              w,
1426                                         gint              h)
1427 {
1428     ibus_panel_service_not_implemented(panel);
1429 }
1430 
1431 static void
ibus_panel_service_set_cursor_location_relative(IBusPanelService * panel,gint x,gint y,gint w,gint h)1432 ibus_panel_service_set_cursor_location_relative (IBusPanelService *panel,
1433                                                  gint              x,
1434                                                  gint              y,
1435                                                  gint              w,
1436                                                  gint              h)
1437 {
1438     ibus_panel_service_not_implemented(panel);
1439 }
1440 
1441 static void
ibus_panel_service_update_auxiliary_text(IBusPanelService * panel,IBusText * text,gboolean visible)1442 ibus_panel_service_update_auxiliary_text (IBusPanelService *panel,
1443                                           IBusText         *text,
1444                                           gboolean          visible)
1445 {
1446     ibus_panel_service_not_implemented(panel);
1447 }
1448 
1449 static void
ibus_panel_service_update_lookup_table(IBusPanelService * panel,IBusLookupTable * lookup_table,gboolean visible)1450 ibus_panel_service_update_lookup_table (IBusPanelService *panel,
1451                                         IBusLookupTable  *lookup_table,
1452                                         gboolean          visible)
1453 {
1454     ibus_panel_service_not_implemented(panel);
1455 }
1456 
1457 static void
ibus_panel_service_update_preedit_text(IBusPanelService * panel,IBusText * text,guint cursor_pos,gboolean visible)1458 ibus_panel_service_update_preedit_text (IBusPanelService *panel,
1459                                         IBusText         *text,
1460                                         guint             cursor_pos,
1461                                         gboolean          visible)
1462 {
1463     ibus_panel_service_not_implemented(panel);
1464 }
1465 
1466 static void
ibus_panel_service_update_property(IBusPanelService * panel,IBusProperty * prop)1467 ibus_panel_service_update_property (IBusPanelService *panel,
1468                                     IBusProperty     *prop)
1469 {
1470     ibus_panel_service_not_implemented(panel);
1471 }
1472 
1473 static void
ibus_panel_service_set_content_type(IBusPanelService * panel,guint purpose,guint hints)1474 ibus_panel_service_set_content_type (IBusPanelService *panel,
1475                                      guint             purpose,
1476                                      guint             hints)
1477 {
1478     ibus_panel_service_not_implemented(panel);
1479 }
1480 
1481 static void
ibus_panel_service_panel_extension_received(IBusPanelService * panel,IBusExtensionEvent * event)1482 ibus_panel_service_panel_extension_received (IBusPanelService   *panel,
1483                                              IBusExtensionEvent *event)
1484 {
1485     ibus_panel_service_not_implemented(panel);
1486 }
1487 
1488 IBusPanelService *
ibus_panel_service_new(GDBusConnection * connection)1489 ibus_panel_service_new (GDBusConnection *connection)
1490 {
1491     g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
1492 
1493     GObject *object = g_object_new (IBUS_TYPE_PANEL_SERVICE,
1494                                     "object-path", IBUS_PATH_PANEL,
1495                                     "connection", connection,
1496                                     NULL);
1497 
1498     return IBUS_PANEL_SERVICE (object);
1499 }
1500 
1501 void
ibus_panel_service_candidate_clicked(IBusPanelService * panel,guint index,guint button,guint state)1502 ibus_panel_service_candidate_clicked (IBusPanelService *panel,
1503                                       guint             index,
1504                                       guint             button,
1505                                       guint             state)
1506 {
1507     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1508     ibus_service_emit_signal ((IBusService *) panel,
1509                               NULL,
1510                               IBUS_INTERFACE_PANEL,
1511                               "CandidateClicked",
1512                               g_variant_new ("(uuu)", index, button, state),
1513                               NULL);
1514 }
1515 
1516 void
ibus_panel_service_property_activate(IBusPanelService * panel,const gchar * prop_name,guint prop_state)1517 ibus_panel_service_property_activate (IBusPanelService *panel,
1518                                       const gchar      *prop_name,
1519                                       guint             prop_state)
1520 {
1521     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1522     ibus_service_emit_signal ((IBusService *) panel,
1523                               NULL,
1524                               IBUS_INTERFACE_PANEL,
1525                               "PropertyActivate",
1526                               g_variant_new ("(su)", prop_name, prop_state),
1527                               NULL);
1528 }
1529 
1530 void
ibus_panel_service_property_show(IBusPanelService * panel,const gchar * prop_name)1531 ibus_panel_service_property_show (IBusPanelService *panel,
1532                                   const gchar      *prop_name)
1533 {
1534     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1535     ibus_service_emit_signal ((IBusService *) panel,
1536                               NULL,
1537                               IBUS_INTERFACE_PANEL,
1538                               "PropertyShow",
1539                               g_variant_new ("(s)", prop_name),
1540                               NULL);
1541 }
1542 
1543 void
ibus_panel_service_property_hide(IBusPanelService * panel,const gchar * prop_name)1544 ibus_panel_service_property_hide (IBusPanelService *panel,
1545                                   const gchar      *prop_name)
1546 {
1547     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1548     ibus_service_emit_signal ((IBusService *) panel,
1549                               NULL,
1550                               IBUS_INTERFACE_PANEL,
1551                               "PropertyHide",
1552                               g_variant_new ("(s)", prop_name),
1553                               NULL);
1554 }
1555 
1556 void
ibus_panel_service_commit_text(IBusPanelService * panel,IBusText * text)1557 ibus_panel_service_commit_text (IBusPanelService *panel,
1558                                 IBusText         *text)
1559 {
1560     GVariant *variant;
1561     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1562     g_return_if_fail (IBUS_IS_TEXT (text));
1563 
1564     variant = ibus_serializable_serialize ((IBusSerializable *)text);
1565     ibus_service_emit_signal ((IBusService *) panel,
1566                               NULL,
1567                               IBUS_INTERFACE_PANEL,
1568                               "CommitText",
1569                               g_variant_new ("(v)", variant),
1570                               NULL);
1571 
1572     if (g_object_is_floating (text)) {
1573         g_object_unref (text);
1574     }
1575 }
1576 
1577 void
ibus_panel_service_panel_extension(IBusPanelService * panel,IBusExtensionEvent * event)1578 ibus_panel_service_panel_extension (IBusPanelService   *panel,
1579                                     IBusExtensionEvent *event)
1580 {
1581     GVariant *variant;
1582     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1583     g_return_if_fail (IBUS_IS_EXTENSION_EVENT (event));
1584 
1585     variant = ibus_serializable_serialize ((IBusSerializable *)event);
1586     ibus_service_emit_signal ((IBusService *) panel,
1587                               NULL,
1588                               IBUS_INTERFACE_PANEL,
1589                               "PanelExtension",
1590                               g_variant_new ("(v)", variant),
1591                               NULL);
1592 
1593     if (g_object_is_floating (event)) {
1594         g_object_unref (event);
1595     }
1596 }
1597 
1598 void
ibus_panel_service_panel_extension_register_keys(IBusPanelService * panel,const gchar * first_property_name,...)1599 ibus_panel_service_panel_extension_register_keys (IBusPanelService   *panel,
1600                                                   const gchar
1601                                                            *first_property_name,
1602                                                   ...)
1603 {
1604     GVariantBuilder builder;
1605     GVariantBuilder child;
1606     const gchar *name;
1607     va_list var_args;
1608     IBusProcessKeyEventData *keys;
1609 
1610     g_return_if_fail (first_property_name);
1611 
1612     g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
1613     name = first_property_name;
1614 
1615     va_start (var_args, first_property_name);
1616     do {
1617         keys = va_arg (var_args, IBusProcessKeyEventData *);
1618         if (keys == NULL) {
1619             va_end (var_args);
1620             g_warning ("Failed to va_arg for IBusProcessKeyEventData");
1621             return;
1622         }
1623         g_variant_builder_init (&child, G_VARIANT_TYPE ("av"));
1624         for (; keys; keys++) {
1625             if (keys->keyval == 0 && keys->keycode == 0 && keys->state == 0)
1626                 break;
1627             g_variant_builder_add (&child, "v",
1628                                    g_variant_new ("(iii)",
1629                                                   keys->keyval,
1630                                                   keys->keycode,
1631                                                   keys->state));
1632         }
1633         g_variant_builder_add (&builder, "{sv}",
1634                                g_strdup (name), g_variant_builder_end (&child));
1635     } while ((name = va_arg (var_args, const gchar *)));
1636     va_end (var_args);
1637 
1638     ibus_service_emit_signal ((IBusService *) panel,
1639                               NULL,
1640                               IBUS_INTERFACE_PANEL,
1641                               "PanelExtensionRegisterKeys",
1642                               g_variant_new ("(v)",
1643                                              g_variant_builder_end (&builder)),
1644                               NULL);
1645 }
1646 
1647 void
ibus_panel_service_update_preedit_text_received(IBusPanelService * panel,IBusText * text,guint cursor_pos,gboolean visible)1648 ibus_panel_service_update_preedit_text_received (IBusPanelService *panel,
1649                                                  IBusText         *text,
1650                                                  guint             cursor_pos,
1651                                                  gboolean          visible)
1652 {
1653     GVariant *variant;
1654 
1655     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1656     g_return_if_fail (IBUS_IS_TEXT (text));
1657 
1658     variant = ibus_serializable_serialize ((IBusSerializable *)text);
1659     g_return_if_fail (variant);
1660     ibus_service_emit_signal ((IBusService *) panel,
1661                               NULL,
1662                               IBUS_INTERFACE_PANEL,
1663                               "UpdatePreeditTextReceived",
1664                               g_variant_new ("(vub)",
1665                                              variant, cursor_pos, visible),
1666                               NULL);
1667 
1668     if (g_object_is_floating (text)) {
1669         g_object_unref (text);
1670     }
1671 }
1672 
1673 void
ibus_panel_service_update_auxiliary_text_received(IBusPanelService * panel,IBusText * text,gboolean visible)1674 ibus_panel_service_update_auxiliary_text_received (IBusPanelService *panel,
1675                                                    IBusText         *text,
1676                                                    gboolean          visible)
1677 {
1678     GVariant *variant;
1679     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1680     g_return_if_fail (IBUS_IS_TEXT (text));
1681 
1682     variant = ibus_serializable_serialize ((IBusSerializable *)text);
1683     g_return_if_fail (variant);
1684     ibus_service_emit_signal ((IBusService *) panel,
1685                               NULL,
1686                               IBUS_INTERFACE_PANEL,
1687                               "UpdateAuxiliaryTextReceived",
1688                               g_variant_new ("(vb)",
1689                                              variant, visible),
1690                               NULL);
1691 
1692     if (g_object_is_floating (text)) {
1693         g_object_unref (text);
1694     }
1695 }
1696 
1697 void
ibus_panel_service_update_lookup_table_received(IBusPanelService * panel,IBusLookupTable * table,gboolean visible)1698 ibus_panel_service_update_lookup_table_received (IBusPanelService *panel,
1699                                                  IBusLookupTable  *table,
1700                                                  gboolean          visible)
1701 {
1702     GVariant *variant;
1703 
1704     g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
1705     g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table));
1706 
1707     variant = ibus_serializable_serialize ((IBusSerializable *)table);
1708     g_return_if_fail (variant);
1709     ibus_service_emit_signal ((IBusService *) panel,
1710                               NULL,
1711                               IBUS_INTERFACE_PANEL,
1712                               "UpdateLookupTableReceived",
1713                               g_variant_new ("(vb)",
1714                                              variant, visible),
1715                               NULL);
1716 
1717     if (g_object_is_floating (table)) {
1718         g_object_unref (table);
1719     }
1720 }
1721 
1722 #define DEFINE_FUNC(name, Name)                             \
1723     void                                                    \
1724     ibus_panel_service_##name (IBusPanelService *panel)     \
1725     {                                                       \
1726         g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));   \
1727         ibus_service_emit_signal ((IBusService *) panel,    \
1728                                   NULL,                     \
1729                                   IBUS_INTERFACE_PANEL,     \
1730                                   #Name,                    \
1731                                   NULL,                     \
1732                                   NULL);                    \
1733     }
1734 DEFINE_FUNC (cursor_down, CursorDown)
1735 DEFINE_FUNC (cursor_up, CursorUp)
1736 DEFINE_FUNC (page_down, PageDown)
1737 DEFINE_FUNC (page_up, PageUp)
1738 #undef DEFINE_FUNC
1739