123
215
static void _engine_destroy_cb (BusEngineProxy *factory,
124
216
BusInputContext *context);
127
218
static IBusText *text_empty = NULL;
128
219
static IBusLookupTable *lookup_table_empty = NULL;
129
220
static IBusPropList *props_empty = NULL;
222
/* The interfaces available in this class, which consists of a list of methods this class implements and
223
* a list of signals this class may emit. Method calls to the interface that are not defined in this XML
224
* will be automatically rejected by the GDBus library (see src/ibusservice.c for details.) */
225
static const gchar introspection_xml[] =
227
" <interface name='org.freedesktop.IBus.InputContext'>"
229
" <method name='ProcessKeyEvent'>"
230
" <arg direction='in' type='u' name='keyval' />"
231
" <arg direction='in' type='u' name='keycode' />"
232
" <arg direction='in' type='u' name='state' />"
233
" <arg direction='out' type='b' name='handled' />"
235
" <method name='SetCursorLocation'>"
236
" <arg direction='in' type='i' name='x' />"
237
" <arg direction='in' type='i' name='y' />"
238
" <arg direction='in' type='i' name='w' />"
239
" <arg direction='in' type='i' name='h' />"
241
" <method name='FocusIn' />"
242
" <method name='FocusOut' />"
243
" <method name='Reset' />"
244
" <method name='Enable' />"
245
" <method name='Disable' />"
246
" <method name='IsEnabled'>"
247
" <arg direction='out' type='b' name='enable' />"
249
" <method name='SetCapabilities'>"
250
" <arg direction='in' type='u' name='caps' />"
252
" <method name='PropertyActivate'>"
253
" <arg direction='in' type='s' name='name' />"
254
" <arg direction='in' type='u' name='state' />"
256
" <method name='SetEngine'>"
257
" <arg direction='in' type='s' name='name' />"
259
" <method name='GetEngine'>"
260
" <arg direction='out' type='v' name='desc' />"
262
" <method name='SetSurroundingText'>"
263
" <arg direction='in' type='v' name='text' />"
264
" <arg direction='in' type='u' name='cursor_pos' />"
268
" <signal name='CommitText'>"
269
" <arg type='v' name='text' />"
271
" <signal name='Enabled'/>"
272
" <signal name='Disabled'/>"
273
" <signal name='ForwardKeyEvent'>"
274
" <arg type='u' name='keyval' />"
275
" <arg type='u' name='keycode' />"
276
" <arg type='u' name='state' />"
278
" <signal name='UpdatePreeditText'>"
279
" <arg type='v' name='text' />"
280
" <arg type='u' name='cursor_pos' />"
281
" <arg type='b' name='visible' />"
283
" <signal name='ShowPreeditText'/>"
284
" <signal name='HidePreeditText'/>"
285
" <signal name='UpdateAuxiliaryText'>"
286
" <arg type='v' name='text' />"
287
" <arg type='b' name='visible' />"
289
" <signal name='ShowAuxiliaryText'/>"
290
" <signal name='HideAuxiliaryText'/>"
291
" <signal name='UpdateLookupTable'>"
292
" <arg type='v' name='table' />"
293
" <arg type='b' name='visible' />"
295
" <signal name='ShowLookupTable'/>"
296
" <signal name='HideLookupTable'/>"
297
" <signal name='PageUpLookupTable'/>"
298
" <signal name='PageDownLookupTable'/>"
299
" <signal name='CursorUpLookupTable'/>"
300
" <signal name='CursorDownLookupTable'/>"
301
" <signal name='RegisterProperties'>"
302
" <arg type='v' name='props' />"
304
" <signal name='UpdateProperty'>"
305
" <arg type='v' name='prop' />"
131
310
G_DEFINE_TYPE (BusInputContext, bus_input_context, IBUS_TYPE_SERVICE)
133
/* when send preedit to client */
312
/* TRUE if we can send preedit text to client. FALSE if the panel has to handle it. Note that we check IBUS_CAP_FOCUS here since
313
* when the capability is not set, the client has to handle a preedit text regardless of the embed_preedit_text config. */
134
314
#define PREEDIT_CONDITION \
135
315
((context->capabilities & IBUS_CAP_PREEDIT_TEXT) && \
136
(BUS_DEFAULT_IBUS->embed_preedit_text || (context->capabilities & IBUS_CAP_FOCUS) == 0))
316
(bus_ibus_impl_is_embed_preedit_text (BUS_DEFAULT_IBUS) || (context->capabilities & IBUS_CAP_FOCUS) == 0))
139
319
_connection_destroy_cb (BusConnection *connection,
140
320
BusInputContext *context)
142
BUS_IS_CONNECTION (connection);
143
BUS_IS_INPUT_CONTEXT (context);
322
g_assert (BUS_IS_CONNECTION (connection));
323
g_assert (BUS_IS_INPUT_CONTEXT (context));
145
325
ibus_object_destroy (IBUS_OBJECT (context));
150
bus_input_context_new (BusConnection *connection,
153
g_assert (BUS_IS_CONNECTION (connection));
154
g_assert (client != NULL);
156
BusInputContext *context;
159
path = g_strdup_printf (IBUS_PATH_INPUT_CONTEXT, ++id);
161
context = (BusInputContext *) g_object_new (BUS_TYPE_INPUT_CONTEXT,
167
ibus_service_add_to_connection (IBUS_SERVICE (context),
168
IBUS_CONNECTION (connection));
171
g_object_ref_sink (connection);
172
context->connection = connection;
173
context->client = g_strdup (client);
175
/* it is a fake input context, just need process hotkey */
176
context->fake = (g_strcmp0 (client, "fake") == 0);
178
g_signal_connect (context->connection,
180
(GCallback) _connection_destroy_cb,
187
bus_input_context_class_init (BusInputContextClass *klass)
329
bus_input_context_class_init (BusInputContextClass *class)
189
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
331
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
191
333
ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_input_context_destroy;
193
IBUS_SERVICE_CLASS (klass)->ibus_message =
194
(ServiceIBusMessageFunc) bus_input_context_ibus_message;
335
/* override the parent class's implementation. */
336
IBUS_SERVICE_CLASS (class)->service_method_call = bus_input_context_service_method_call;
337
/* register the xml so that bus_ibus_impl_service_method_call will be called on a method call defined in the xml (e.g. 'FocusIn'.) */
338
ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
196
/* install signals */
340
/* install glib signals that would be handled by other classes like ibusimpl.c and panelproxy.c. */
197
341
context_signals[PROCESS_KEY_EVENT] =
198
342
g_signal_new (I_("process-key-event"),
199
G_TYPE_FROM_CLASS (klass),
343
G_TYPE_FROM_CLASS (class),
200
344
G_SIGNAL_RUN_LAST,
203
ibus_marshal_BOOL__UINT_UINT,
347
bus_marshal_BOOL__UINT_UINT_UINT,
209
354
context_signals[SET_CURSOR_LOCATION] =
210
355
g_signal_new (I_("set-cursor-location"),
211
G_TYPE_FROM_CLASS (klass),
356
G_TYPE_FROM_CLASS (class),
212
357
G_SIGNAL_RUN_LAST,
215
ibus_marshal_VOID__INT_INT_INT_INT,
360
bus_marshal_VOID__INT_INT_INT_INT,
318
463
context_signals[SHOW_LOOKUP_TABLE] =
319
464
g_signal_new (I_("show-lookup-table"),
320
G_TYPE_FROM_CLASS (klass),
465
G_TYPE_FROM_CLASS (class),
321
466
G_SIGNAL_RUN_LAST,
324
ibus_marshal_VOID__VOID,
469
bus_marshal_VOID__VOID,
327
472
context_signals[HIDE_LOOKUP_TABLE] =
328
473
g_signal_new (I_("hide-lookup-table"),
329
G_TYPE_FROM_CLASS (klass),
474
G_TYPE_FROM_CLASS (class),
330
475
G_SIGNAL_RUN_LAST,
333
ibus_marshal_VOID__VOID,
478
bus_marshal_VOID__VOID,
336
481
context_signals[PAGE_UP_LOOKUP_TABLE] =
337
482
g_signal_new (I_("page-up-lookup-table"),
338
G_TYPE_FROM_CLASS (klass),
483
G_TYPE_FROM_CLASS (class),
339
484
G_SIGNAL_RUN_LAST,
342
ibus_marshal_VOID__VOID,
487
bus_marshal_VOID__VOID,
345
490
context_signals[PAGE_DOWN_LOOKUP_TABLE] =
346
491
g_signal_new (I_("page-down-lookup-table"),
347
G_TYPE_FROM_CLASS (klass),
492
G_TYPE_FROM_CLASS (class),
348
493
G_SIGNAL_RUN_LAST,
351
ibus_marshal_VOID__VOID,
496
bus_marshal_VOID__VOID,
354
499
context_signals[CURSOR_UP_LOOKUP_TABLE] =
355
500
g_signal_new (I_("cursor-up-lookup-table"),
356
G_TYPE_FROM_CLASS (klass),
501
G_TYPE_FROM_CLASS (class),
357
502
G_SIGNAL_RUN_LAST,
360
ibus_marshal_VOID__VOID,
505
bus_marshal_VOID__VOID,
363
508
context_signals[CURSOR_DOWN_LOOKUP_TABLE] =
364
509
g_signal_new (I_("cursor-down-lookup-table"),
365
G_TYPE_FROM_CLASS (klass),
510
G_TYPE_FROM_CLASS (class),
366
511
G_SIGNAL_RUN_LAST,
369
ibus_marshal_VOID__VOID,
514
bus_marshal_VOID__VOID,
372
517
context_signals[REGISTER_PROPERTIES] =
373
518
g_signal_new (I_("register-properties"),
374
G_TYPE_FROM_CLASS (klass),
519
G_TYPE_FROM_CLASS (class),
375
520
G_SIGNAL_RUN_LAST,
378
ibus_marshal_VOID__OBJECT,
523
bus_marshal_VOID__OBJECT,
381
526
IBUS_TYPE_PROP_LIST);
383
528
context_signals[UPDATE_PROPERTY] =
384
529
g_signal_new (I_("update-property"),
385
G_TYPE_FROM_CLASS (klass),
530
G_TYPE_FROM_CLASS (class),
386
531
G_SIGNAL_RUN_LAST,
389
ibus_marshal_VOID__OBJECT,
534
bus_marshal_VOID__OBJECT,
392
537
IBUS_TYPE_PROPERTY);
394
539
context_signals[ENABLED] =
395
540
g_signal_new (I_("enabled"),
396
G_TYPE_FROM_CLASS (klass),
541
G_TYPE_FROM_CLASS (class),
397
542
G_SIGNAL_RUN_LAST,
400
ibus_marshal_VOID__VOID,
545
bus_marshal_VOID__VOID,
404
549
context_signals[DISABLED] =
405
550
g_signal_new (I_("disabled"),
406
G_TYPE_FROM_CLASS (klass),
551
G_TYPE_FROM_CLASS (class),
407
552
G_SIGNAL_RUN_LAST,
410
ibus_marshal_VOID__VOID,
555
bus_marshal_VOID__VOID,
414
559
context_signals[ENGINE_CHANGED] =
415
560
g_signal_new (I_("engine-changed"),
416
G_TYPE_FROM_CLASS (klass),
561
G_TYPE_FROM_CLASS (class),
417
562
G_SIGNAL_RUN_LAST,
420
ibus_marshal_VOID__VOID,
565
bus_marshal_VOID__VOID,
569
/* This signal is not for notifying an event on this object, but is for requesting an engine as the name shows.
570
* On the signal emission, ibusimpl.c will immediately update the context->engine variable. */
424
571
context_signals[REQUEST_ENGINE] =
425
572
g_signal_new (I_("request-engine"),
426
G_TYPE_FROM_CLASS (klass),
573
G_TYPE_FROM_CLASS (class),
427
574
G_SIGNAL_RUN_LAST,
430
ibus_marshal_VOID__STRING,
577
bus_marshal_OBJECT__STRING,
578
IBUS_TYPE_ENGINE_DESC,
435
582
text_empty = ibus_text_new_from_string ("");
436
583
g_object_ref_sink (text_empty);
437
lookup_table_empty = ibus_lookup_table_new (9, 0, FALSE, FALSE);
584
lookup_table_empty = ibus_lookup_table_new (9 /* page size */, 0, FALSE, FALSE);
438
585
g_object_ref_sink (lookup_table_empty);
439
586
props_empty = ibus_prop_list_new ();
440
587
g_object_ref_sink (props_empty);
515
641
context->client = NULL;
518
IBUS_OBJECT_CLASS(bus_input_context_parent_class)->destroy (IBUS_OBJECT (context));
521
/* introspectable interface */
523
_ibus_introspect (BusInputContext *context,
524
IBusMessage *message,
525
BusConnection *connection)
527
static const gchar *introspect =
528
DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE
530
" <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
531
" <method name=\"Introspect\">\n"
532
" <arg name=\"data\" direction=\"out\" type=\"s\"/>\n"
535
" <interface name=\"org.freedesktop.IBus.InputContext\">\n"
538
" <method name=\"ProcessKeyEvent\">\n"
539
" <arg name=\"keyval\" direction=\"in\" type=\"u\"/>\n"
540
" <arg name=\"keycode\" direction=\"in\" type=\"u\"/>\n"
541
" <arg name=\"state\" direction=\"in\" type=\"u\"/>\n"
542
" <arg name=\"handled\" direction=\"out\" type=\"b\"/>\n"
544
" <method name=\"SetCursorLocation\">\n"
545
" <arg name=\"x\" direction=\"in\" type=\"i\"/>\n"
546
" <arg name=\"y\" direction=\"in\" type=\"i\"/>\n"
547
" <arg name=\"w\" direction=\"in\" type=\"i\"/>\n"
548
" <arg name=\"h\" direction=\"in\" type=\"i\"/>\n"
550
" <method name=\"FocusIn\"/>\n"
551
" <method name=\"FocusOut\"/>\n"
552
" <method name=\"Reset\"/>\n"
553
" <method name=\"Enable\"/>\n"
554
" <method name=\"Disable\"/>\n"
555
" <method name=\"IsEnabled\">\n"
556
" <arg name=\"enable\" direction=\"out\" type=\"b\"/>\n"
558
" <method name=\"SetCapabilities\">\n"
559
" <arg name=\"caps\" direction=\"in\" type=\"u\"/>\n"
561
" <method name=\"PropertyActivate\">\n"
562
" <arg name=\"name\" direction=\"in\" type=\"s\"/>\n"
563
" <arg name=\"state\" direction=\"in\" type=\"i\"/>\n"
565
" <method name=\"SetEngine\">\n"
566
" <arg name=\"name\" direction=\"in\" type=\"s\"/>\n"
568
" <method name=\"GetEngine\">\n"
569
" <arg name=\"desc\" direction=\"out\" type=\"v\"/>\n"
571
" <method name=\"Destroy\"/>\n"
574
" <signal name=\"CommitText\">\n"
575
" <arg name=\"text\" type=\"v\"/>\n"
577
" <signal name=\"Enabled\"/>\n"
578
" <signal name=\"Disabled\"/>\n"
579
" <signal name=\"ForwardKeyEvent\">\n"
580
" <arg name=\"keyval\" type=\"u\"/>\n"
581
" <arg name=\"keycode\" type=\"u\"/>\n"
582
" <arg name=\"state\" type=\"u\"/>\n"
585
" <signal name=\"UpdatePreeditText\">\n"
586
" <arg name=\"text\" type=\"v\"/>\n"
587
" <arg name=\"cursor_pos\" type=\"u\"/>\n"
588
" <arg name=\"visible\" type=\"b\"/>\n"
590
" <signal name=\"ShowPreeditText\"/>\n"
591
" <signal name=\"HidePreeditText\"/>\n"
593
" <signal name=\"UpdateAuxiliaryText\">\n"
594
" <arg name=\"text\" type=\"v\"/>\n"
595
" <arg name=\"visible\" type=\"b\"/>\n"
597
" <signal name=\"ShowAuxiliaryText\"/>\n"
598
" <signal name=\"HideAuxiliaryText\"/>\n"
600
" <signal name=\"UpdateLookupTable\">\n"
601
" <arg name=\"table\" type=\"v\"/>\n"
602
" <arg name=\"visible\" type=\"b\"/>\n"
604
" <signal name=\"ShowLookupTable\"/>\n"
605
" <signal name=\"HideLookupTable\"/>\n"
606
" <signal name=\"PageUpLookupTable\"/>\n"
607
" <signal name=\"PageDownLookupTable\"/>\n"
608
" <signal name=\"CursorUpLookupTable\"/>\n"
609
" <signal name=\"CursorDownLookupTable\"/>\n"
611
" <signal name=\"RegisterProperties\">\n"
612
" <arg name=\"props\" type=\"v\"/>\n"
614
" <signal name=\"UpdateProperty\">\n"
615
" <arg name=\"prop\" type=\"v\"/>\n"
621
IBusMessage *reply_message;
622
reply_message = ibus_message_new_method_return (message);
623
ibus_message_append_args (reply_message,
624
G_TYPE_STRING, &introspect,
627
return reply_message;
631
BusInputContext *context;
632
IBusMessage *message;
636
_ic_process_key_event_reply_cb (gpointer data,
642
retval = (gboolean) GPOINTER_TO_INT (data);
643
call_data = (CallData *) user_data;
645
/* make sure the connection is alive */
646
if (G_LIKELY (call_data->context->connection != NULL)) {
648
reply = ibus_message_new_method_return (call_data->message);
649
ibus_message_append_args (reply,
650
G_TYPE_BOOLEAN, &retval,
653
ibus_connection_send ((IBusConnection *)call_data->context->connection, reply);
654
ibus_message_unref (reply);
657
g_object_unref (call_data->context);
658
ibus_message_unref (call_data->message);
659
g_slice_free (CallData, call_data);
663
_ic_process_key_event (BusInputContext *context,
664
IBusMessage *message,
665
BusConnection *connection)
667
g_assert (BUS_IS_INPUT_CONTEXT (context));
668
g_assert (message != NULL);
669
g_assert (BUS_IS_CONNECTION (connection));
672
guint keyval, keycode, modifiers;
676
retval = ibus_message_get_args (message,
678
G_TYPE_UINT, &keyval,
679
G_TYPE_UINT, &keycode,
680
G_TYPE_UINT, &modifiers,
684
reply = ibus_message_new_error (message,
687
ibus_error_free (error);
644
IBUS_OBJECT_CLASS (bus_input_context_parent_class)->destroy (IBUS_OBJECT (context));
648
* bus_input_context_emit_signal:
649
* @signal_name: The D-Bus signal name to emit which is in the introspection_xml.
651
* Emit the D-Bus signal.
654
bus_input_context_emit_signal (BusInputContext *context,
655
const gchar *signal_name,
656
GVariant *parameters,
659
if (context->connection == NULL)
662
GDBusMessage *message = g_dbus_message_new_signal (ibus_service_get_object_path ((IBusService *)context),
663
"org.freedesktop.IBus.InputContext",
665
g_dbus_message_set_sender (message, "org.freedesktop.IBus");
666
g_dbus_message_set_destination (message, bus_connection_get_unique_name (context->connection));
667
if (parameters != NULL)
668
g_dbus_message_set_body (message, parameters);
670
gboolean retval = g_dbus_connection_send_message (bus_connection_get_dbus_connection (context->connection),
672
G_DBUS_SEND_MESSAGE_FLAGS_NONE,
674
g_object_unref (message);
679
* _ic_process_key_event_reply_cb:
681
* A GAsyncReadyCallback function to be called when bus_engine_proxy_process_key_event() is finished.
684
_ic_process_key_event_reply_cb (GObject *source,
686
GDBusMethodInvocation *invocation)
688
GError *error = NULL;
689
GVariant *value = g_dbus_proxy_call_finish ((GDBusProxy *)source,
693
g_dbus_method_invocation_return_value (invocation, value);
694
g_variant_unref (value);
697
g_dbus_method_invocation_return_gerror (invocation, error);
698
g_error_free (error);
703
* _ic_process_key_event:
705
* Implement the "ProcessKeyEvent" method call of the org.freedesktop.IBus.InputContext interface.
708
_ic_process_key_event (BusInputContext *context,
709
GVariant *parameters,
710
GDBusMethodInvocation *invocation)
712
guint keyval = IBUS_VoidSymbol;
716
g_variant_get (parameters, "(uuu)", &keyval, &keycode, &modifiers);
691
717
if (G_UNLIKELY (!context->has_focus)) {
692
718
/* workaround: set focus if context does not have focus */
693
if (BUS_DEFAULT_IBUS->focused_context == NULL ||
694
BUS_DEFAULT_IBUS->focused_context->fake == TRUE ||
719
BusInputContext *focused_context = bus_ibus_impl_get_focused_input_context (BUS_DEFAULT_IBUS);
720
if (focused_context == NULL ||
721
focused_context->fake == TRUE ||
695
722
context->fake == FALSE) {
696
723
/* grab focus, if context is a real IC or current focused IC is fake */
697
724
bus_input_context_focus_in (context);
701
728
if (G_LIKELY (context->has_focus)) {
702
retval = bus_input_context_filter_keyboard_shortcuts (context, keyval, keycode, modifiers);
729
gboolean retval = bus_input_context_filter_keyboard_shortcuts (context, keyval, keycode, modifiers);
703
730
/* If it is keyboard shortcut, reply TRUE to client */
704
731
if (G_UNLIKELY (retval)) {
705
reply = ibus_message_new_method_return (message);
706
ibus_message_append_args (reply,
707
G_TYPE_BOOLEAN, &retval,
732
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
713
737
/* ignore key events, if it is a fake input context */
714
738
if (context->has_focus && context->enabled && context->engine && context->fake == FALSE) {
717
call_data = g_slice_new (CallData);
719
g_object_ref (context);
720
ibus_message_ref (message);
722
call_data->context = context;
723
call_data->message = message;
725
739
bus_engine_proxy_process_key_event (context->engine,
729
(GFunc) _ic_process_key_event_reply_cb,
743
(GAsyncReadyCallback) _ic_process_key_event_reply_cb,
735
reply = ibus_message_new_method_return (message);
736
ibus_message_append_args (reply,
737
G_TYPE_BOOLEAN, &retval,
747
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
744
_ic_set_cursor_location (BusInputContext *context,
745
IBusMessage *message,
746
BusConnection *connection)
752
* _ic_set_cursor_location:
754
* Implement the "SetCursorLocation" method call of the org.freedesktop.IBus.InputContext interface.
757
_ic_set_cursor_location (BusInputContext *context,
758
GVariant *parameters,
759
GDBusMethodInvocation *invocation)
748
g_assert (BUS_IS_INPUT_CONTEXT (context));
749
g_assert (message != NULL);
750
g_assert (BUS_IS_CONNECTION (connection));
757
retval = ibus_message_get_args (message, &error,
765
reply = ibus_message_new_error (message,
768
ibus_error_free (error);
761
g_dbus_method_invocation_return_value (invocation, NULL);
763
g_variant_get (parameters, "(iiii)",
764
&context->x, &context->y, &context->w, &context->h);
777
766
if (context->has_focus && context->enabled && context->engine) {
778
bus_engine_proxy_set_cursor_location (context->engine, x, y, w, h);
767
bus_engine_proxy_set_cursor_location (context->engine,
768
context->x, context->y, context->w, context->h);
781
771
if (context->capabilities & IBUS_CAP_FOCUS) {
782
772
g_signal_emit (context,
783
773
context_signals[SET_CURSOR_LOCATION],
791
reply = ibus_message_new_method_return (message);
796
_ic_focus_in (BusInputContext *context,
797
IBusMessage *message,
798
BusConnection *connection)
785
* Implement the "FocusIn" method call of the org.freedesktop.IBus.InputContext interface.
788
_ic_focus_in (BusInputContext *context,
789
GVariant *parameters,
790
GDBusMethodInvocation *invocation)
800
g_assert (BUS_IS_INPUT_CONTEXT (context));
801
g_assert (message != NULL);
802
g_assert (BUS_IS_CONNECTION (connection));
806
792
if (context->capabilities & IBUS_CAP_FOCUS) {
807
793
bus_input_context_focus_in (context);
808
reply = ibus_message_new_method_return (message);
794
g_dbus_method_invocation_return_value (invocation, NULL);
811
reply = ibus_message_new_error (message,
813
"The input context does not support focus.");
797
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
798
"The input context does not support focus.");
820
_ic_focus_out (BusInputContext *context,
821
IBusMessage *message,
822
BusConnection *connection)
805
* Implement the "FocusOut" method call of the org.freedesktop.IBus.InputContext interface.
808
_ic_focus_out (BusInputContext *context,
809
GVariant *parameters,
810
GDBusMethodInvocation *invocation)
824
g_assert (BUS_IS_INPUT_CONTEXT (context));
825
g_assert (message != NULL);
826
g_assert (BUS_IS_CONNECTION (connection));
830
812
if (context->capabilities & IBUS_CAP_FOCUS) {
831
813
bus_input_context_focus_out (context);
832
reply = ibus_message_new_method_return (message);
814
g_dbus_method_invocation_return_value (invocation, NULL);
835
reply = ibus_message_new_error (message,
837
"The input context does not support focus.");
817
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
818
"The input context does not support focus.");
844
_ic_reset (BusInputContext *context,
845
IBusMessage *message,
846
BusConnection *connection)
825
* Implement the "Reset" method call of the org.freedesktop.IBus.InputContext interface.
828
_ic_reset (BusInputContext *context,
829
GVariant *parameters,
830
GDBusMethodInvocation *invocation)
848
g_assert (BUS_IS_INPUT_CONTEXT (context));
849
g_assert (message != NULL);
850
g_assert (BUS_IS_CONNECTION (connection));
854
832
if (context->enabled && context->engine) {
855
833
bus_engine_proxy_reset (context->engine);
858
reply = ibus_message_new_method_return (message);
863
_ic_set_capabilities (BusInputContext *context,
864
IBusMessage *message,
865
BusConnection *connection)
867
g_assert (BUS_IS_INPUT_CONTEXT (context));
868
g_assert (message != NULL);
869
g_assert (BUS_IS_CONNECTION (connection));
876
retval = ibus_message_get_args (message,
882
reply = ibus_message_new_error (message,
885
ibus_error_free (error);
889
if (context->capabilities != caps) {
890
context->capabilities = caps;
892
/* If the context does not support IBUS_CAP_FOCUS, then we always assume
894
if ((caps & IBUS_CAP_FOCUS) == 0) {
895
bus_input_context_focus_in (context);
898
if (context->engine) {
899
bus_engine_proxy_set_capabilities (context->engine, caps);
903
reply = ibus_message_new_method_return (message);
908
_ic_property_activate (BusInputContext *context,
909
IBusMessage *message,
910
BusConnection *connection)
912
g_assert (BUS_IS_INPUT_CONTEXT (context));
913
g_assert (message != NULL);
914
g_assert (BUS_IS_CONNECTION (connection));
922
retval = ibus_message_get_args (message,
924
G_TYPE_STRING, &prop_name,
925
G_TYPE_INT, &prop_state,
929
reply = ibus_message_new_error (message,
932
ibus_error_free (error);
835
g_dbus_method_invocation_return_value (invocation, NULL);
839
* _ic_set_capabilities:
841
* Implement the "SetCapabilities" method call of the org.freedesktop.IBus.InputContext interface.
844
_ic_set_capabilities (BusInputContext *context,
845
GVariant *parameters,
846
GDBusMethodInvocation *invocation)
849
g_variant_get (parameters, "(u)", &caps);
851
bus_input_context_set_capabilities (context, caps);
853
g_dbus_method_invocation_return_value (invocation, NULL);
857
* _ic_property_activate:
859
* Implement the "PropertyActivate" method call of the org.freedesktop.IBus.InputContext interface.
862
_ic_property_activate (BusInputContext *context,
863
GVariant *parameters,
864
GDBusMethodInvocation *invocation)
866
gchar *prop_name = NULL;
867
guint prop_state = 0;
868
g_variant_get (parameters, "(&su)", &prop_name, &prop_state);
936
870
if (context->enabled && context->engine) {
937
871
bus_engine_proxy_property_activate (context->engine, prop_name, prop_state);
939
874
#ifdef OS_CHROMEOS
940
875
/* Global engine is always enabled in chromeos,
941
876
* so pass PropertyActivate signal to the focused context.
945
BUS_DEFAULT_IBUS->focused_context &&
946
BUS_DEFAULT_IBUS->focused_context->engine) {
947
bus_engine_proxy_property_activate (BUS_DEFAULT_IBUS->focused_context->engine, prop_name, prop_state);
878
else if (context->fake) {
879
BusInputContext *focused_context = bus_ibus_impl_get_focused_input_context (BUS_DEFAULT_IBUS);
880
if (focused_context && focused_context->engine)
881
bus_engine_proxy_property_activate (focused_context->engine, prop_name, prop_state);
952
reply = ibus_message_new_method_return (message);
885
g_dbus_method_invocation_return_value (invocation, NULL);
957
_ic_enable (BusInputContext *context,
958
IBusMessage *message,
959
BusConnection *connection)
891
* Implement the "Enable" method call of the org.freedesktop.IBus.InputContext interface.
894
_ic_enable (BusInputContext *context,
895
GVariant *parameters,
896
GDBusMethodInvocation *invocation)
961
g_assert (BUS_IS_INPUT_CONTEXT (context));
962
g_assert (message != NULL);
963
g_assert (BUS_IS_CONNECTION (connection));
967
898
bus_input_context_enable (context);
969
reply = ibus_message_new_method_return (message);
899
g_dbus_method_invocation_return_value (invocation, NULL);
974
_ic_disable (BusInputContext *context,
975
IBusMessage *message,
976
BusConnection *connection)
905
* Implement the "Disable" method call of the org.freedesktop.IBus.InputContext interface.
908
_ic_disable (BusInputContext *context,
909
GVariant *parameters,
910
GDBusMethodInvocation *invocation)
978
g_assert (BUS_IS_INPUT_CONTEXT (context));
979
g_assert (message != NULL);
980
g_assert (BUS_IS_CONNECTION (connection));
984
912
bus_input_context_disable (context);
986
reply = ibus_message_new_method_return (message);
991
_ic_is_enabled (BusInputContext *context,
992
IBusMessage *message,
993
BusConnection *connection)
995
g_assert (BUS_IS_INPUT_CONTEXT (context));
996
g_assert (message != NULL);
997
g_assert (BUS_IS_CONNECTION (connection));
1001
reply = ibus_message_new_method_return (message);
1002
ibus_message_append_args (reply,
1003
G_TYPE_BOOLEAN, &context->enabled,
1009
static IBusMessage *
1010
_ic_set_engine (BusInputContext *context,
1011
IBusMessage *message,
1012
BusConnection *connection)
1014
g_assert (BUS_IS_INPUT_CONTEXT (context));
1015
g_assert (message != NULL);
1016
g_assert (BUS_IS_CONNECTION (connection));
1023
retval = ibus_message_get_args (message,
1025
G_TYPE_STRING, &engine_name,
1028
reply = ibus_message_new_error (message,
1031
ibus_error_free (error);
1035
g_signal_emit (context, context_signals[REQUEST_ENGINE], 0, engine_name);
1037
if (context->engine == NULL) {
1038
reply = ibus_message_new_error_printf (message,
1039
"org.freedesktop.IBus.NoEngine",
1040
"can not find engine with name %s",
1045
bus_input_context_enable (context);
1047
reply = ibus_message_new_method_return (message);
1051
static IBusMessage *
1052
_ic_get_engine (BusInputContext *context,
1053
IBusMessage *message,
1054
BusConnection *connection)
1056
g_assert (BUS_IS_INPUT_CONTEXT (context));
1057
g_assert (message != NULL);
1058
g_assert (BUS_IS_CONNECTION (connection));
1061
IBusEngineDesc *desc;
913
g_dbus_method_invocation_return_value (invocation, NULL);
919
* Implement the "IsEnabled" method call of the org.freedesktop.IBus.InputContext interface.
922
_ic_is_enabled (BusInputContext *context,
923
GVariant *parameters,
924
GDBusMethodInvocation *invocation)
926
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", context->enabled));
930
_ic_set_engine_done (BusInputContext *context,
932
GDBusMethodInvocation *invocation)
934
gboolean retval = FALSE;
935
GError *error = NULL;
937
retval = bus_input_context_set_engine_by_desc_finish (context,
941
g_dbus_method_invocation_return_gerror (invocation, error);
942
g_error_free (error);
945
g_dbus_method_invocation_return_value (invocation, NULL);
952
* Implement the "SetEngine" method call of the org.freedesktop.IBus.InputContext interface.
955
_ic_set_engine (BusInputContext *context,
956
GVariant *parameters,
957
GDBusMethodInvocation *invocation)
959
gchar *engine_name = NULL;
960
g_variant_get (parameters, "(&s)", &engine_name);
962
if (!bus_input_context_has_focus (context)) {
963
g_dbus_method_invocation_return_error (invocation,
964
G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
965
"Context which does not has focus can not change engine to %s.",
970
IBusEngineDesc *desc = NULL;
971
g_signal_emit (context,
972
context_signals[REQUEST_ENGINE], 0,
976
g_dbus_method_invocation_return_error (invocation,
977
G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
978
"Can not find engine %s.", engine_name);
982
bus_input_context_set_engine_by_desc (context,
986
(GAsyncReadyCallback)_ic_set_engine_done,
989
g_object_unref (desc);
995
* Implement the "GetEngine" method call of the org.freedesktop.IBus.InputContext interface.
998
_ic_get_engine (BusInputContext *context,
999
GVariant *parameters,
1000
GDBusMethodInvocation *invocation)
1063
1002
if (context->engine) {
1064
desc = bus_engine_proxy_get_desc (context->engine);
1066
reply = ibus_message_new_method_return (message);
1067
ibus_message_append_args (reply,
1068
IBUS_TYPE_ENGINE_DESC, &desc,
1074
reply = ibus_message_new_error (message,
1076
"InputContext does not have factory.");
1080
static IBusMessage *
1081
_ic_destroy (BusInputContext *context,
1082
IBusMessage *message,
1083
BusConnection *connection)
1085
g_assert (BUS_IS_INPUT_CONTEXT (context));
1086
g_assert (message != NULL);
1087
g_assert (BUS_IS_CONNECTION (connection));
1090
reply = ibus_message_new_method_return (message);
1092
ibus_connection_send ((IBusConnection *) connection, reply);
1093
ibus_connection_flush ((IBusConnection *) connection);
1094
ibus_message_unref (reply);
1096
ibus_object_destroy ((IBusObject *) context);
1102
bus_input_context_ibus_message (BusInputContext *context,
1103
BusConnection *connection,
1104
IBusMessage *message)
1106
g_assert (BUS_IS_INPUT_CONTEXT (context));
1107
g_assert (BUS_IS_CONNECTION (connection));
1108
g_assert (message != NULL);
1111
IBusMessage *reply_message = NULL;
1003
IBusEngineDesc *desc = bus_engine_proxy_get_desc (context->engine);
1004
g_dbus_method_invocation_return_value (invocation,
1005
g_variant_new ("(v)", ibus_serializable_serialize ((IBusSerializable *)desc)));
1008
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, G_DBUS_ERROR_FAILED,
1009
"Input context does not have engine.");
1014
* bus_input_context_service_method_call:
1016
* Handle a D-Bus method call whose destination and interface name are both "org.freedesktop.IBus.InputContext"
1019
_ic_set_surrounding_text (BusInputContext *context,
1020
GVariant *parameters,
1021
GDBusMethodInvocation *invocation)
1023
GVariant *variant = NULL;
1025
guint cursor_pos = 0;
1027
g_variant_get (parameters, "(vu)", &variant, &cursor_pos);
1028
text = IBUS_TEXT (ibus_serializable_deserialize (variant));
1029
g_variant_unref (variant);
1031
if ((context->capabilities & IBUS_CAP_SURROUNDING_TEXT) &&
1032
context->has_focus && context->enabled && context->engine) {
1033
bus_engine_proxy_set_surrounding_text (context->engine,
1038
if (g_object_is_floating (text))
1039
g_object_unref (text);
1041
g_dbus_method_invocation_return_value (invocation, NULL);
1045
bus_input_context_service_method_call (IBusService *service,
1046
GDBusConnection *connection,
1047
const gchar *sender,
1048
const gchar *object_path,
1049
const gchar *interface_name,
1050
const gchar *method_name,
1051
GVariant *parameters,
1052
GDBusMethodInvocation *invocation)
1054
if (g_strcmp0 (interface_name, "org.freedesktop.IBus.InputContext") != 0) {
1055
IBUS_SERVICE_CLASS (bus_input_context_parent_class)->service_method_call (
1113
1067
static const struct {
1114
const gchar *interface;
1116
IBusMessage *(* handler) (BusInputContext *, IBusMessage *, BusConnection *);
1118
/* Introspectable interface */
1119
{ DBUS_INTERFACE_INTROSPECTABLE,
1120
"Introspect", _ibus_introspect },
1121
/* IBus interface */
1122
{ IBUS_INTERFACE_INPUT_CONTEXT, "ProcessKeyEvent", _ic_process_key_event },
1123
{ IBUS_INTERFACE_INPUT_CONTEXT, "SetCursorLocation", _ic_set_cursor_location },
1124
{ IBUS_INTERFACE_INPUT_CONTEXT, "FocusIn", _ic_focus_in },
1125
{ IBUS_INTERFACE_INPUT_CONTEXT, "FocusOut", _ic_focus_out },
1126
{ IBUS_INTERFACE_INPUT_CONTEXT, "Reset", _ic_reset },
1127
{ IBUS_INTERFACE_INPUT_CONTEXT, "SetCapabilities", _ic_set_capabilities },
1128
{ IBUS_INTERFACE_INPUT_CONTEXT, "PropertyActivate", _ic_property_activate },
1129
{ IBUS_INTERFACE_INPUT_CONTEXT, "Enable", _ic_enable },
1130
{ IBUS_INTERFACE_INPUT_CONTEXT, "Disable", _ic_disable },
1131
{ IBUS_INTERFACE_INPUT_CONTEXT, "IsEnabled", _ic_is_enabled },
1132
{ IBUS_INTERFACE_INPUT_CONTEXT, "SetEngine", _ic_set_engine },
1133
{ IBUS_INTERFACE_INPUT_CONTEXT, "GetEngine", _ic_get_engine },
1134
{ IBUS_INTERFACE_INPUT_CONTEXT, "Destroy", _ic_destroy },
1068
const gchar *method_name;
1069
void (* method_callback) (BusInputContext *, GVariant *, GDBusMethodInvocation *);
1071
{ "ProcessKeyEvent", _ic_process_key_event },
1072
{ "SetCursorLocation", _ic_set_cursor_location },
1073
{ "FocusIn", _ic_focus_in },
1074
{ "FocusOut", _ic_focus_out },
1075
{ "Reset", _ic_reset },
1076
{ "SetCapabilities", _ic_set_capabilities },
1077
{ "PropertyActivate", _ic_property_activate },
1078
{ "Enable", _ic_enable },
1079
{ "Disable", _ic_disable },
1080
{ "IsEnabled", _ic_is_enabled },
1081
{ "SetEngine", _ic_set_engine },
1082
{ "GetEngine", _ic_get_engine },
1083
{ "SetSurroundingText", _ic_set_surrounding_text},
1137
ibus_message_set_sender (message, bus_connection_get_unique_name (connection));
1138
ibus_message_set_destination (message, DBUS_SERVICE_DBUS);
1140
for (i = 0; i < G_N_ELEMENTS (handlers); i++) {
1141
if (ibus_message_is_method_call (message,
1142
handlers[i].interface,
1143
handlers[i].name)) {
1145
reply_message = handlers[i].handler (context, message, connection);
1146
if (reply_message) {
1148
ibus_message_set_sender (reply_message,
1150
ibus_message_set_destination (reply_message,
1151
bus_connection_get_unique_name (connection));
1152
ibus_message_set_no_reply (reply_message, TRUE);
1154
ibus_connection_send (IBUS_CONNECTION (connection), reply_message);
1155
ibus_message_unref (reply_message);
1158
g_signal_stop_emission_by_name (context, "ibus-message");
1087
for (i = 0; i < G_N_ELEMENTS (methods); i++) {
1088
if (g_strcmp0 (method_name, methods[i].method_name) == 0) {
1089
methods[i].method_callback ((BusInputContext *)service, parameters, invocation);
1163
return IBUS_SERVICE_CLASS (bus_input_context_parent_class)->ibus_message (
1164
(IBusService *)context,
1165
(IBusConnection *)connection,
1094
g_return_if_reached ();
1171
1098
bus_input_context_has_focus (BusInputContext *context)
2200
static void set_engine_by_desc_data_free (SetEngineByDescData *data)
2202
if (data->context != NULL) {
2203
if (data->context->data == data)
2204
data->context->data = NULL;
2205
g_object_unref (data->context);
2208
if (data->simple != NULL) {
2209
g_object_unref (data->simple);
2212
if (data->cancellable != NULL)
2213
g_object_unref (data->cancellable);
2215
if (data->origin_cancellable != NULL) {
2216
if (data->cancelled_handler_id != 0)
2217
g_cancellable_disconnect (data->origin_cancellable,
2218
data->cancelled_handler_id);
2219
g_object_unref (data->origin_cancellable);
2222
g_slice_free (SetEngineByDescData, data);
2228
* A callback function to be called when bus_engine_proxy_new() is finished.
2231
new_engine_cb (GObject *obj,
2233
SetEngineByDescData *data)
2235
GError *error = NULL;
2236
BusEngineProxy *engine = bus_engine_proxy_new_finish (res, &error);
2238
if (engine == NULL) {
2239
g_simple_async_result_set_from_error (data->simple, error);
2240
g_error_free (error);
2243
if (data->context->data != data) {
2244
/* Request has been overriden or cancelled */
2245
g_object_unref (engine);
2246
g_simple_async_result_set_error (data->simple,
2248
G_IO_ERROR_CANCELLED,
2249
"Opertation was cancelled");
2252
bus_input_context_set_engine (data->context, engine);
2253
bus_input_context_enable (data->context);
2254
g_simple_async_result_set_op_res_gboolean (data->simple, TRUE);
2258
/* Call the callback function for bus_input_context_set_engine_by_desc(). */
2259
g_simple_async_result_complete_in_idle (data->simple);
2261
set_engine_by_desc_data_free (data);
2265
cancel_set_engine_by_desc (SetEngineByDescData *data)
2267
if (data->context->data == data)
2268
data->context->data = NULL;
2270
if (data->origin_cancellable != NULL) {
2271
if (data->cancelled_handler_id != 0) {
2272
g_cancellable_disconnect (data->origin_cancellable,
2273
data->cancelled_handler_id);
2274
data->cancelled_handler_id = 0;
2277
g_object_unref (data->origin_cancellable);
2278
data->origin_cancellable = NULL;
2281
if (data->cancellable != NULL) {
2282
g_cancellable_cancel (data->cancellable);
2283
g_object_unref (data->cancellable);
2284
data->cancellable = NULL;
2289
set_engine_by_desc_cancelled_idle_cb (SetEngineByDescData *data)
2291
cancel_set_engine_by_desc (data);
2296
set_engine_by_desc_cancelled_cb (GCancellable *cancellable,
2297
SetEngineByDescData *data)
2299
/* Cancel in idle to avoid deadlock */
2300
g_idle_add ((GSourceFunc) set_engine_by_desc_cancelled_idle_cb, data);
2304
* set_engine_by_desc_ready_cb:
2306
* A default callback function for bus_input_context_set_engine_by_desc().
2309
set_engine_by_desc_ready_cb (BusInputContext *context,
2313
GError *error = NULL;
2314
if (!bus_input_context_set_engine_by_desc_finish (context, res, &error)) {
2315
g_warning ("Set context engine failed: %s", error->message);
2316
g_error_free (error);
2321
bus_input_context_set_engine_by_desc (BusInputContext *context,
2322
IBusEngineDesc *desc,
2324
GCancellable *cancellable,
2325
GAsyncReadyCallback callback,
2328
g_assert (BUS_IS_INPUT_CONTEXT (context));
2329
g_assert (IBUS_IS_ENGINE_DESC (desc));
2330
g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
2332
if (context->data != NULL) {
2333
/* Cancel previous set_engine_by_desc() request */
2334
cancel_set_engine_by_desc (context->data);
2337
/* Previous request must be completed or cancelled */
2338
g_assert (context->data == NULL);
2340
if (callback == NULL)
2341
callback = (GAsyncReadyCallback) set_engine_by_desc_ready_cb;
2343
GSimpleAsyncResult *simple =
2344
g_simple_async_result_new ((GObject *) context,
2347
bus_input_context_set_engine_by_desc);
2349
if (g_cancellable_is_cancelled (cancellable)) {
2350
g_simple_async_result_set_error (simple,
2352
G_IO_ERROR_CANCELLED,
2353
"Operation was cancelled");
2354
g_simple_async_result_complete_in_idle (simple);
2355
g_object_unref (simple);
2359
SetEngineByDescData *data = g_slice_new0 (SetEngineByDescData);
2360
context->data = data;
2361
data->context = context;
2362
g_object_ref (context);
2363
data->simple = simple;
2365
if (cancellable != NULL) {
2366
data->origin_cancellable = cancellable;
2367
g_object_ref (cancellable);
2368
data->cancelled_handler_id =
2369
g_cancellable_connect (data->origin_cancellable,
2370
(GCallback) set_engine_by_desc_cancelled_cb,
2375
data->cancellable = g_cancellable_new ();
2376
/* We can cancel the bus_engine_proxy_new() call by data->cancellable;
2377
* See cancel_set_engine_by_desc() and set_engine_by_desc_cancelled_cb(). */
2378
bus_engine_proxy_new (desc,
2381
(GAsyncReadyCallback) new_engine_cb,
2386
bus_input_context_set_engine_by_desc_finish (BusInputContext *context,
2390
GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
2392
g_assert (BUS_IS_INPUT_CONTEXT (context));
2393
g_assert (g_simple_async_result_get_source_tag (simple) ==
2394
bus_input_context_set_engine_by_desc);
2396
if (g_simple_async_result_propagate_error (simple, error))
2036
2401
BusEngineProxy *
2037
2402
bus_input_context_get_engine (BusInputContext *context)