Move input focus on Emojier to engines' preedit
This commit is contained in:
Родитель
37aa95f1ad
Коммит
5ee3f48049
|
@ -6,8 +6,15 @@ namespace IBus {
|
|||
[CCode (cname = "ibus_text_new_from_static_string", has_construct_function = false)]
|
||||
public Text.from_static_string (string str);
|
||||
}
|
||||
public class ExtensionEvent : IBus.Serializable {
|
||||
[CCode (cname = "ibus_extension_event_new", has_construct_function = true)]
|
||||
public ExtensionEvent (string first_property_name, ...);
|
||||
}
|
||||
public class XEvent : IBus.Serializable {
|
||||
[CCode (cname = "ibus_x_event_new", has_construct_function = true)]
|
||||
public XEvent (string first_property_name, ...);
|
||||
}
|
||||
public class PanelService : IBus.Service {
|
||||
public void panel_extension_register_keys(string first_property_name, ...);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
# ibus - The Input Bus
|
||||
#
|
||||
# Copyright (c) 2007-2016 Peng Huang <shawn.p.huang@gmail.com>
|
||||
# Copyright (c) 2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
||||
# Copyright (c) 2017-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
||||
# Copyright (c) 2007-2017 Red Hat, Inc.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
|
@ -86,6 +86,7 @@ EXTRA_DIST = \
|
|||
ibus-1.0.deps \
|
||||
ibus-emoji-dialog-1.0.deps \
|
||||
config.vapi \
|
||||
gdk-wayland.vapi \
|
||||
xi.vapi \
|
||||
$(NULL)
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "gdk/gdkwayland.h")]
|
||||
namespace GdkWayland
|
||||
{
|
||||
[CCode (type_id = "gdk_wayland_display_get_type ()")]
|
||||
public class Display : Gdk.Display {
|
||||
}
|
||||
}
|
|
@ -377,10 +377,10 @@ bus_engine_proxy_class_init (BusEngineProxyClass *class)
|
|||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
bus_marshal_VOID__VARIANT,
|
||||
bus_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_VARIANT);
|
||||
IBUS_TYPE_EXTENSION_EVENT);
|
||||
|
||||
text_empty = ibus_text_new_from_static_string ("");
|
||||
g_object_ref_sink (text_empty);
|
||||
|
@ -644,7 +644,16 @@ bus_engine_proxy_g_signal (GDBusProxy *proxy,
|
|||
}
|
||||
|
||||
if (g_strcmp0 (signal_name, "PanelExtension") == 0) {
|
||||
g_signal_emit (engine, engine_signals[PANEL_EXTENSION], 0, parameters);
|
||||
GVariant *arg0 = NULL;
|
||||
g_variant_get (parameters, "(v)", &arg0);
|
||||
g_return_if_fail (arg0 != NULL);
|
||||
|
||||
IBusExtensionEvent *event = IBUS_EXTENSION_EVENT (
|
||||
ibus_serializable_deserialize (arg0));
|
||||
g_variant_unref (arg0);
|
||||
g_return_if_fail (event != NULL);
|
||||
g_signal_emit (engine, engine_signals[PANEL_EXTENSION], 0, event);
|
||||
_g_object_unref_if_floating (event);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1323,6 +1332,44 @@ bus_engine_proxy_is_enabled (BusEngineProxy *engine)
|
|||
return engine->enabled;
|
||||
}
|
||||
|
||||
void
|
||||
bus_engine_proxy_panel_extension_received (BusEngineProxy *engine,
|
||||
IBusExtensionEvent *event)
|
||||
{
|
||||
GVariant *variant;
|
||||
g_assert (BUS_IS_ENGINE_PROXY (engine));
|
||||
g_assert (IBUS_IS_EXTENSION_EVENT (event));
|
||||
|
||||
variant = ibus_serializable_serialize_object (
|
||||
IBUS_SERIALIZABLE (event));
|
||||
g_return_if_fail (variant != NULL);
|
||||
g_dbus_proxy_call ((GDBusProxy *)engine,
|
||||
"PanelExtensionReceived",
|
||||
g_variant_new ("(v)", variant),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
bus_engine_proxy_panel_extension_register_keys (BusEngineProxy *engine,
|
||||
GVariant *parameters)
|
||||
{
|
||||
g_assert (BUS_IS_ENGINE_PROXY (engine));
|
||||
g_assert (parameters);
|
||||
|
||||
g_dbus_proxy_call ((GDBusProxy *)engine,
|
||||
"PanelExtensionRegisterKeys",
|
||||
g_variant_new ("(v)", g_variant_ref (parameters)),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
initable_init (GInitable *initable,
|
||||
GCancellable *cancellable,
|
||||
|
|
|
@ -2,7 +2,8 @@
|
|||
/* vim:set et sts=4: */
|
||||
/* ibus - The Input Bus
|
||||
* Copyright (C) 2008-2013 Peng Huang <shawn.p.huang@gmail.com>
|
||||
* Copyright (C) 2008-2013 Red Hat, Inc.
|
||||
* Copyright (C) 2018 Takao Fujiwara <takao.fujiwara@gmail.com>
|
||||
* Copyright (C) 2008-2018 Red Hat, Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -325,5 +326,27 @@ void bus_engine_proxy_set_content_type
|
|||
IBusPropList *bus_engine_proxy_get_properties
|
||||
(BusEngineProxy *engine);
|
||||
|
||||
/**
|
||||
* bus_engine_proxy_panel_extension_received:
|
||||
* @engine: A #BusEngineProxy.
|
||||
* @event: An #IBusExtensionEvent.
|
||||
*
|
||||
* Send an #IBusExtensionEvent to the engine.
|
||||
*/
|
||||
void bus_engine_proxy_panel_extension_received
|
||||
(BusEngineProxy *engine,
|
||||
IBusExtensionEvent *event);
|
||||
|
||||
/**
|
||||
* bus_engine_proxy_panel_extension_register_keys:
|
||||
* @engine: A #BusEngineProxy.
|
||||
* @parameters: A #GVariant array which includes the name and shortcut keys.
|
||||
*
|
||||
* Send shortcut keys to the engine to enable the extension.
|
||||
*/
|
||||
void bus_engine_proxy_panel_extension_register_keys
|
||||
(BusEngineProxy *engine,
|
||||
GVariant *parameters);
|
||||
|
||||
G_END_DECLS
|
||||
#endif
|
||||
|
|
247
bus/ibusimpl.c
247
bus/ibusimpl.c
|
@ -74,7 +74,8 @@ struct _BusIBusImpl {
|
|||
|
||||
BusInputContext *focused_context;
|
||||
BusPanelProxy *panel;
|
||||
BusPanelProxy *extension;
|
||||
BusPanelProxy *emoji_extension;
|
||||
gboolean enable_emoji_extension;
|
||||
|
||||
/* a default keymap of ibus-daemon (usually "us") which is used only
|
||||
* when use_sys_layout is FALSE. */
|
||||
|
@ -83,6 +84,7 @@ struct _BusIBusImpl {
|
|||
gboolean use_global_engine;
|
||||
gchar *global_engine_name;
|
||||
gchar *global_previous_engine_name;
|
||||
GVariant *extension_register_keys;
|
||||
};
|
||||
|
||||
struct _BusIBusImplClass {
|
||||
|
@ -294,40 +296,158 @@ _panel_destroy_cb (BusPanelProxy *panel,
|
|||
|
||||
if (ibus->panel == panel)
|
||||
ibus->panel = NULL;
|
||||
else if (ibus->extension == panel)
|
||||
ibus->extension = NULL;
|
||||
else if (ibus->emoji_extension == panel)
|
||||
ibus->emoji_extension = NULL;
|
||||
else
|
||||
g_return_if_reached ();
|
||||
g_object_unref (panel);
|
||||
}
|
||||
|
||||
static void
|
||||
bus_ibus_impl_panel_extension_received (BusIBusImpl *ibus,
|
||||
GVariant *parameters)
|
||||
bus_ibus_impl_set_panel_extension_mode (BusIBusImpl *ibus,
|
||||
IBusExtensionEvent *event)
|
||||
{
|
||||
if (!ibus->extension) {
|
||||
gboolean is_extension = FALSE;
|
||||
g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
|
||||
g_return_if_fail (IBUS_IS_EXTENSION_EVENT (event));
|
||||
|
||||
if (!ibus->emoji_extension) {
|
||||
g_warning ("Panel extension is not running.");
|
||||
return;
|
||||
}
|
||||
|
||||
g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
|
||||
g_return_if_fail (BUS_IS_PANEL_PROXY (ibus->extension));
|
||||
g_return_if_fail (BUS_IS_PANEL_PROXY (ibus->emoji_extension));
|
||||
|
||||
ibus->enable_emoji_extension = ibus_extension_event_is_enabled (event);
|
||||
is_extension = ibus_extension_event_is_extension (event);
|
||||
if (ibus->focused_context != NULL) {
|
||||
if (ibus->enable_emoji_extension) {
|
||||
bus_input_context_set_emoji_extension (ibus->focused_context,
|
||||
ibus->emoji_extension);
|
||||
} else {
|
||||
bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
|
||||
}
|
||||
if (is_extension)
|
||||
bus_input_context_panel_extension_received (ibus->focused_context,
|
||||
event);
|
||||
}
|
||||
if (is_extension)
|
||||
return;
|
||||
|
||||
/* Use the DBus method because it seems any DBus signal,
|
||||
* g_dbus_message_new_signal(), cannot be reached to the server. */
|
||||
g_dbus_proxy_call (G_DBUS_PROXY (ibus->extension),
|
||||
"PanelExtensionReceived",
|
||||
parameters,
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1, NULL, NULL, NULL);
|
||||
bus_panel_proxy_panel_extension_received (ibus->emoji_extension,
|
||||
event);
|
||||
}
|
||||
|
||||
static void
|
||||
_panel_panel_extension_cb (BusPanelProxy *panel,
|
||||
GVariant *parameters,
|
||||
BusIBusImpl *ibus)
|
||||
bus_ibus_impl_set_panel_extension_keys (BusIBusImpl *ibus,
|
||||
GVariant *parameters)
|
||||
{
|
||||
bus_ibus_impl_panel_extension_received (ibus, parameters);
|
||||
BusEngineProxy *engine = NULL;
|
||||
|
||||
g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
|
||||
g_return_if_fail (parameters);
|
||||
|
||||
if (!ibus->emoji_extension) {
|
||||
g_warning ("Panel extension is not running.");
|
||||
return;
|
||||
}
|
||||
|
||||
if (ibus->extension_register_keys)
|
||||
g_variant_unref (ibus->extension_register_keys);
|
||||
ibus->extension_register_keys = g_variant_ref_sink (parameters);
|
||||
if (ibus->focused_context != NULL) {
|
||||
engine = bus_input_context_get_engine (ibus->focused_context);
|
||||
}
|
||||
if (!engine)
|
||||
return;
|
||||
bus_engine_proxy_panel_extension_register_keys (engine, parameters);
|
||||
}
|
||||
|
||||
static void
|
||||
_panel_panel_extension_cb (BusPanelProxy *panel,
|
||||
IBusExtensionEvent *event,
|
||||
BusIBusImpl *ibus)
|
||||
{
|
||||
bus_ibus_impl_set_panel_extension_mode (ibus, event);
|
||||
}
|
||||
|
||||
static void
|
||||
_panel_panel_extension_register_keys_cb (BusInputContext *context,
|
||||
GVariant *parameters,
|
||||
BusIBusImpl *ibus)
|
||||
{
|
||||
bus_ibus_impl_set_panel_extension_keys (ibus, parameters);
|
||||
}
|
||||
|
||||
static void
|
||||
_panel_update_preedit_text_received_cb (BusPanelProxy *panel,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
gboolean visible,
|
||||
BusIBusImpl *ibus)
|
||||
{
|
||||
g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
|
||||
|
||||
if (!ibus->focused_context)
|
||||
return;
|
||||
bus_input_context_update_preedit_text (ibus->focused_context,
|
||||
text, cursor_pos, visible, IBUS_ENGINE_PREEDIT_CLEAR, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_panel_update_lookup_table_received_cb (BusPanelProxy *panel,
|
||||
IBusLookupTable *table,
|
||||
gboolean visible,
|
||||
BusIBusImpl *ibus)
|
||||
{
|
||||
g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
|
||||
g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table));
|
||||
|
||||
if (!ibus->focused_context)
|
||||
return;
|
||||
/* Call bus_input_context_update_lookup_table() instead of
|
||||
* bus_panel_proxy_update_lookup_table() for panel extensions because
|
||||
* bus_input_context_page_up() can call bus_panel_proxy_page_up_received().
|
||||
*/
|
||||
bus_input_context_update_lookup_table (
|
||||
ibus->focused_context, table, visible, TRUE);
|
||||
}
|
||||
|
||||
static void
|
||||
_panel_update_auxiliary_text_received_cb (BusPanelProxy *panel,
|
||||
IBusText *text,
|
||||
gboolean visible,
|
||||
BusIBusImpl *ibus)
|
||||
{
|
||||
g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
|
||||
g_return_if_fail (IBUS_IS_TEXT (text));
|
||||
|
||||
if (!ibus->panel)
|
||||
return;
|
||||
bus_panel_proxy_update_auxiliary_text (
|
||||
ibus->panel, text, visible);
|
||||
}
|
||||
|
||||
static void
|
||||
_panel_show_lookup_table_received_cb (BusPanelProxy *panel,
|
||||
BusIBusImpl *ibus)
|
||||
{
|
||||
g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
|
||||
|
||||
if (ibus->panel)
|
||||
bus_panel_proxy_show_lookup_table (ibus->panel);
|
||||
}
|
||||
|
||||
static void
|
||||
_panel_hide_lookup_table_received_cb (BusPanelProxy *panel,
|
||||
BusIBusImpl *ibus)
|
||||
{
|
||||
g_return_if_fail (BUS_IS_IBUS_IMPL (ibus));
|
||||
|
||||
if (ibus->panel)
|
||||
bus_panel_proxy_hide_lookup_table (ibus->panel);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -361,8 +481,8 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
|
|||
|
||||
if (!g_strcmp0 (name, IBUS_SERVICE_PANEL))
|
||||
panel_type = PANEL_TYPE_PANEL;
|
||||
else if (!g_strcmp0 (name, IBUS_SERVICE_PANEL_EXTENSION))
|
||||
panel_type = PANEL_TYPE_EXTENSION;
|
||||
else if (!g_strcmp0 (name, IBUS_SERVICE_PANEL_EXTENSION_EMOJI))
|
||||
panel_type = PANEL_TYPE_EXTENSION_EMOJI;
|
||||
|
||||
if (panel_type != PANEL_TYPE_NONE) {
|
||||
if (g_strcmp0 (new_name, "") != 0) {
|
||||
|
@ -370,7 +490,7 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
|
|||
BusConnection *connection;
|
||||
BusInputContext *context = NULL;
|
||||
BusPanelProxy **panel = (panel_type == PANEL_TYPE_PANEL) ?
|
||||
&ibus->panel : &ibus->extension;
|
||||
&ibus->panel : &ibus->emoji_extension;
|
||||
|
||||
if (*panel != NULL) {
|
||||
ibus_proxy_destroy ((IBusProxy *)(*panel));
|
||||
|
@ -383,6 +503,8 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
|
|||
g_return_if_fail (connection != NULL);
|
||||
|
||||
*panel = bus_panel_proxy_new (connection, panel_type);
|
||||
if (panel_type == PANEL_TYPE_EXTENSION_EMOJI)
|
||||
ibus->enable_emoji_extension = FALSE;
|
||||
|
||||
g_signal_connect (*panel,
|
||||
"destroy",
|
||||
|
@ -392,6 +514,26 @@ _dbus_name_owner_changed_cb (BusDBusImpl *dbus,
|
|||
"panel-extension",
|
||||
G_CALLBACK (_panel_panel_extension_cb),
|
||||
ibus);
|
||||
g_signal_connect (*panel,
|
||||
"panel-extension-register-keys",
|
||||
G_CALLBACK (
|
||||
_panel_panel_extension_register_keys_cb),
|
||||
ibus);
|
||||
g_signal_connect (
|
||||
*panel,
|
||||
"update-preedit-text-received",
|
||||
G_CALLBACK (_panel_update_preedit_text_received_cb),
|
||||
ibus);
|
||||
g_signal_connect (
|
||||
*panel,
|
||||
"update-lookup-table-received",
|
||||
G_CALLBACK (_panel_update_lookup_table_received_cb),
|
||||
ibus);
|
||||
g_signal_connect (
|
||||
*panel,
|
||||
"update-auxiliary-text-received",
|
||||
G_CALLBACK (_panel_update_auxiliary_text_received_cb),
|
||||
ibus);
|
||||
|
||||
if (ibus->focused_context != NULL) {
|
||||
context = ibus->focused_context;
|
||||
|
@ -450,7 +592,7 @@ bus_ibus_impl_init (BusIBusImpl *ibus)
|
|||
ibus->contexts = NULL;
|
||||
ibus->focused_context = NULL;
|
||||
ibus->panel = NULL;
|
||||
ibus->extension = NULL;
|
||||
ibus->emoji_extension = NULL;
|
||||
|
||||
ibus->keymap = ibus_keymap_get ("us");
|
||||
|
||||
|
@ -650,11 +792,11 @@ bus_ibus_impl_set_context_engine_from_desc (BusIBusImpl *ibus,
|
|||
}
|
||||
|
||||
static void
|
||||
_context_panel_extension_cb (BusInputContext *context,
|
||||
GVariant *parameters,
|
||||
BusIBusImpl *ibus)
|
||||
_context_panel_extension_cb (BusInputContext *context,
|
||||
IBusExtensionEvent *event,
|
||||
BusIBusImpl *ibus)
|
||||
{
|
||||
bus_ibus_impl_panel_extension_received (ibus, parameters);
|
||||
bus_ibus_impl_set_panel_extension_mode (ibus, event);
|
||||
}
|
||||
|
||||
const static struct {
|
||||
|
@ -694,13 +836,18 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
|
|||
if (engine) {
|
||||
g_object_ref (engine);
|
||||
bus_input_context_set_engine (ibus->focused_context, NULL);
|
||||
bus_input_context_set_emoji_extension (ibus->focused_context,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (ibus->panel != NULL)
|
||||
bus_panel_proxy_focus_out (ibus->panel, ibus->focused_context);
|
||||
if (ibus->extension != NULL)
|
||||
bus_panel_proxy_focus_out (ibus->extension, ibus->focused_context);
|
||||
if (ibus->emoji_extension != NULL) {
|
||||
bus_panel_proxy_focus_out (ibus->emoji_extension,
|
||||
ibus->focused_context);
|
||||
}
|
||||
bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
|
||||
|
||||
bus_input_context_get_content_type (ibus->focused_context,
|
||||
&purpose, &hints);
|
||||
|
@ -724,6 +871,12 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
|
|||
if (engine != NULL) {
|
||||
bus_input_context_set_engine (context, engine);
|
||||
bus_input_context_enable (context);
|
||||
if (ibus->enable_emoji_extension) {
|
||||
bus_input_context_set_emoji_extension (context,
|
||||
ibus->emoji_extension);
|
||||
} else {
|
||||
bus_input_context_set_emoji_extension (context, NULL);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < G_N_ELEMENTS(context_signals); i++) {
|
||||
g_signal_connect (ibus->focused_context,
|
||||
|
@ -734,8 +887,8 @@ bus_ibus_impl_set_focused_context (BusIBusImpl *ibus,
|
|||
|
||||
if (ibus->panel != NULL)
|
||||
bus_panel_proxy_focus_in (ibus->panel, context);
|
||||
if (ibus->extension != NULL)
|
||||
bus_panel_proxy_focus_in (ibus->extension, context);
|
||||
if (ibus->emoji_extension != NULL)
|
||||
bus_panel_proxy_focus_in (ibus->emoji_extension, context);
|
||||
}
|
||||
|
||||
if (engine != NULL)
|
||||
|
@ -751,6 +904,12 @@ bus_ibus_impl_set_global_engine (BusIBusImpl *ibus,
|
|||
|
||||
if (ibus->focused_context) {
|
||||
bus_input_context_set_engine (ibus->focused_context, engine);
|
||||
if (ibus->enable_emoji_extension) {
|
||||
bus_input_context_set_emoji_extension (ibus->focused_context,
|
||||
ibus->emoji_extension);
|
||||
} else {
|
||||
bus_input_context_set_emoji_extension (ibus->focused_context, NULL);
|
||||
}
|
||||
} else if (ibus->fake_context) {
|
||||
bus_input_context_set_engine (ibus->fake_context, engine);
|
||||
}
|
||||
|
@ -927,9 +1086,9 @@ _context_destroy_cb (BusInputContext *context,
|
|||
bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) {
|
||||
bus_panel_proxy_destroy_context (ibus->panel, context);
|
||||
}
|
||||
if (ibus->extension &&
|
||||
if (ibus->emoji_extension &&
|
||||
bus_input_context_get_capabilities (context) & IBUS_CAP_FOCUS) {
|
||||
bus_panel_proxy_destroy_context (ibus->extension, context);
|
||||
bus_panel_proxy_destroy_context (ibus->emoji_extension, context);
|
||||
}
|
||||
|
||||
ibus->contexts = g_list_remove (ibus->contexts, context);
|
||||
|
@ -1489,6 +1648,7 @@ _ibus_set_global_engine_ready_cb (BusInputContext *context,
|
|||
else {
|
||||
g_dbus_method_invocation_return_value (data->invocation, NULL);
|
||||
|
||||
BusEngineProxy *engine = bus_input_context_get_engine (context);
|
||||
if (ibus->use_global_engine && (context != ibus->focused_context)) {
|
||||
/* context and ibus->focused_context don't match. This means that
|
||||
* the focus is moved before _ibus_set_global_engine() asynchronous
|
||||
|
@ -1496,14 +1656,28 @@ _ibus_set_global_engine_ready_cb (BusInputContext *context,
|
|||
* being focused hasn't been updated. Update the engine here so that
|
||||
* subsequent _ibus_get_global_engine() call could return a
|
||||
* consistent engine name. */
|
||||
BusEngineProxy *engine = bus_input_context_get_engine (context);
|
||||
if (engine && ibus->focused_context != NULL) {
|
||||
g_object_ref (engine);
|
||||
bus_input_context_set_engine (context, NULL);
|
||||
bus_input_context_set_emoji_extension (context, NULL);
|
||||
bus_input_context_set_engine (ibus->focused_context, engine);
|
||||
if (ibus->enable_emoji_extension) {
|
||||
bus_input_context_set_emoji_extension (
|
||||
ibus->focused_context,
|
||||
ibus->emoji_extension);
|
||||
} else {
|
||||
bus_input_context_set_emoji_extension (
|
||||
ibus->focused_context,
|
||||
NULL);
|
||||
}
|
||||
g_object_unref (engine);
|
||||
}
|
||||
}
|
||||
if (engine && ibus->extension_register_keys) {
|
||||
bus_engine_proxy_panel_extension_register_keys (
|
||||
engine,
|
||||
ibus->extension_register_keys);
|
||||
}
|
||||
}
|
||||
|
||||
g_object_unref (ibus);
|
||||
|
@ -2013,11 +2187,12 @@ bus_ibus_impl_registry_destroy (BusIBusImpl *ibus)
|
|||
g_list_free_full (ibus->components, g_object_unref);
|
||||
ibus->components = NULL;
|
||||
|
||||
g_hash_table_destroy (ibus->engine_table);
|
||||
ibus->engine_table = NULL;
|
||||
g_clear_pointer (&ibus->engine_table, g_hash_table_destroy);
|
||||
|
||||
ibus_object_destroy (IBUS_OBJECT (ibus->registry));
|
||||
ibus->registry = NULL;
|
||||
g_clear_pointer (&ibus->registry, ibus_object_destroy);
|
||||
|
||||
if (ibus->extension_register_keys)
|
||||
g_clear_pointer (&ibus->extension_register_keys, g_variant_unref);
|
||||
}
|
||||
|
||||
static gint
|
||||
|
|
|
@ -94,6 +94,9 @@ struct _BusInputContext {
|
|||
/* content-type (primary purpose and hints) */
|
||||
guint purpose;
|
||||
guint hints;
|
||||
|
||||
BusPanelProxy *emoji_extension;
|
||||
gboolean is_extension_lookup_table;
|
||||
};
|
||||
|
||||
struct _BusInputContextClass {
|
||||
|
@ -162,16 +165,12 @@ static gboolean bus_input_context_service_set_property
|
|||
GError **error);
|
||||
static void bus_input_context_unset_engine
|
||||
(BusInputContext *context);
|
||||
static void bus_input_context_update_preedit_text
|
||||
(BusInputContext *context,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
gboolean visible,
|
||||
guint mode);
|
||||
static void bus_input_context_show_preedit_text
|
||||
(BusInputContext *context);
|
||||
(BusInputContext *context,
|
||||
gboolean is_extension);
|
||||
static void bus_input_context_hide_preedit_text
|
||||
(BusInputContext *context);
|
||||
(BusInputContext *context,
|
||||
gboolean is_extension);
|
||||
static void bus_input_context_update_auxiliary_text
|
||||
(BusInputContext *context,
|
||||
IBusText *text,
|
||||
|
@ -180,10 +179,6 @@ static void bus_input_context_show_auxiliary_text
|
|||
(BusInputContext *context);
|
||||
static void bus_input_context_hide_auxiliary_text
|
||||
(BusInputContext *context);
|
||||
static void bus_input_context_update_lookup_table
|
||||
(BusInputContext *context,
|
||||
IBusLookupTable *table,
|
||||
gboolean visible);
|
||||
static void bus_input_context_show_lookup_table
|
||||
(BusInputContext *context);
|
||||
static void bus_input_context_hide_lookup_table
|
||||
|
@ -605,10 +600,10 @@ bus_input_context_class_init (BusInputContextClass *class)
|
|||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
bus_marshal_VOID__VARIANT,
|
||||
bus_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_VARIANT);
|
||||
IBUS_TYPE_EXTENSION_EVENT);
|
||||
|
||||
text_empty = ibus_text_new_from_string ("");
|
||||
g_object_ref_sink (text_empty);
|
||||
|
@ -760,15 +755,17 @@ bus_input_context_property_changed (BusInputContext *context,
|
|||
error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* _ic_process_key_event_reply_cb:
|
||||
* _panel_process_key_event_cb:
|
||||
*
|
||||
* A GAsyncReadyCallback function to be called when bus_engine_proxy_process_key_event() is finished.
|
||||
* A GAsyncReadyCallback function to be called when
|
||||
* bus_panel_proxy_process_key_event() is finished.
|
||||
*/
|
||||
static void
|
||||
_ic_process_key_event_reply_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
GDBusMethodInvocation *invocation)
|
||||
_panel_process_key_event_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
GError *error = NULL;
|
||||
GVariant *value = g_dbus_proxy_call_finish ((GDBusProxy *)source,
|
||||
|
@ -784,6 +781,61 @@ _ic_process_key_event_reply_cb (GObject *source,
|
|||
}
|
||||
}
|
||||
|
||||
typedef struct _ProcessKeyEventData ProcessKeyEventData;
|
||||
struct _ProcessKeyEventData {
|
||||
GDBusMethodInvocation *invocation;
|
||||
BusInputContext *context;
|
||||
guint keyval;
|
||||
guint keycode;
|
||||
guint modifiers;
|
||||
};
|
||||
|
||||
/**
|
||||
* _ic_process_key_event_reply_cb:
|
||||
*
|
||||
* A GAsyncReadyCallback function to be called when
|
||||
* bus_engine_proxy_process_key_event() is finished.
|
||||
*/
|
||||
static void
|
||||
_ic_process_key_event_reply_cb (GObject *source,
|
||||
GAsyncResult *res,
|
||||
ProcessKeyEventData *data)
|
||||
{
|
||||
GDBusMethodInvocation *invocation = data->invocation;
|
||||
BusInputContext *context = data->context;
|
||||
guint keyval = data->keyval;
|
||||
guint keycode = data->keycode;
|
||||
guint modifiers = data->modifiers;
|
||||
GError *error = NULL;
|
||||
GVariant *value = g_dbus_proxy_call_finish ((GDBusProxy *)source,
|
||||
res,
|
||||
&error);
|
||||
|
||||
if (value != NULL) {
|
||||
gboolean retval = FALSE;
|
||||
g_variant_get (value, "(b)", &retval);
|
||||
if (context->emoji_extension && !retval) {
|
||||
bus_panel_proxy_process_key_event (context->emoji_extension,
|
||||
keyval,
|
||||
keycode,
|
||||
modifiers,
|
||||
(GAsyncReadyCallback)
|
||||
_panel_process_key_event_cb,
|
||||
invocation);
|
||||
} else {
|
||||
g_dbus_method_invocation_return_value (invocation, value);
|
||||
}
|
||||
g_variant_unref (value);
|
||||
}
|
||||
else {
|
||||
g_dbus_method_invocation_return_gerror (invocation, error);
|
||||
g_error_free (error);
|
||||
}
|
||||
|
||||
g_object_unref (context);
|
||||
g_slice_free (ProcessKeyEventData, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* _ic_process_key_event:
|
||||
*
|
||||
|
@ -840,12 +892,19 @@ _ic_process_key_event (BusInputContext *context,
|
|||
|
||||
/* ignore key events, if it is a fake input context */
|
||||
if (context->has_focus && context->engine && context->fake == FALSE) {
|
||||
ProcessKeyEventData *data = g_slice_new0 (ProcessKeyEventData);
|
||||
data->invocation = invocation;
|
||||
data->context = g_object_ref (context);
|
||||
data->keyval = keyval;
|
||||
data->keycode = keycode;
|
||||
data->modifiers = modifiers;
|
||||
bus_engine_proxy_process_key_event (context->engine,
|
||||
keyval,
|
||||
keycode,
|
||||
modifiers,
|
||||
(GAsyncReadyCallback) _ic_process_key_event_reply_cb,
|
||||
invocation);
|
||||
(GAsyncReadyCallback)
|
||||
_ic_process_key_event_reply_cb,
|
||||
data);
|
||||
}
|
||||
else {
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", FALSE));
|
||||
|
@ -880,6 +939,13 @@ _ic_set_cursor_location (BusInputContext *context,
|
|||
context->y,
|
||||
context->w,
|
||||
context->h);
|
||||
if (context->emoji_extension) {
|
||||
bus_panel_proxy_set_cursor_location (context->emoji_extension,
|
||||
context->x,
|
||||
context->y,
|
||||
context->w,
|
||||
context->h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -912,6 +978,14 @@ _ic_set_cursor_location_relative (BusInputContext *context,
|
|||
y,
|
||||
w,
|
||||
h);
|
||||
if (context->emoji_extension) {
|
||||
bus_panel_proxy_set_cursor_location_relative (
|
||||
context->emoji_extension,
|
||||
x,
|
||||
y,
|
||||
w,
|
||||
h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1394,7 +1468,7 @@ bus_input_context_clear_preedit_text (BusInputContext *context)
|
|||
|
||||
/* always clear preedit text */
|
||||
bus_input_context_update_preedit_text (context,
|
||||
text_empty, 0, FALSE, IBUS_ENGINE_PREEDIT_CLEAR);
|
||||
text_empty, 0, FALSE, IBUS_ENGINE_PREEDIT_CLEAR, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -1407,7 +1481,10 @@ bus_input_context_focus_out (BusInputContext *context)
|
|||
|
||||
bus_input_context_clear_preedit_text (context);
|
||||
bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
|
||||
bus_input_context_update_lookup_table (context, lookup_table_empty, FALSE);
|
||||
bus_input_context_update_lookup_table (context,
|
||||
lookup_table_empty,
|
||||
FALSE,
|
||||
FALSE);
|
||||
bus_input_context_register_properties (context, props_empty);
|
||||
|
||||
if (context->engine) {
|
||||
|
@ -1427,7 +1504,12 @@ bus_input_context_focus_out (BusInputContext *context)
|
|||
{ \
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context)); \
|
||||
\
|
||||
if (context->has_focus && context->engine) { \
|
||||
if (context->is_extension_lookup_table && \
|
||||
context->emoji_extension) { \
|
||||
bus_panel_proxy_##name##_lookup_table (context->emoji_extension); \
|
||||
return; \
|
||||
} \
|
||||
if (context->has_focus && context->engine) { \
|
||||
bus_engine_proxy_##name (context->engine); \
|
||||
} \
|
||||
}
|
||||
|
@ -1447,6 +1529,14 @@ bus_input_context_candidate_clicked (BusInputContext *context,
|
|||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (context->is_extension_lookup_table && context->emoji_extension) {
|
||||
bus_panel_proxy_candidate_clicked_lookup_table (
|
||||
context->emoji_extension,
|
||||
index,
|
||||
button,
|
||||
state);
|
||||
return;
|
||||
}
|
||||
if (context->engine) {
|
||||
bus_engine_proxy_candidate_clicked (context->engine,
|
||||
index,
|
||||
|
@ -1467,62 +1557,34 @@ bus_input_context_property_activate (BusInputContext *context,
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bus_input_context_update_preedit_text:
|
||||
*
|
||||
* Update a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
|
||||
*/
|
||||
static void
|
||||
bus_input_context_update_preedit_text (BusInputContext *context,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
gboolean visible,
|
||||
guint mode)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (context->preedit_text) {
|
||||
g_object_unref (context->preedit_text);
|
||||
}
|
||||
|
||||
context->preedit_text = (IBusText *) g_object_ref_sink (text ? text : text_empty);
|
||||
context->preedit_cursor_pos = cursor_pos;
|
||||
context->preedit_visible = visible;
|
||||
context->preedit_mode = mode;
|
||||
|
||||
if (PREEDIT_CONDITION) {
|
||||
GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)context->preedit_text);
|
||||
bus_input_context_emit_signal (context,
|
||||
"UpdatePreeditText",
|
||||
g_variant_new ("(vub)", variant, context->preedit_cursor_pos, context->preedit_visible),
|
||||
NULL);
|
||||
}
|
||||
else {
|
||||
g_signal_emit (context,
|
||||
context_signals[UPDATE_PREEDIT_TEXT],
|
||||
0,
|
||||
context->preedit_text,
|
||||
context->preedit_cursor_pos,
|
||||
context->preedit_visible);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bus_input_context_show_preedit_text:
|
||||
*
|
||||
* Show a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
|
||||
*/
|
||||
static void
|
||||
bus_input_context_show_preedit_text (BusInputContext *context)
|
||||
bus_input_context_show_preedit_text (BusInputContext *context,
|
||||
gboolean is_extension)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (context->preedit_visible) {
|
||||
if (context->preedit_visible)
|
||||
return;
|
||||
if (!is_extension && context->emoji_extension)
|
||||
return;
|
||||
|
||||
if (!is_extension)
|
||||
context->preedit_visible = TRUE;
|
||||
|
||||
if (context->emoji_extension && !is_extension) {
|
||||
/* Do not use HIDE_PREEDIT_TEXT signal below but call
|
||||
* bus_panel_proxy_hide_preedit_text() directly for the extension only
|
||||
* but not for the normal panel.
|
||||
*/
|
||||
bus_panel_proxy_show_preedit_text (context->emoji_extension);
|
||||
return;
|
||||
}
|
||||
|
||||
context->preedit_visible = TRUE;
|
||||
|
||||
if (PREEDIT_CONDITION) {
|
||||
bus_input_context_emit_signal (context,
|
||||
"ShowPreeditText",
|
||||
|
@ -1542,16 +1604,26 @@ bus_input_context_show_preedit_text (BusInputContext *context)
|
|||
* Hide a preedit text. Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
|
||||
*/
|
||||
static void
|
||||
bus_input_context_hide_preedit_text (BusInputContext *context)
|
||||
bus_input_context_hide_preedit_text (BusInputContext *context,
|
||||
gboolean is_extension)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (!context->preedit_visible) {
|
||||
if (!is_extension && !context->preedit_visible)
|
||||
return;
|
||||
|
||||
if (!is_extension)
|
||||
context->preedit_visible = FALSE;
|
||||
|
||||
if (context->emoji_extension && !is_extension) {
|
||||
/* Do not use HIDE_PREEDIT_TEXT signal below but call
|
||||
* bus_panel_proxy_hide_preedit_text() directly for the extension only
|
||||
* but not for the normal panel.
|
||||
*/
|
||||
bus_panel_proxy_hide_preedit_text (context->emoji_extension);
|
||||
return;
|
||||
}
|
||||
|
||||
context->preedit_visible = FALSE;
|
||||
|
||||
if (PREEDIT_CONDITION) {
|
||||
bus_input_context_emit_signal (context,
|
||||
"HidePreeditText",
|
||||
|
@ -1658,19 +1730,15 @@ bus_input_context_hide_auxiliary_text (BusInputContext *context)
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* bus_input_context_update_lookup_table:
|
||||
*
|
||||
* Update contents in the lookup table.
|
||||
* Send D-Bus signal to update status of client or send glib signal to the panel, depending on capabilities of the client.
|
||||
*/
|
||||
static void
|
||||
void
|
||||
bus_input_context_update_lookup_table (BusInputContext *context,
|
||||
IBusLookupTable *table,
|
||||
gboolean visible)
|
||||
gboolean visible,
|
||||
gboolean is_extension)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
context->is_extension_lookup_table = is_extension;
|
||||
if (context->lookup_table) {
|
||||
g_object_unref (context->lookup_table);
|
||||
}
|
||||
|
@ -2035,7 +2103,9 @@ _engine_update_preedit_text_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
bus_input_context_update_preedit_text (context, text, cursor_pos, visible, mode);
|
||||
bus_input_context_update_preedit_text (context, text,
|
||||
cursor_pos, visible, mode,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2075,7 +2145,7 @@ _engine_update_lookup_table_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
bus_input_context_update_lookup_table (context, table, visible);
|
||||
bus_input_context_update_lookup_table (context, table, visible, FALSE);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2123,11 +2193,35 @@ _engine_update_property_cb (BusEngineProxy *engine,
|
|||
* from the engine object.
|
||||
*/
|
||||
static void
|
||||
_engine_panel_extension_cb (BusEngineProxy *engine,
|
||||
GVariant *parameters,
|
||||
BusInputContext *context)
|
||||
_engine_panel_extension_cb (BusEngineProxy *engine,
|
||||
IBusExtensionEvent *event,
|
||||
BusInputContext *context)
|
||||
{
|
||||
g_signal_emit (context, context_signals[PANEL_EXTENSION], 0, parameters);
|
||||
g_signal_emit (context, context_signals[PANEL_EXTENSION], 0, event);
|
||||
}
|
||||
|
||||
static void
|
||||
_engine_show_preedit_text_cb (BusEngineProxy *engine,
|
||||
BusInputContext *context)
|
||||
{
|
||||
g_assert (BUS_IS_ENGINE_PROXY (engine));
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
bus_input_context_show_preedit_text (context, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_engine_hide_preedit_text_cb (BusEngineProxy *engine,
|
||||
BusInputContext *context)
|
||||
{
|
||||
g_assert (BUS_IS_ENGINE_PROXY (engine));
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
bus_input_context_hide_preedit_text (context, FALSE);
|
||||
}
|
||||
|
||||
#define DEFINE_FUNCTION(name) \
|
||||
|
@ -2143,8 +2237,6 @@ _engine_panel_extension_cb (BusEngineProxy *engine,
|
|||
bus_input_context_##name (context); \
|
||||
}
|
||||
|
||||
DEFINE_FUNCTION (show_preedit_text)
|
||||
DEFINE_FUNCTION (hide_preedit_text)
|
||||
DEFINE_FUNCTION (show_auxiliary_text)
|
||||
DEFINE_FUNCTION (hide_auxiliary_text)
|
||||
DEFINE_FUNCTION (show_lookup_table)
|
||||
|
@ -2239,7 +2331,10 @@ bus_input_context_disable (BusInputContext *context)
|
|||
|
||||
bus_input_context_clear_preedit_text (context);
|
||||
bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
|
||||
bus_input_context_update_lookup_table (context, lookup_table_empty, FALSE);
|
||||
bus_input_context_update_lookup_table (context,
|
||||
lookup_table_empty,
|
||||
FALSE,
|
||||
FALSE);
|
||||
bus_input_context_register_properties (context, props_empty);
|
||||
|
||||
if (context->engine) {
|
||||
|
@ -2283,7 +2378,10 @@ bus_input_context_unset_engine (BusInputContext *context)
|
|||
|
||||
bus_input_context_clear_preedit_text (context);
|
||||
bus_input_context_update_auxiliary_text (context, text_empty, FALSE);
|
||||
bus_input_context_update_lookup_table (context, lookup_table_empty, FALSE);
|
||||
bus_input_context_update_lookup_table (context,
|
||||
lookup_table_empty,
|
||||
FALSE,
|
||||
FALSE);
|
||||
bus_input_context_register_properties (context, props_empty);
|
||||
|
||||
if (context->engine) {
|
||||
|
@ -2639,17 +2737,128 @@ bus_input_context_set_content_type (BusInputContext *context,
|
|||
}
|
||||
|
||||
void
|
||||
bus_input_context_commit_text (BusInputContext *context,
|
||||
IBusText *text)
|
||||
bus_input_context_commit_text_use_extension (BusInputContext *context,
|
||||
IBusText *text,
|
||||
gboolean use_extension)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (text == text_empty || text == NULL)
|
||||
return;
|
||||
|
||||
GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
|
||||
bus_input_context_emit_signal (context,
|
||||
"CommitText",
|
||||
g_variant_new ("(v)", variant),
|
||||
NULL);
|
||||
if (use_extension && context->emoji_extension) {
|
||||
bus_panel_proxy_commit_text_received (context->emoji_extension, text);
|
||||
} else {
|
||||
GVariant *variant = ibus_serializable_serialize (
|
||||
(IBusSerializable *)text);
|
||||
bus_input_context_emit_signal (context,
|
||||
"CommitText",
|
||||
g_variant_new ("(v)", variant),
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bus_input_context_commit_text (BusInputContext *context,
|
||||
IBusText *text)
|
||||
{
|
||||
bus_input_context_commit_text_use_extension (context, text, TRUE);
|
||||
}
|
||||
|
||||
void
|
||||
bus_input_context_update_preedit_text (BusInputContext *context,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
gboolean visible,
|
||||
guint mode,
|
||||
gboolean use_extension)
|
||||
{
|
||||
gboolean extension_visible = FALSE;
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (context->preedit_text) {
|
||||
g_object_unref (context->preedit_text);
|
||||
}
|
||||
|
||||
context->preedit_text = (IBusText *) g_object_ref_sink (text ? text :
|
||||
text_empty);
|
||||
context->preedit_cursor_pos = cursor_pos;
|
||||
if (use_extension)
|
||||
context->preedit_visible = visible;
|
||||
if (use_extension)
|
||||
context->preedit_mode = mode;
|
||||
extension_visible = context->preedit_visible |
|
||||
(context->emoji_extension != NULL);
|
||||
|
||||
if (use_extension && context->emoji_extension) {
|
||||
bus_panel_proxy_update_preedit_text (context->emoji_extension,
|
||||
context->preedit_text,
|
||||
context->preedit_cursor_pos,
|
||||
context->preedit_visible);
|
||||
} else if (PREEDIT_CONDITION) {
|
||||
GVariant *variant = ibus_serializable_serialize (
|
||||
(IBusSerializable *)context->preedit_text);
|
||||
bus_input_context_emit_signal (context,
|
||||
"UpdatePreeditText",
|
||||
g_variant_new (
|
||||
"(vub)",
|
||||
variant,
|
||||
context->preedit_cursor_pos,
|
||||
extension_visible),
|
||||
NULL);
|
||||
} else {
|
||||
g_signal_emit (context,
|
||||
context_signals[UPDATE_PREEDIT_TEXT],
|
||||
0,
|
||||
context->preedit_text,
|
||||
context->preedit_cursor_pos,
|
||||
extension_visible);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bus_input_context_set_emoji_extension (BusInputContext *context,
|
||||
BusPanelProxy *emoji_extension)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (context->emoji_extension)
|
||||
g_object_unref (context->emoji_extension);
|
||||
context->emoji_extension = emoji_extension;
|
||||
if (emoji_extension) {
|
||||
g_object_ref (context->emoji_extension);
|
||||
if (!context->connection)
|
||||
return;
|
||||
bus_input_context_show_preedit_text (context, TRUE);
|
||||
bus_panel_proxy_set_cursor_location (context->emoji_extension,
|
||||
context->x,
|
||||
context->y,
|
||||
context->w,
|
||||
context->h);
|
||||
} else {
|
||||
if (!context->connection)
|
||||
return;
|
||||
/* https://gitlab.gnome.org/GNOME/gnome-shell/merge_requests/113
|
||||
* Cannot use bus_input_context_hide_preedit_text () yet.
|
||||
*/
|
||||
if (!context->preedit_visible) {
|
||||
bus_input_context_update_preedit_text (context,
|
||||
text_empty,
|
||||
0,
|
||||
FALSE,
|
||||
IBUS_ENGINE_PREEDIT_CLEAR,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bus_input_context_panel_extension_received (BusInputContext *context,
|
||||
IBusExtensionEvent *event)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (!context->engine)
|
||||
return;
|
||||
bus_engine_proxy_panel_extension_received (context->engine, event);
|
||||
}
|
||||
|
|
|
@ -28,6 +28,11 @@
|
|||
#include "connection.h"
|
||||
#include "factoryproxy.h"
|
||||
|
||||
#ifndef __BUS_PANEL_PROXY_DEFINED
|
||||
#define __BUS_PANEL_PROXY_DEFINED
|
||||
typedef struct _BusPanelProxy BusPanelProxy;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Type macros.
|
||||
*/
|
||||
|
@ -63,6 +68,7 @@ BusInputContext *bus_input_context_new (BusConnection *connection,
|
|||
|
||||
/**
|
||||
* bus_input_context_focus_in:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Give a focus to the context. Call FocusIn, Enable, SetCapabilities,
|
||||
* and SetCursorLocation methods of the engine for the context,
|
||||
|
@ -73,6 +79,7 @@ void bus_input_context_focus_in (BusInputContext *context);
|
|||
|
||||
/**
|
||||
* bus_input_context_focus_out:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Remove a focus from the context. Call FocusOut method of the engine for
|
||||
* the context.
|
||||
|
@ -83,6 +90,7 @@ void bus_input_context_focus_out
|
|||
|
||||
/**
|
||||
* bus_input_context_has_focus:
|
||||
* @context: A #BusInputContext.
|
||||
* @returns: context->has_focus.
|
||||
*/
|
||||
gboolean bus_input_context_has_focus
|
||||
|
@ -90,6 +98,7 @@ gboolean bus_input_context_has_focus
|
|||
|
||||
/**
|
||||
* bus_input_context_enable:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Enable the current engine for the context. Request an engine (if needed),
|
||||
* call FocusIn, Enable, SetCapabilities, and SetCursorLocation methods
|
||||
|
@ -100,6 +109,7 @@ void bus_input_context_enable (BusInputContext *context);
|
|||
|
||||
/**
|
||||
* bus_input_context_disable:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Disable the current engine for the context. Request an engine (if needed),
|
||||
* call FocusIn, Enable, SetCapabilities, and SetCursorLocation methods
|
||||
|
@ -110,6 +120,7 @@ void bus_input_context_disable (BusInputContext *context);
|
|||
|
||||
/**
|
||||
* bus_input_context_page_up:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Call page_up method of the current engine proxy.
|
||||
*/
|
||||
|
@ -117,6 +128,7 @@ void bus_input_context_page_up (BusInputContext *context);
|
|||
|
||||
/**
|
||||
* bus_input_context_page_down:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Call page_down method of the current engine proxy.
|
||||
*/
|
||||
|
@ -125,6 +137,7 @@ void bus_input_context_page_down
|
|||
|
||||
/**
|
||||
* bus_input_context_cursor_up:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Call cursor_up method of the current engine proxy.
|
||||
*/
|
||||
|
@ -133,6 +146,7 @@ void bus_input_context_cursor_up
|
|||
|
||||
/**
|
||||
* bus_input_context_cursor_down:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Call cursor_down method of the current engine proxy.
|
||||
*/
|
||||
|
@ -141,6 +155,10 @@ void bus_input_context_cursor_down
|
|||
|
||||
/**
|
||||
* bus_input_context_candidate_clicked:
|
||||
* @context: A #BusInputContext.
|
||||
* @index: An index.
|
||||
* @button: A button number.
|
||||
* @state: A button state.
|
||||
*
|
||||
* Call candidate_clicked method of the current engine proxy.
|
||||
*/
|
||||
|
@ -152,6 +170,8 @@ void bus_input_context_candidate_clicked
|
|||
|
||||
/**
|
||||
* bus_input_context_set_engine:
|
||||
* @context: A #BusInputContext.
|
||||
* @engine: A #BusEngineProxy.
|
||||
*
|
||||
* Use the engine on the context.
|
||||
*/
|
||||
|
@ -161,12 +181,14 @@ void bus_input_context_set_engine
|
|||
|
||||
/**
|
||||
* bus_input_context_set_engine_by_desc:
|
||||
* @context: A #BusInputContext.
|
||||
* @desc: the engine to use on the context.
|
||||
* @timeout: timeout (in ms) for D-Bus calls.
|
||||
* @callback: a function to be called when bus_input_context_set_engine_by_desc
|
||||
* is finished. if NULL, the default callback
|
||||
* function, which just calls
|
||||
* bus_input_context_set_engine_by_desc_finish, is used.
|
||||
* @user_data: an argument of @callback.
|
||||
*
|
||||
* Create a new BusEngineProxy object and use it on the context.
|
||||
*/
|
||||
|
@ -181,6 +203,9 @@ void bus_input_context_set_engine_by_desc
|
|||
|
||||
/**
|
||||
* bus_input_context_set_engine_by_desc_finish:
|
||||
* @context: A #BusInputContext.
|
||||
* @res: A #GAsyncResult.
|
||||
* @error: A #GError.
|
||||
*
|
||||
* A function to be called by the GAsyncReadyCallback function for
|
||||
* bus_input_context_set_engine_by_desc.
|
||||
|
@ -192,6 +217,7 @@ gboolean bus_input_context_set_engine_by_desc_finish
|
|||
|
||||
/**
|
||||
* bus_input_context_get_engine:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Get a BusEngineProxy object of the current engine.
|
||||
*/
|
||||
|
@ -200,6 +226,7 @@ BusEngineProxy *bus_input_context_get_engine
|
|||
|
||||
/**
|
||||
* bus_input_context_get_engine_desc:
|
||||
* @context: A #BusInputContext.
|
||||
*
|
||||
* Get an IBusEngineDesc object of the current engine.
|
||||
*/
|
||||
|
@ -208,6 +235,9 @@ IBusEngineDesc *bus_input_context_get_engine_desc
|
|||
|
||||
/**
|
||||
* bus_input_context_property_activate:
|
||||
* @context: A #BusInputContext.
|
||||
* @prop_name: A property name.
|
||||
* @prop_state: A property state.
|
||||
*
|
||||
* Call property_activate method of the current engine proxy.
|
||||
*/
|
||||
|
@ -219,6 +249,7 @@ void bus_input_context_property_activate
|
|||
|
||||
/**
|
||||
* bus_input_context_get_capabilities:
|
||||
* @context: A #BusInputContext.
|
||||
* @returns: context->capabilities.
|
||||
*/
|
||||
guint bus_input_context_get_capabilities
|
||||
|
@ -226,6 +257,8 @@ guint bus_input_context_get_capabilities
|
|||
|
||||
/**
|
||||
* bus_input_context_set_capabilities:
|
||||
* @context: A #BusInputContext.
|
||||
* @capabilities: capabilities.
|
||||
*
|
||||
* Call set_capabilities method of the current engine proxy.
|
||||
*/
|
||||
|
@ -236,6 +269,7 @@ void bus_input_context_set_capabilities
|
|||
|
||||
/**
|
||||
* bus_input_context_get_client:
|
||||
* @context: A #BusInputContext.
|
||||
* @returns: context->client.
|
||||
*/
|
||||
const gchar *bus_input_context_get_client
|
||||
|
@ -243,6 +277,7 @@ const gchar *bus_input_context_get_client
|
|||
|
||||
/**
|
||||
* bus_input_context_get_content_type:
|
||||
* @context: A #BusInputContext.
|
||||
* @purpose: Input purpose.
|
||||
* @hints: Input hints.
|
||||
*/
|
||||
|
@ -253,6 +288,7 @@ void bus_input_context_get_content_type
|
|||
|
||||
/**
|
||||
* bus_input_context_set_content_type:
|
||||
* @context: A #BusInputContext.
|
||||
* @purpose: Input purpose.
|
||||
* @hints: Input hints.
|
||||
*/
|
||||
|
@ -263,11 +299,83 @@ void bus_input_context_set_content_type
|
|||
|
||||
/**
|
||||
* bus_input_context_commit_text:
|
||||
* @text: a commited text.
|
||||
* @context: A #BusInputContext.
|
||||
* @text: A committed text.
|
||||
*/
|
||||
void bus_input_context_commit_text
|
||||
(BusInputContext *context,
|
||||
IBusText *text);
|
||||
|
||||
/**
|
||||
* bus_input_context_commit_text:
|
||||
* @context: A #BusInputContext.
|
||||
* @text: A committed text.
|
||||
* @use_extension: Use an extension if it's %TRUE and the extension is
|
||||
* available.
|
||||
*/
|
||||
void bus_input_context_commit_text_use_extension
|
||||
(BusInputContext *context,
|
||||
IBusText *text,
|
||||
gboolean use_extension);
|
||||
|
||||
/**
|
||||
* bus_input_context_set_emoji_extension:
|
||||
* @context: A #BusInputContext.
|
||||
* @extension: A #BusPanelProxy.
|
||||
*/
|
||||
void bus_input_context_set_emoji_extension
|
||||
(BusInputContext *context,
|
||||
BusPanelProxy *extension);
|
||||
|
||||
/**
|
||||
* bus_input_context_update_preedit_text:
|
||||
* @context: A #BusInputContext.
|
||||
* @text: An #IBusText.
|
||||
* @cursor_pos: The cursor position.
|
||||
* @visible: %TRUE if the preedit is visible. Otherwise %FALSE.
|
||||
* @mode: The preedit commit mode.
|
||||
* @use_extension: %TRUE if preedit text is sent to the extesion at first.
|
||||
*
|
||||
* Update a preedit text. Send D-Bus signal to update status of client or
|
||||
* send glib signal to the panel, depending on capabilities of the client.
|
||||
*/
|
||||
void bus_input_context_update_preedit_text
|
||||
(BusInputContext *context,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
gboolean visible,
|
||||
guint mode,
|
||||
gboolean
|
||||
use_extension);
|
||||
|
||||
/**
|
||||
* bus_input_context_update_lookup_table:
|
||||
* @context: A #BusInputContext.
|
||||
* @table: An #IBusTable.
|
||||
* @visible: %TRUE if the lookup table is visible. Otherwise %FALSE.
|
||||
* @is_extension: %TRUE if the lookup table is created by panel extensions.
|
||||
*
|
||||
* Update contents in the lookup table.
|
||||
* Send D-Bus signal to update status of client or send glib signal to the
|
||||
* panel, depending on capabilities of the client.
|
||||
*/
|
||||
void bus_input_context_update_lookup_table
|
||||
(BusInputContext *context,
|
||||
IBusLookupTable *table,
|
||||
gboolean visible,
|
||||
gboolean
|
||||
is_extension);
|
||||
|
||||
|
||||
/**
|
||||
* bus_input_context_panel_extension_received:
|
||||
* @context: A #BusInputContext.
|
||||
* @event: An #IBusExtensionEvent.
|
||||
*
|
||||
* Send An #IBusExtensionEvent callback from an extension.
|
||||
*/
|
||||
void bus_input_context_panel_extension_received
|
||||
(BusInputContext *context,
|
||||
IBusExtensionEvent *event);
|
||||
G_END_DECLS
|
||||
#endif
|
||||
|
|
210
bus/panelproxy.c
210
bus/panelproxy.c
|
@ -52,6 +52,10 @@ enum {
|
|||
PROPERTY_HIDE,
|
||||
COMMIT_TEXT,
|
||||
PANEL_EXTENSION,
|
||||
PANEL_EXTENSION_REGISTER_KEYS,
|
||||
UPDATE_PREEDIT_TEXT_RECEIVED,
|
||||
UPDATE_LOOKUP_TABLE_RECEIVED,
|
||||
UPDATE_AUXILIARY_TEXT_RECEIVED,
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
|
@ -125,8 +129,8 @@ bus_panel_proxy_new (BusConnection *connection,
|
|||
case PANEL_TYPE_PANEL:
|
||||
path = IBUS_PATH_PANEL;
|
||||
break;
|
||||
case PANEL_TYPE_EXTENSION:
|
||||
path = IBUS_PATH_PANEL_EXTENSION;
|
||||
case PANEL_TYPE_EXTENSION_EMOJI:
|
||||
path = IBUS_PATH_PANEL_EXTENSION_EMOJI;
|
||||
break;
|
||||
default:
|
||||
g_return_val_if_reached (NULL);
|
||||
|
@ -253,6 +257,16 @@ bus_panel_proxy_class_init (BusPanelProxyClass *class)
|
|||
|
||||
panel_signals[PANEL_EXTENSION] =
|
||||
g_signal_new (I_("panel-extension"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
bus_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE, 1,
|
||||
IBUS_TYPE_EXTENSION_EVENT);
|
||||
|
||||
panel_signals[PANEL_EXTENSION_REGISTER_KEYS] =
|
||||
g_signal_new (I_("panel-extension-register-keys"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
|
@ -260,6 +274,40 @@ bus_panel_proxy_class_init (BusPanelProxyClass *class)
|
|||
bus_marshal_VOID__VARIANT,
|
||||
G_TYPE_NONE, 1,
|
||||
G_TYPE_VARIANT);
|
||||
|
||||
panel_signals[UPDATE_PREEDIT_TEXT_RECEIVED] =
|
||||
g_signal_new (I_("update-preedit-text-received"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
bus_marshal_VOID__OBJECT_UINT_BOOLEAN,
|
||||
G_TYPE_NONE, 3,
|
||||
IBUS_TYPE_TEXT,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
panel_signals[UPDATE_LOOKUP_TABLE_RECEIVED] =
|
||||
g_signal_new (I_("update-lookup-table-received"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
bus_marshal_VOID__OBJECT_BOOLEAN,
|
||||
G_TYPE_NONE, 2,
|
||||
IBUS_TYPE_LOOKUP_TABLE,
|
||||
G_TYPE_BOOLEAN);
|
||||
|
||||
panel_signals[UPDATE_AUXILIARY_TEXT_RECEIVED] =
|
||||
g_signal_new (I_("update-auxiliary-text-received"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
bus_marshal_VOID__OBJECT_BOOLEAN,
|
||||
G_TYPE_NONE, 2,
|
||||
IBUS_TYPE_TEXT,
|
||||
G_TYPE_BOOLEAN);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -355,23 +403,83 @@ bus_panel_proxy_g_signal (GDBusProxy *proxy,
|
|||
|
||||
if (g_strcmp0 ("CommitText", signal_name) == 0) {
|
||||
GVariant *arg0 = NULL;
|
||||
g_variant_get (parameters, "(v)", &arg0);
|
||||
g_return_if_fail (arg0 != NULL);
|
||||
|
||||
g_variant_get (parameters, "(v)", &arg0);
|
||||
g_return_if_fail (arg0);
|
||||
IBusText *text = IBUS_TEXT (ibus_serializable_deserialize (arg0));
|
||||
g_variant_unref (arg0);
|
||||
g_return_if_fail (text != NULL);
|
||||
g_return_if_fail (text);
|
||||
g_signal_emit (panel, panel_signals[COMMIT_TEXT], 0, text);
|
||||
_g_object_unref_if_floating (text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 ("PanelExtension", signal_name) == 0) {
|
||||
if (panel->panel_type != PANEL_TYPE_PANEL) {
|
||||
g_warning ("Wrong signal");
|
||||
return;
|
||||
}
|
||||
g_signal_emit (panel, panel_signals[PANEL_EXTENSION], 0, parameters);
|
||||
GVariant *arg0 = NULL;
|
||||
|
||||
g_variant_get (parameters, "(v)", &arg0);
|
||||
g_return_if_fail (arg0);
|
||||
IBusExtensionEvent *event = IBUS_EXTENSION_EVENT (
|
||||
ibus_serializable_deserialize (arg0));
|
||||
g_variant_unref (arg0);
|
||||
g_return_if_fail (event);
|
||||
g_signal_emit (panel, panel_signals[PANEL_EXTENSION], 0, event);
|
||||
_g_object_unref_if_floating (event);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 ("PanelExtensionRegisterKeys", signal_name) == 0) {
|
||||
g_signal_emit (panel, panel_signals[PANEL_EXTENSION_REGISTER_KEYS], 0,
|
||||
parameters);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 ("UpdatePreeditTextReceived", signal_name) == 0) {
|
||||
GVariant *variant = NULL;
|
||||
guint cursor_pos = 0;
|
||||
gboolean visible = FALSE;
|
||||
IBusText *text = NULL;
|
||||
|
||||
g_variant_get (parameters, "(vub)", &variant, &cursor_pos, &visible);
|
||||
g_return_if_fail (variant);
|
||||
text = (IBusText *) ibus_serializable_deserialize (variant);
|
||||
g_variant_unref (variant);
|
||||
g_return_if_fail (text);
|
||||
g_signal_emit (panel, panel_signals[UPDATE_PREEDIT_TEXT_RECEIVED], 0,
|
||||
text, cursor_pos, visible);
|
||||
_g_object_unref_if_floating (text);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 ("UpdateLookupTableReceived", signal_name) == 0) {
|
||||
GVariant *variant = NULL;
|
||||
gboolean visible = FALSE;
|
||||
IBusLookupTable *table = NULL;
|
||||
|
||||
g_variant_get (parameters, "(vb)", &variant, &visible);
|
||||
g_return_if_fail (variant);
|
||||
table = (IBusLookupTable *) ibus_serializable_deserialize (variant);
|
||||
g_variant_unref (variant);
|
||||
g_return_if_fail (table);
|
||||
g_signal_emit (panel, panel_signals[UPDATE_LOOKUP_TABLE_RECEIVED], 0,
|
||||
table, visible);
|
||||
_g_object_unref_if_floating (table);
|
||||
return;
|
||||
}
|
||||
|
||||
if (g_strcmp0 ("UpdateAuxiliaryTextReceived", signal_name) == 0) {
|
||||
GVariant *variant = NULL;
|
||||
gboolean visible = FALSE;
|
||||
IBusText *text = NULL;
|
||||
|
||||
g_variant_get (parameters, "(vb)", &variant, &visible);
|
||||
g_return_if_fail (variant);
|
||||
text = (IBusText *) ibus_serializable_deserialize (variant);
|
||||
g_variant_unref (variant);
|
||||
g_return_if_fail (text);
|
||||
g_signal_emit (panel, panel_signals[UPDATE_AUXILIARY_TEXT_RECEIVED], 0,
|
||||
text, visible);
|
||||
_g_object_unref_if_floating (text);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -552,12 +660,17 @@ static void
|
|||
bus_panel_proxy_commit_text (BusPanelProxy *panel,
|
||||
IBusText *text)
|
||||
{
|
||||
gboolean use_extension = TRUE;
|
||||
g_assert (BUS_IS_PANEL_PROXY (panel));
|
||||
g_assert (text != NULL);
|
||||
|
||||
if (panel->focused_context) {
|
||||
bus_input_context_commit_text (panel->focused_context, text);
|
||||
}
|
||||
if (!panel->focused_context)
|
||||
return;
|
||||
if (panel->panel_type != PANEL_TYPE_PANEL)
|
||||
use_extension = FALSE;
|
||||
bus_input_context_commit_text_use_extension (panel->focused_context,
|
||||
text,
|
||||
use_extension);
|
||||
}
|
||||
|
||||
#define DEFINE_FUNCTION(Name, name) \
|
||||
|
@ -877,3 +990,74 @@ bus_panel_proxy_get_panel_type (BusPanelProxy *panel)
|
|||
g_assert (BUS_IS_PANEL_PROXY (panel));
|
||||
return panel->panel_type;
|
||||
}
|
||||
|
||||
void
|
||||
bus_panel_proxy_panel_extension_received (BusPanelProxy *panel,
|
||||
IBusExtensionEvent *event)
|
||||
{
|
||||
GVariant *data;
|
||||
|
||||
g_assert (BUS_IS_PANEL_PROXY (panel));
|
||||
g_assert (event);
|
||||
|
||||
data = ibus_serializable_serialize (IBUS_SERIALIZABLE (event));
|
||||
g_return_if_fail (data);
|
||||
g_dbus_proxy_call ((GDBusProxy *)panel,
|
||||
"PanelExtensionReceived",
|
||||
g_variant_new ("(v)", data),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
bus_panel_proxy_process_key_event (BusPanelProxy *panel,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
guint state,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_assert (BUS_IS_PANEL_PROXY (panel));
|
||||
|
||||
g_dbus_proxy_call ((GDBusProxy *)panel,
|
||||
"ProcessKeyEvent",
|
||||
g_variant_new ("(uuu)", keyval, keycode, state),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1,
|
||||
NULL,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
void
|
||||
bus_panel_proxy_commit_text_received (BusPanelProxy *panel,
|
||||
IBusText *text)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
g_assert (BUS_IS_PANEL_PROXY (panel));
|
||||
g_assert (IBUS_IS_TEXT (text));
|
||||
|
||||
variant = ibus_serializable_serialize (IBUS_SERIALIZABLE (text));
|
||||
g_dbus_proxy_call ((GDBusProxy *)panel,
|
||||
"CommitTextReceived",
|
||||
g_variant_new ("(v)", variant),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
bus_panel_proxy_candidate_clicked_lookup_table (BusPanelProxy *panel,
|
||||
guint index,
|
||||
guint button,
|
||||
guint state)
|
||||
{
|
||||
gboolean use_extension = TRUE;
|
||||
g_assert (BUS_IS_PANEL_PROXY (panel));
|
||||
|
||||
g_dbus_proxy_call ((GDBusProxy *)panel,
|
||||
"CandidateClickedLookupTable",
|
||||
g_variant_new ("(uuu)", index, button, state),
|
||||
G_DBUS_CALL_FLAGS_NONE,
|
||||
-1, NULL, NULL, NULL);
|
||||
}
|
||||
|
|
|
@ -55,7 +55,7 @@ typedef enum
|
|||
{
|
||||
PANEL_TYPE_NONE,
|
||||
PANEL_TYPE_PANEL,
|
||||
PANEL_TYPE_EXTENSION
|
||||
PANEL_TYPE_EXTENSION_EMOJI
|
||||
} PanelType;
|
||||
|
||||
typedef struct _BusPanelProxy BusPanelProxy;
|
||||
|
@ -135,6 +135,27 @@ void bus_panel_proxy_set_content_type
|
|||
guint hints);
|
||||
PanelType bus_panel_proxy_get_panel_type
|
||||
(BusPanelProxy *panel);
|
||||
void bus_panel_proxy_panel_extension_received
|
||||
(BusPanelProxy *panel,
|
||||
IBusExtensionEvent
|
||||
*event);
|
||||
void bus_panel_proxy_process_key_event
|
||||
(BusPanelProxy *panel,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
guint state,
|
||||
GAsyncReadyCallback
|
||||
callback,
|
||||
gpointer user_data);
|
||||
void bus_panel_proxy_commit_text_received
|
||||
(BusPanelProxy *panel,
|
||||
IBusText *text);
|
||||
void bus_panel_proxy_candidate_clicked_lookup_table
|
||||
(BusPanelProxy *panel,
|
||||
guint index,
|
||||
guint button,
|
||||
guint state);
|
||||
|
||||
G_END_DECLS
|
||||
#endif
|
||||
|
||||
|
|
|
@ -353,6 +353,18 @@
|
|||
<long>Custom font name for language panel</long>
|
||||
</locale>
|
||||
</schema>
|
||||
<schema>
|
||||
<key>/schemas/desktop/ibus/panel/emoji/unicode-hotkey</key>
|
||||
<applyto>/desktop/ibus/panel/emoji/unicode-hotkey</applyto>
|
||||
<owner>ibus</owner>
|
||||
<type>list</type>
|
||||
<list_type>string</list_type>
|
||||
<default>[<Control><Shift>u]</default>
|
||||
<locale name="C">
|
||||
<short>Unicode shortcut keys for gtk_accelerator_parse</short>
|
||||
<long>The shortcut keys for turning Unicode typing on or off</long>
|
||||
</locale>
|
||||
</schema>
|
||||
<schema>
|
||||
<key>/schemas/desktop/ibus/panel/emoji/hotkey</key>
|
||||
<applyto>/desktop/ibus/panel/emoji/hotkey</applyto>
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# ibus - The Input Bus
|
||||
#
|
||||
# Copyright (c) 2007-2016 Peng Huang <shawn.p.huang@gmail.com>
|
||||
# Copyright (c) 2010-2017 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
||||
# Copyright (c) 2010-2018 Takao Fujiwara <takao.fujiwara1@gmail.com>
|
||||
# Copyright (c) 2007-2016 Red Hat, Inc.
|
||||
#
|
||||
# This library is free software; you can redistribute it and/or
|
||||
|
@ -123,10 +123,15 @@ class Setup(object):
|
|||
name = 'emoji'
|
||||
label = 'emoji_dialog'
|
||||
self.__init_hotkey(name, label)
|
||||
name = 'unicode'
|
||||
label = 'unicode_dialog'
|
||||
self.__init_hotkey(name, label)
|
||||
|
||||
def __init_hotkey(self, name, label, comment=None):
|
||||
if name == 'emoji':
|
||||
shortcuts = self.__settings_emoji.get_strv('hotkey')
|
||||
elif name == 'unicode':
|
||||
shortcuts = self.__settings_emoji.get_strv('unicode-hotkey')
|
||||
else:
|
||||
shortcuts = self.__settings_hotkey.get_strv(name)
|
||||
button = self.__builder.get_object("button_%s" % label)
|
||||
|
@ -139,6 +144,9 @@ class Setup(object):
|
|||
if name == 'emoji':
|
||||
button.connect("clicked", self.__shortcut_button_clicked_cb,
|
||||
'hotkey', 'panel/' + name, label, entry)
|
||||
elif name == 'unicode':
|
||||
button.connect("clicked", self.__shortcut_button_clicked_cb,
|
||||
'unicode-hotkey', 'panel/emoji', label, entry)
|
||||
else:
|
||||
button.connect("clicked", self.__shortcut_button_clicked_cb,
|
||||
name, "general/hotkey", label, entry)
|
||||
|
|
|
@ -870,9 +870,9 @@
|
|||
<object class="GtkLabel" id="label_emoji1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">The shortcut keys for showing emoji dialog</property>
|
||||
<property name="tooltip_text" translatable="yes">The shortcut keys to enable conversions of emoji annotations or Unicode names</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Emoji choice:</property>
|
||||
<property name="label" translatable="yes">Emoji annotation:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
|
@ -920,6 +920,60 @@
|
|||
<property name="top_attach">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label_unicode1">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="tooltip_text" translatable="yes">The shortcut keys to enable Unicode code point conversions</property>
|
||||
<property name="halign">start</property>
|
||||
<property name="label" translatable="yes">Unicode code point:</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">0</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkBox" id="hbox_unicode1">
|
||||
<property name="orientation">horizontal</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">False</property>
|
||||
<property name="spacing">6</property>
|
||||
<property name="hexpand">true</property>
|
||||
<child>
|
||||
<object class="GtkEntry" id="entry_unicode_dialog">
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="editable">False</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">True</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_unicode_dialog">
|
||||
<property name="label" translatable="yes">...</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="visible">True</property>
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_action_appearance">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="expand">False</property>
|
||||
<property name="fill">True</property>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="left_attach">1</property>
|
||||
<property name="top_attach">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child type="label">
|
||||
|
|
305
src/ibusengine.c
305
src/ibusengine.c
|
@ -64,8 +64,6 @@ enum {
|
|||
};
|
||||
|
||||
|
||||
typedef struct _IBusEngineKeybinding IBusEngineKeybinding;
|
||||
|
||||
/* IBusEnginePriv */
|
||||
struct _IBusEnginePrivate {
|
||||
gchar *engine_name;
|
||||
|
@ -81,14 +79,11 @@ struct _IBusEnginePrivate {
|
|||
guint content_purpose;
|
||||
guint content_hints;
|
||||
|
||||
GSettings *settings_emoji;
|
||||
IBusEngineKeybinding **emoji_keybindings;
|
||||
GHashTable *extension_keybindings;
|
||||
gboolean enable_extension;
|
||||
gchar *current_extension_name;
|
||||
};
|
||||
|
||||
struct _IBusEngineKeybinding {
|
||||
guint keyval;
|
||||
IBusModifierType modifiers;
|
||||
};
|
||||
|
||||
static guint engine_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
|
@ -191,10 +186,6 @@ static void ibus_engine_dbus_property_changed
|
|||
const gchar *property_name,
|
||||
GVariant *value);
|
||||
static void ibus_engine_keybinding_free (IBusEngine *engine);
|
||||
static void settings_emoji_hotkey_changed_cb
|
||||
(GSettings *settings,
|
||||
const gchar *key,
|
||||
gpointer data);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (IBusEngine, ibus_engine, IBUS_TYPE_SERVICE)
|
||||
|
@ -253,6 +244,12 @@ static const gchar introspection_xml[] =
|
|||
" <arg direction='in' type='u' name='cursor_pos' />"
|
||||
" <arg direction='in' type='u' name='anchor_pos' />"
|
||||
" </method>"
|
||||
" <method name='PanelExtensionReceived'>"
|
||||
" <arg direction='in' type='v' name='event' />"
|
||||
" </method>"
|
||||
" <method name='PanelExtensionRegisterKeys'>"
|
||||
" <arg direction='in' type='v' name='data' />"
|
||||
" </method>"
|
||||
/* FIXME signals */
|
||||
" <signal name='CommitText'>"
|
||||
" <arg type='v' name='text' />"
|
||||
|
@ -309,16 +306,22 @@ ibus_engine_class_init (IBusEngineClass *class)
|
|||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
|
||||
|
||||
gobject_class->set_property = (GObjectSetPropertyFunc) ibus_engine_set_property;
|
||||
gobject_class->get_property = (GObjectGetPropertyFunc) ibus_engine_get_property;
|
||||
gobject_class->set_property =
|
||||
(GObjectSetPropertyFunc) ibus_engine_set_property;
|
||||
gobject_class->get_property =
|
||||
(GObjectGetPropertyFunc) ibus_engine_get_property;
|
||||
|
||||
ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_engine_destroy;
|
||||
|
||||
IBUS_SERVICE_CLASS (class)->service_method_call = ibus_engine_service_method_call;
|
||||
IBUS_SERVICE_CLASS (class)->service_get_property = ibus_engine_service_get_property;
|
||||
IBUS_SERVICE_CLASS (class)->service_set_property = ibus_engine_service_set_property;
|
||||
IBUS_SERVICE_CLASS (class)->service_method_call =
|
||||
ibus_engine_service_method_call;
|
||||
IBUS_SERVICE_CLASS (class)->service_get_property =
|
||||
ibus_engine_service_get_property;
|
||||
IBUS_SERVICE_CLASS (class)->service_set_property =
|
||||
ibus_engine_service_set_property;
|
||||
|
||||
ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class), introspection_xml);
|
||||
ibus_service_class_add_interfaces (IBUS_SERVICE_CLASS (class),
|
||||
introspection_xml);
|
||||
|
||||
class->process_key_event = ibus_engine_process_key_event;
|
||||
class->focus_in = ibus_engine_focus_in;
|
||||
|
@ -839,26 +842,25 @@ ibus_engine_init (IBusEngine *engine)
|
|||
{
|
||||
IBusEnginePrivate *priv;
|
||||
engine->priv = priv = IBUS_ENGINE_GET_PRIVATE (engine);
|
||||
|
||||
priv->surrounding_text = g_object_ref_sink (text_empty);
|
||||
priv->settings_emoji =
|
||||
g_settings_new ("org.freedesktop.ibus.panel.emoji");
|
||||
settings_emoji_hotkey_changed_cb (priv->settings_emoji, "hotkey", engine);
|
||||
g_signal_connect (priv->settings_emoji, "changed::hotkey",
|
||||
G_CALLBACK (settings_emoji_hotkey_changed_cb), engine);
|
||||
priv->extension_keybindings = g_hash_table_new_full (
|
||||
g_str_hash,
|
||||
g_str_equal,
|
||||
g_free,
|
||||
g_free);
|
||||
}
|
||||
|
||||
static void
|
||||
ibus_engine_destroy (IBusEngine *engine)
|
||||
{
|
||||
g_free (engine->priv->engine_name);
|
||||
engine->priv->engine_name = NULL;
|
||||
IBusEnginePrivate *priv = engine->priv;
|
||||
|
||||
if (engine->priv->surrounding_text) {
|
||||
g_object_unref (engine->priv->surrounding_text);
|
||||
engine->priv->surrounding_text = NULL;
|
||||
}
|
||||
ibus_engine_keybinding_free (engine);
|
||||
g_clear_pointer (&priv->engine_name, g_free);
|
||||
g_clear_pointer (&priv->current_extension_name, g_free);
|
||||
if (priv->surrounding_text)
|
||||
g_clear_object (&priv->surrounding_text);
|
||||
if (priv->extension_keybindings)
|
||||
g_clear_pointer (&priv->extension_keybindings, g_hash_table_destroy);
|
||||
|
||||
IBUS_OBJECT_CLASS(ibus_engine_parent_class)->destroy (IBUS_OBJECT (engine));
|
||||
}
|
||||
|
@ -895,19 +897,38 @@ ibus_engine_get_property (IBusEngine *engine,
|
|||
}
|
||||
|
||||
static void
|
||||
ibus_engine_panel_extension (IBusEngine *engine)
|
||||
ibus_engine_panel_extension (IBusEngine *engine,
|
||||
const gchar *name)
|
||||
{
|
||||
IBusXEvent *xevent = ibus_x_event_new (
|
||||
"event-type", IBUS_X_EVENT_KEY_PRESS,
|
||||
"purpose", "emoji",
|
||||
IBusEnginePrivate *priv;
|
||||
IBusExtensionEvent *event;
|
||||
GVariant *data;
|
||||
|
||||
g_assert (IBUS_IS_ENGINE (engine));
|
||||
g_assert (name);
|
||||
|
||||
priv = engine->priv;
|
||||
if (!g_strcmp0 (name, priv->current_extension_name))
|
||||
priv->enable_extension = !priv->enable_extension;
|
||||
else
|
||||
priv->enable_extension = TRUE;
|
||||
if (priv->enable_extension) {
|
||||
g_free (priv->current_extension_name);
|
||||
priv->current_extension_name = g_strdup (name);
|
||||
}
|
||||
event = ibus_extension_event_new (
|
||||
"name", name,
|
||||
"is-enabled", priv->enable_extension,
|
||||
NULL);
|
||||
GVariant *data = ibus_serializable_serialize_object (
|
||||
IBUS_SERIALIZABLE (xevent));
|
||||
g_assert (IBUS_IS_EXTENSION_EVENT (event));
|
||||
data = ibus_serializable_serialize_object (
|
||||
IBUS_SERIALIZABLE (event));
|
||||
|
||||
g_assert (data != NULL);
|
||||
ibus_engine_emit_signal (engine,
|
||||
"PanelExtension",
|
||||
g_variant_new ("(v)", data));
|
||||
g_object_unref (event);
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -917,7 +938,8 @@ ibus_engine_filter_key_event (IBusEngine *engine,
|
|||
guint state)
|
||||
{
|
||||
IBusEnginePrivate *priv;
|
||||
int i;
|
||||
GList *names, *n;
|
||||
IBusProcessKeyEventData *keys;
|
||||
guint modifiers;
|
||||
|
||||
if ((state & IBUS_RELEASE_MASK) != 0)
|
||||
|
@ -925,22 +947,29 @@ ibus_engine_filter_key_event (IBusEngine *engine,
|
|||
g_return_val_if_fail (IBUS_IS_ENGINE (engine), FALSE);
|
||||
|
||||
priv = engine->priv;
|
||||
if (!priv->emoji_keybindings)
|
||||
return FALSE;
|
||||
|
||||
modifiers = state & IBUS_MODIFIER_FILTER;
|
||||
if (keyval >= IBUS_KEY_A && keyval <= IBUS_KEY_Z &&
|
||||
(modifiers & IBUS_SHIFT_MASK) != 0) {
|
||||
keyval = keyval - IBUS_KEY_A + IBUS_KEY_a;
|
||||
}
|
||||
for (i = 0; priv->emoji_keybindings[i]; i++) {
|
||||
IBusEngineKeybinding *binding = priv->emoji_keybindings[i];
|
||||
if (binding->keyval == keyval &&
|
||||
binding->modifiers == modifiers) {
|
||||
ibus_engine_panel_extension (engine);
|
||||
return TRUE;
|
||||
names = g_hash_table_get_keys (priv->extension_keybindings);
|
||||
if (!names)
|
||||
return FALSE;
|
||||
for (n = names; n; n = n->next) {
|
||||
const gchar *name = (const gchar *)n->data;
|
||||
keys = g_hash_table_lookup (priv->extension_keybindings, name);
|
||||
for (; keys; keys++) {
|
||||
if (keys->keyval == 0 && keys->keycode == 0 && keys->state == 0)
|
||||
break;
|
||||
if (keys->keyval == keyval &&
|
||||
keys->state == modifiers &&
|
||||
(keys->keycode == 0 || keys->keycode == keycode)) {
|
||||
ibus_engine_panel_extension (engine, name);
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
g_list_free (names);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
@ -953,6 +982,97 @@ ibus_engine_service_authorized_method (IBusService *service,
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
ibus_engine_service_panel_extension_register_keys (IBusEngine *engine,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation
|
||||
*invocation)
|
||||
{
|
||||
IBusEnginePrivate *priv = engine->priv;
|
||||
GVariant *v1 = NULL;
|
||||
GVariant *v2 = NULL;
|
||||
GVariant *v3 = NULL;
|
||||
GVariant *vkeys = NULL;
|
||||
GVariantIter *iter1 = NULL;
|
||||
GVariantIter *iter2 = NULL;
|
||||
const gchar *name = NULL;
|
||||
guint failure_id = 0;
|
||||
|
||||
g_variant_get (parameters, "(v)", &v1);
|
||||
if (v1)
|
||||
g_variant_get (v1, "(v)", &v2);
|
||||
else
|
||||
failure_id = 1;
|
||||
if (v2)
|
||||
g_variant_get (v2, "a{sv}", &iter1);
|
||||
else
|
||||
failure_id = 2;
|
||||
if (iter1) {
|
||||
while (g_variant_iter_loop (iter1, "{&sv}", &name, &vkeys)) {
|
||||
if (vkeys)
|
||||
g_variant_get (vkeys, "av", &iter2);
|
||||
if (name && iter2) {
|
||||
IBusProcessKeyEventData *keys = NULL;
|
||||
gint num = 0;
|
||||
while (g_variant_iter_loop (iter2, "v", &v3)) {
|
||||
if (v3) {
|
||||
guint keyval = 0;
|
||||
guint keycode = 0;
|
||||
guint state = 0;
|
||||
g_variant_get (v3, "(iii)",
|
||||
&keyval, &keycode, &state);
|
||||
if (!keys)
|
||||
keys = g_new0 (IBusProcessKeyEventData, 2);
|
||||
else
|
||||
keys = g_renew (IBusProcessKeyEventData,
|
||||
keys,
|
||||
num + 2);
|
||||
keys[num].keyval = keyval;
|
||||
keys[num].keycode = keycode;
|
||||
keys[num].state = state;
|
||||
keys[num + 1].keyval = 0;
|
||||
keys[num + 1].keycode = 0;
|
||||
keys[num + 1].state = 0;
|
||||
g_clear_pointer (&v3, g_variant_unref);
|
||||
num++;
|
||||
} else {
|
||||
failure_id = 5;
|
||||
}
|
||||
}
|
||||
if (num > 0) {
|
||||
g_hash_table_replace (priv->extension_keybindings,
|
||||
g_strdup (name),
|
||||
keys);
|
||||
} else {
|
||||
g_hash_table_remove (priv->extension_keybindings, name);
|
||||
}
|
||||
g_clear_pointer (&iter2, g_variant_iter_free);
|
||||
} else {
|
||||
failure_id = 4;
|
||||
}
|
||||
g_clear_pointer (&vkeys, g_variant_unref);
|
||||
name = NULL;
|
||||
}
|
||||
g_variant_iter_free (iter1);
|
||||
} else {
|
||||
failure_id = 3;
|
||||
}
|
||||
if (failure_id == 0) {
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
} else {
|
||||
g_dbus_method_invocation_return_error (
|
||||
invocation,
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"PanelExtensionRegisterKeys method gives NULL: %d",
|
||||
failure_id);
|
||||
}
|
||||
if (v2)
|
||||
g_variant_unref (v2);
|
||||
if (v1)
|
||||
g_variant_unref (v1);
|
||||
}
|
||||
|
||||
static void
|
||||
ibus_engine_service_method_call (IBusService *service,
|
||||
GDBusConnection *connection,
|
||||
|
@ -964,6 +1084,7 @@ ibus_engine_service_method_call (IBusService *service,
|
|||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
IBusEngine *engine = IBUS_ENGINE (service);
|
||||
IBusEnginePrivate *priv = engine->priv;
|
||||
|
||||
if (g_strcmp0 (interface_name, IBUS_INTERFACE_ENGINE) != 0) {
|
||||
IBUS_SERVICE_CLASS (ibus_engine_parent_class)->
|
||||
|
@ -1002,6 +1123,33 @@ ibus_engine_service_method_call (IBusService *service,
|
|||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", retval));
|
||||
return;
|
||||
}
|
||||
if (g_strcmp0 (method_name, "PanelExtensionReceived") == 0) {
|
||||
GVariant *arg0 = NULL;
|
||||
IBusExtensionEvent *event = NULL;
|
||||
|
||||
g_variant_get (parameters, "(v)", &arg0);
|
||||
if (arg0) {
|
||||
event = (IBusExtensionEvent *)ibus_serializable_deserialize_object (
|
||||
arg0);
|
||||
}
|
||||
if (!event) {
|
||||
g_dbus_method_invocation_return_error (
|
||||
invocation,
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"PanelExtensionReceived method gives NULL");
|
||||
return;
|
||||
}
|
||||
priv->enable_extension = ibus_extension_event_is_enabled (event);
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
return;
|
||||
}
|
||||
if (g_strcmp0 (method_name, "PanelExtensionRegisterKeys") == 0) {
|
||||
ibus_engine_service_panel_extension_register_keys (engine,
|
||||
parameters,
|
||||
invocation);
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
gchar *member;
|
||||
|
@ -1441,73 +1589,10 @@ static void
|
|||
ibus_engine_keybinding_free (IBusEngine *engine)
|
||||
{
|
||||
IBusEnginePrivate *priv;
|
||||
int i;
|
||||
|
||||
g_return_if_fail (IBUS_IS_ENGINE (engine));
|
||||
|
||||
priv = engine->priv;
|
||||
if (priv->emoji_keybindings) {
|
||||
for (i = 0; priv->emoji_keybindings[i]; i++)
|
||||
g_slice_free (IBusEngineKeybinding, priv->emoji_keybindings[i]);
|
||||
g_clear_pointer (&priv->emoji_keybindings, g_free);
|
||||
}
|
||||
}
|
||||
|
||||
static IBusEngineKeybinding *
|
||||
ibus_engine_keybinding_new (IBusEngine *engine,
|
||||
const gchar *accelerator)
|
||||
{
|
||||
guint keyval = 0U;
|
||||
IBusModifierType modifiers = 0;
|
||||
IBusEngineKeybinding *binding = NULL;
|
||||
|
||||
ibus_accelerator_parse (accelerator, &keyval, &modifiers);
|
||||
if (keyval == 0U && modifiers == 0) {
|
||||
g_warning ("Failed to parse shortcut key '%s'", accelerator);
|
||||
return NULL;
|
||||
}
|
||||
if (modifiers & IBUS_SUPER_MASK) {
|
||||
modifiers^=IBUS_SUPER_MASK;
|
||||
modifiers|=IBUS_MOD4_MASK;
|
||||
}
|
||||
|
||||
binding = g_slice_new0 (IBusEngineKeybinding);
|
||||
binding->keyval = keyval;
|
||||
binding->modifiers = modifiers;
|
||||
return binding;
|
||||
}
|
||||
|
||||
static void
|
||||
settings_emoji_hotkey_changed_cb (GSettings *settings,
|
||||
const gchar *key,
|
||||
gpointer data)
|
||||
{
|
||||
IBusEngine *engine;
|
||||
IBusEnginePrivate *priv;
|
||||
gchar **accelerators;
|
||||
int i, j, length;
|
||||
g_return_if_fail (IBUS_IS_ENGINE (data));
|
||||
engine = IBUS_ENGINE (data);
|
||||
priv = engine->priv;
|
||||
|
||||
if (g_strcmp0 (key, "hotkey") != 0)
|
||||
return;
|
||||
accelerators = g_settings_get_strv (settings, key);
|
||||
length = g_strv_length (accelerators);
|
||||
ibus_engine_keybinding_free (engine);
|
||||
if (length == 0) {
|
||||
g_strfreev (accelerators);
|
||||
return;
|
||||
}
|
||||
priv->emoji_keybindings = g_new0 (IBusEngineKeybinding*, length + 1);
|
||||
for (i = 0, j = 0; i < length; i++) {
|
||||
IBusEngineKeybinding *binding =
|
||||
ibus_engine_keybinding_new (engine, accelerators[i]);
|
||||
if (!binding)
|
||||
continue;
|
||||
priv->emoji_keybindings[j++] = binding;
|
||||
}
|
||||
g_strfreev (accelerators);
|
||||
}
|
||||
|
||||
IBusEngine *
|
||||
|
|
|
@ -57,6 +57,9 @@ enum {
|
|||
DESTROY_CONTEXT,
|
||||
SET_CONTENT_TYPE,
|
||||
PANEL_EXTENSION_RECEIVED,
|
||||
PROCESS_KEY_EVENT,
|
||||
COMMIT_TEXT_RECEIVED,
|
||||
CANDIDATE_CLICKED_LOOKUP_TABLE,
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
|
@ -153,7 +156,7 @@ static void ibus_panel_service_set_content_type
|
|||
guint hints);
|
||||
static void ibus_panel_service_panel_extension_received
|
||||
(IBusPanelService *panel,
|
||||
GVariant *data);
|
||||
IBusExtensionEvent *event);
|
||||
|
||||
G_DEFINE_TYPE (IBusPanelService, ibus_panel_service, IBUS_TYPE_SERVICE)
|
||||
|
||||
|
@ -184,6 +187,11 @@ static const gchar introspection_xml[] =
|
|||
" <method name='CursorDownLookupTable' />"
|
||||
" <method name='PageUpLookupTable' />"
|
||||
" <method name='PageDownLookupTable' />"
|
||||
" <method name='CandidateClickedLookupTable'>"
|
||||
" <arg direction='in' type='u' name='index' />"
|
||||
" <arg direction='in' type='u' name='button' />"
|
||||
" <arg direction='in' type='u' name='state' />"
|
||||
" </method>"
|
||||
" <method name='RegisterProperties'>"
|
||||
" <arg direction='in' type='v' name='props' />"
|
||||
" </method>"
|
||||
|
@ -221,7 +229,16 @@ static const gchar introspection_xml[] =
|
|||
" <arg direction='in' type='u' name='hints' />"
|
||||
" </method>"
|
||||
" <method name='PanelExtensionReceived'>"
|
||||
" <arg direction='in' type='v' name='data' />"
|
||||
" <arg direction='in' type='v' name='event' />"
|
||||
" </method>"
|
||||
" <method name='ProcessKeyEvent'>"
|
||||
" <arg direction='in' type='u' name='keyval' />"
|
||||
" <arg direction='in' type='u' name='keycode' />"
|
||||
" <arg direction='in' type='u' name='state' />"
|
||||
" <arg direction='out' type='b' />"
|
||||
" </method>"
|
||||
" <method name='CommitTextReceived'>"
|
||||
" <arg direction='in' type='v' name='text' />"
|
||||
" </method>"
|
||||
/* Signals */
|
||||
" <signal name='CursorUp' />"
|
||||
|
@ -247,7 +264,23 @@ static const gchar introspection_xml[] =
|
|||
" <arg type='v' name='text' />"
|
||||
" </signal>"
|
||||
" <signal name='PanelExtension'>"
|
||||
" <arg type='v' name='event' />"
|
||||
" </signal>"
|
||||
" <method name='PanelExtensionRegisterKeys'>"
|
||||
" <arg type='v' name='data' />"
|
||||
" </method>"
|
||||
" <signal name='UpdatePreeditTextReceived'>"
|
||||
" <arg type='v' name='text' />"
|
||||
" <arg type='u' name='cursor_pos' />"
|
||||
" <arg type='b' name='visible' />"
|
||||
" </signal>"
|
||||
" <signal name='UpdateAuxiliaryTextReceived'>"
|
||||
" <arg type='v' name='text' />"
|
||||
" <arg type='b' name='visible' />"
|
||||
" </signal>"
|
||||
" <signal name='UpdateLookupTableReceived'>"
|
||||
" <arg type='v' name='table' />"
|
||||
" <arg type='b' name='visible' />"
|
||||
" </signal>"
|
||||
" </interface>"
|
||||
"</node>";
|
||||
|
@ -927,10 +960,81 @@ ibus_panel_service_class_init (IBusPanelServiceClass *class)
|
|||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (IBusPanelServiceClass, panel_extension_received),
|
||||
NULL, NULL,
|
||||
_ibus_marshal_VOID__VARIANT,
|
||||
_ibus_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
G_TYPE_VARIANT);
|
||||
IBUS_TYPE_EXTENSION_EVENT);
|
||||
|
||||
/**
|
||||
* IBusPanelService::process-key-event:
|
||||
* @panel: An #IBusPanelService
|
||||
* @keyval: Key symbol of the key press.
|
||||
* @keycode: KeyCode of the key press.
|
||||
* @state: Key modifier flags.
|
||||
*
|
||||
* Emitted when a key event is received.
|
||||
* Implement the member function IBusPanelServiceClass::process_key_event
|
||||
* in extended class to receive this signal.
|
||||
* Both the key symbol and keycode are passed to the member function.
|
||||
* See ibus_input_context_process_key_event() for further explanation of
|
||||
* key symbol, keycode and which to use.
|
||||
*
|
||||
* Returns: %TRUE for successfully process the key; %FALSE otherwise.
|
||||
* See also: ibus_input_context_process_key_event().
|
||||
*
|
||||
* <note><para>Argument @user_data is ignored in this function.</para>
|
||||
* </note>
|
||||
*/
|
||||
panel_signals[PROCESS_KEY_EVENT] =
|
||||
g_signal_new (I_("process-key-event"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (IBusPanelServiceClass, process_key_event),
|
||||
g_signal_accumulator_true_handled, NULL,
|
||||
_ibus_marshal_BOOL__UINT_UINT_UINT,
|
||||
G_TYPE_BOOLEAN,
|
||||
3,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_UINT);
|
||||
|
||||
/**
|
||||
* IBusPanelService::commit-text-received:
|
||||
* @panel: An #IBusPanelService
|
||||
* @text: A #IBusText
|
||||
*
|
||||
* Emitted when the client application get the ::commit-text-received.
|
||||
* Implement the member function
|
||||
* IBusPanelServiceClass::commit_text_received in extended class to
|
||||
* receive this signal.
|
||||
*
|
||||
* <note><para>Argument @user_data is ignored in this function.</para>
|
||||
* </note>
|
||||
*/
|
||||
panel_signals[COMMIT_TEXT_RECEIVED] =
|
||||
g_signal_new (I_("commit-text-received"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (IBusPanelServiceClass, commit_text_received),
|
||||
NULL, NULL,
|
||||
_ibus_marshal_VOID__OBJECT,
|
||||
G_TYPE_NONE,
|
||||
1,
|
||||
IBUS_TYPE_TEXT);
|
||||
|
||||
panel_signals[CANDIDATE_CLICKED_LOOKUP_TABLE] =
|
||||
g_signal_new (I_("candidate-clicked-lookup-table"),
|
||||
G_TYPE_FROM_CLASS (gobject_class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
G_STRUCT_OFFSET (IBusPanelServiceClass,
|
||||
candidate_clicked_lookup_table),
|
||||
NULL, NULL,
|
||||
_ibus_marshal_VOID__UINT_UINT_UINT,
|
||||
G_TYPE_NONE,
|
||||
3,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_UINT,
|
||||
G_TYPE_UINT);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -1129,9 +1233,14 @@ ibus_panel_service_service_method_call (IBusService *service,
|
|||
}
|
||||
|
||||
if (g_strcmp0 (method_name, "PanelExtensionReceived") == 0) {
|
||||
GVariant *variant = NULL;
|
||||
g_variant_get (parameters, "(v)", &variant);
|
||||
if (variant == NULL) {
|
||||
GVariant *arg0 = NULL;
|
||||
IBusExtensionEvent *event = NULL;
|
||||
g_variant_get (parameters, "(v)", &arg0);
|
||||
if (arg0) {
|
||||
event = IBUS_EXTENSION_EVENT (ibus_serializable_deserialize (arg0));
|
||||
g_variant_unref (arg0);
|
||||
}
|
||||
if (!event) {
|
||||
g_dbus_method_invocation_return_error (
|
||||
invocation,
|
||||
G_DBUS_ERROR,
|
||||
|
@ -1140,11 +1249,63 @@ ibus_panel_service_service_method_call (IBusService *service,
|
|||
return;
|
||||
}
|
||||
g_signal_emit (panel, panel_signals[PANEL_EXTENSION_RECEIVED], 0,
|
||||
variant);
|
||||
g_variant_unref (variant);
|
||||
event);
|
||||
_g_object_unref_if_floating (event);
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
return;
|
||||
}
|
||||
if (g_strcmp0 (method_name, "ProcessKeyEvent") == 0) {
|
||||
guint keyval, keycode, state;
|
||||
gboolean retval = FALSE;
|
||||
|
||||
g_variant_get (parameters, "(uuu)", &keyval, &keycode, &state);
|
||||
g_signal_emit (panel,
|
||||
panel_signals[PROCESS_KEY_EVENT],
|
||||
0,
|
||||
keyval,
|
||||
keycode,
|
||||
state,
|
||||
&retval);
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(b)", retval));
|
||||
return;
|
||||
}
|
||||
if (g_strcmp0 (method_name, "CommitTextReceived") == 0) {
|
||||
GVariant *arg0 = NULL;
|
||||
IBusText *text = NULL;
|
||||
|
||||
g_variant_get (parameters, "(v)", &arg0);
|
||||
if (arg0) {
|
||||
text = (IBusText *) ibus_serializable_deserialize (arg0);
|
||||
g_variant_unref (arg0);
|
||||
}
|
||||
if (!text) {
|
||||
g_dbus_method_invocation_return_error (
|
||||
invocation,
|
||||
G_DBUS_ERROR,
|
||||
G_DBUS_ERROR_FAILED,
|
||||
"CommitTextReceived method gives NULL");
|
||||
return;
|
||||
}
|
||||
g_signal_emit (panel,
|
||||
panel_signals[COMMIT_TEXT_RECEIVED],
|
||||
0,
|
||||
text);
|
||||
_g_object_unref_if_floating (text);
|
||||
return;
|
||||
}
|
||||
if (g_strcmp0 (method_name, "CandidateClickedLookupTable") == 0) {
|
||||
guint index = 0;
|
||||
guint button = 0;
|
||||
guint state = 0;
|
||||
g_variant_get (parameters, "(uuu)", &index, &button, &state);
|
||||
g_signal_emit (panel,
|
||||
panel_signals[CANDIDATE_CLICKED_LOOKUP_TABLE],
|
||||
0,
|
||||
index, button, state);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const static struct {
|
||||
const gchar *name;
|
||||
|
@ -1318,8 +1479,8 @@ ibus_panel_service_set_content_type (IBusPanelService *panel,
|
|||
}
|
||||
|
||||
static void
|
||||
ibus_panel_service_panel_extension_received (IBusPanelService *panel,
|
||||
GVariant *data)
|
||||
ibus_panel_service_panel_extension_received (IBusPanelService *panel,
|
||||
IBusExtensionEvent *event)
|
||||
{
|
||||
ibus_panel_service_not_implemented(panel);
|
||||
}
|
||||
|
@ -1396,10 +1557,11 @@ void
|
|||
ibus_panel_service_commit_text (IBusPanelService *panel,
|
||||
IBusText *text)
|
||||
{
|
||||
GVariant *variant;
|
||||
g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
|
||||
g_return_if_fail (IBUS_IS_TEXT (text));
|
||||
|
||||
GVariant *variant = ibus_serializable_serialize ((IBusSerializable *)text);
|
||||
variant = ibus_serializable_serialize ((IBusSerializable *)text);
|
||||
ibus_service_emit_signal ((IBusService *) panel,
|
||||
NULL,
|
||||
IBUS_INTERFACE_PANEL,
|
||||
|
@ -1413,18 +1575,144 @@ ibus_panel_service_commit_text (IBusPanelService *panel,
|
|||
}
|
||||
|
||||
void
|
||||
ibus_panel_service_panel_extension (IBusPanelService *panel,
|
||||
GVariant *variant)
|
||||
ibus_panel_service_panel_extension (IBusPanelService *panel,
|
||||
IBusExtensionEvent *event)
|
||||
{
|
||||
GVariant *variant;
|
||||
g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
|
||||
g_return_if_fail (variant);
|
||||
g_return_if_fail (IBUS_IS_EXTENSION_EVENT (event));
|
||||
|
||||
variant = ibus_serializable_serialize ((IBusSerializable *)event);
|
||||
ibus_service_emit_signal ((IBusService *) panel,
|
||||
NULL,
|
||||
IBUS_INTERFACE_PANEL,
|
||||
"PanelExtension",
|
||||
g_variant_new ("(v)", variant),
|
||||
NULL);
|
||||
|
||||
if (g_object_is_floating (event)) {
|
||||
g_object_unref (event);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ibus_panel_service_panel_extension_register_keys (IBusPanelService *panel,
|
||||
const gchar
|
||||
*first_property_name,
|
||||
...)
|
||||
{
|
||||
GVariantBuilder builder;
|
||||
GVariantBuilder child;
|
||||
const gchar *name;
|
||||
va_list var_args;
|
||||
IBusProcessKeyEventData *keys;
|
||||
|
||||
g_return_if_fail (first_property_name);
|
||||
|
||||
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a{sv}"));
|
||||
name = first_property_name;
|
||||
|
||||
va_start (var_args, first_property_name);
|
||||
do {
|
||||
keys = va_arg (var_args, IBusProcessKeyEventData *);
|
||||
g_return_if_fail (keys != NULL);
|
||||
g_variant_builder_init (&child, G_VARIANT_TYPE ("av"));
|
||||
for (; keys; keys++) {
|
||||
if (keys->keyval == 0 && keys->keycode == 0 && keys->state == 0)
|
||||
break;
|
||||
g_variant_builder_add (&child, "v",
|
||||
g_variant_new ("(iii)",
|
||||
keys->keyval,
|
||||
keys->keycode,
|
||||
keys->state));
|
||||
}
|
||||
g_variant_builder_add (&builder, "{sv}",
|
||||
g_strdup (name), g_variant_builder_end (&child));
|
||||
} while ((name = va_arg (var_args, const gchar *)));
|
||||
va_end (var_args);
|
||||
|
||||
ibus_service_emit_signal ((IBusService *) panel,
|
||||
NULL,
|
||||
IBUS_INTERFACE_PANEL,
|
||||
"PanelExtensionRegisterKeys",
|
||||
g_variant_new ("(v)",
|
||||
g_variant_builder_end (&builder)),
|
||||
NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ibus_panel_service_update_preedit_text_received (IBusPanelService *panel,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
gboolean visible)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
|
||||
g_return_if_fail (IBUS_IS_TEXT (text));
|
||||
|
||||
variant = ibus_serializable_serialize ((IBusSerializable *)text);
|
||||
g_return_if_fail (variant);
|
||||
ibus_service_emit_signal ((IBusService *) panel,
|
||||
NULL,
|
||||
IBUS_INTERFACE_PANEL,
|
||||
"UpdatePreeditTextReceived",
|
||||
g_variant_new ("(vub)",
|
||||
variant, cursor_pos, visible),
|
||||
NULL);
|
||||
|
||||
if (g_object_is_floating (text)) {
|
||||
g_object_unref (text);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ibus_panel_service_update_auxiliary_text_received (IBusPanelService *panel,
|
||||
IBusText *text,
|
||||
gboolean visible)
|
||||
{
|
||||
GVariant *variant;
|
||||
g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
|
||||
g_return_if_fail (IBUS_IS_TEXT (text));
|
||||
|
||||
variant = ibus_serializable_serialize ((IBusSerializable *)text);
|
||||
g_return_if_fail (variant);
|
||||
ibus_service_emit_signal ((IBusService *) panel,
|
||||
NULL,
|
||||
IBUS_INTERFACE_PANEL,
|
||||
"UpdateAuxiliaryTextReceived",
|
||||
g_variant_new ("(vb)",
|
||||
variant, visible),
|
||||
NULL);
|
||||
|
||||
if (g_object_is_floating (text)) {
|
||||
g_object_unref (text);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ibus_panel_service_update_lookup_table_received (IBusPanelService *panel,
|
||||
IBusLookupTable *table,
|
||||
gboolean visible)
|
||||
{
|
||||
GVariant *variant;
|
||||
|
||||
g_return_if_fail (IBUS_IS_PANEL_SERVICE (panel));
|
||||
g_return_if_fail (IBUS_IS_LOOKUP_TABLE (table));
|
||||
|
||||
variant = ibus_serializable_serialize ((IBusSerializable *)table);
|
||||
g_return_if_fail (variant);
|
||||
ibus_service_emit_signal ((IBusService *) panel,
|
||||
NULL,
|
||||
IBUS_INTERFACE_PANEL,
|
||||
"UpdateLookupTableReceived",
|
||||
g_variant_new ("(vb)",
|
||||
variant, visible),
|
||||
NULL);
|
||||
|
||||
if (g_object_is_floating (table)) {
|
||||
g_object_unref (table);
|
||||
}
|
||||
}
|
||||
|
||||
#define DEFINE_FUNC(name, Name) \
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include "ibuslookuptable.h"
|
||||
#include "ibusservice.h"
|
||||
#include "ibusproplist.h"
|
||||
#include "ibusxevent.h"
|
||||
|
||||
/*
|
||||
* Type macros.
|
||||
|
@ -130,11 +131,24 @@ struct _IBusPanelServiceClass {
|
|||
gint h);
|
||||
void (* panel_extension_received)
|
||||
(IBusPanelService *panel,
|
||||
GVariant *data);
|
||||
IBusExtensionEvent *event);
|
||||
gboolean (* process_key_event)
|
||||
(IBusPanelService *panel,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
guint state);
|
||||
void (* commit_text_received)
|
||||
(IBusPanelService *panel,
|
||||
IBusText *text);
|
||||
void (* candidate_clicked_lookup_table)
|
||||
(IBusPanelService *panel,
|
||||
guint index,
|
||||
guint button,
|
||||
guint state);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[5]; // We can add 8 pointers without breaking the ABI.
|
||||
gpointer pdummy[2]; // We can add 8 pointers without breaking the ABI.
|
||||
};
|
||||
|
||||
GType ibus_panel_service_get_type (void);
|
||||
|
@ -248,12 +262,105 @@ void ibus_panel_service_commit_text (IBusPanelService *panel,
|
|||
/**
|
||||
* ibus_panel_service_panel_extension:
|
||||
* @panel: An #IBusPanelService
|
||||
* @data: (transfer full): A #GVariant data which is sent to a panel extension.
|
||||
* @event: (transfer full): A #PanelExtensionEvent which is sent to a
|
||||
* panel extension.
|
||||
*
|
||||
* Enable or disable a panel extension with #IBusExtensionEvent.
|
||||
* Notify that a data is sent
|
||||
* by sending a "PanelExtension" message to IBus panel extension service.
|
||||
*/
|
||||
void ibus_panel_service_panel_extension (IBusPanelService *panel,
|
||||
GVariant *data);
|
||||
void ibus_panel_service_panel_extension (IBusPanelService *panel,
|
||||
IBusExtensionEvent *event);
|
||||
|
||||
/**
|
||||
* ibus_panel_service_panel_extension_register_keys:
|
||||
* @panel: An #IBusPanelService
|
||||
* @first_property_name: the first name of the shortcut keys. This is %NULL
|
||||
" terminated.
|
||||
*
|
||||
* Register shortcut keys to enable panel extensions with #IBusExtensionEvent.
|
||||
* Notify that a data is sent
|
||||
* by sending a "PanelExtensionRegisterKeys" message to IBus panel extension
|
||||
* service. Seems Vala does not support uint[][3] and use
|
||||
* IBusProcessKeyEventData[]. E.g.
|
||||
* IBusProcessKeyEventData[] keys = {{
|
||||
* IBUS_KEY_e, 0, IBUS_SHIFT_MASK | IBUS_SUPER_MASK }};
|
||||
* ibus_panel_service_panel_extension_register_keys(panel, "emoji", keys, NULL);
|
||||
*/
|
||||
void ibus_panel_service_panel_extension_register_keys
|
||||
(IBusPanelService *panel,
|
||||
const gchar *first_property_name,
|
||||
...);
|
||||
|
||||
/**
|
||||
* ibus_panel_service_update_preedit_text_received:
|
||||
* @panel: An #IBusPanelService
|
||||
* @text: Update content.
|
||||
* @cursor_pos: Current position of cursor
|
||||
* @visible: Whether the pre-edit buffer is visible.
|
||||
*
|
||||
* Notify that the preedit is updated by the panel extension
|
||||
*
|
||||
* (Note: The table object will be released, if it is floating.
|
||||
* If caller want to keep the object, caller should make the object
|
||||
* sink by g_object_ref_sink.)
|
||||
*/
|
||||
void ibus_panel_service_update_preedit_text_received
|
||||
(IBusPanelService *panel,
|
||||
IBusText *text,
|
||||
guint cursor_pos,
|
||||
gboolean visible);
|
||||
|
||||
/**
|
||||
* ibus_panel_service_show_preedit_text_received:
|
||||
* @panel: An IBusPanelService
|
||||
*
|
||||
* Notify that the preedit is shown by the panel extension
|
||||
*/
|
||||
void ibus_panel_service_show_preedit_text_received
|
||||
(IBusPanelService *panel);
|
||||
|
||||
/**
|
||||
* ibus_panel_service_hide_preedit_text_received:
|
||||
* @panel: An IBusPanelService
|
||||
*
|
||||
* Notify that the preedit is hidden by the panel extension
|
||||
*/
|
||||
void ibus_panel_service_hide_preedit_text_received
|
||||
(IBusPanelService *panel);
|
||||
|
||||
/**
|
||||
* ibus_panel_service_update_auxiliary_text_received:
|
||||
* @panel: An #IBusPanelService
|
||||
* @text: An #IBusText
|
||||
* @visible: Whether the auxilirary text is visible.
|
||||
*
|
||||
* Notify that the auxilirary is updated by the panel extension.
|
||||
*
|
||||
* (Note: The table object will be released, if it is floating.
|
||||
* If caller want to keep the object, caller should make the object
|
||||
* sink by g_object_ref_sink.)
|
||||
*/
|
||||
void ibus_panel_service_update_auxiliary_text_received
|
||||
(IBusPanelService *panel,
|
||||
IBusText *text,
|
||||
gboolean visible);
|
||||
|
||||
/**
|
||||
* ibus_panel_service_update_lookup_table_received:
|
||||
* @panel: An #IBusPanelService
|
||||
* @table: An #IBusLookupTable
|
||||
* @visible: Whether the lookup table is visible.
|
||||
*
|
||||
* Notify that the lookup table is updated by the panel extension.
|
||||
*
|
||||
* (Note: The table object will be released, if it is floating.
|
||||
* If caller want to keep the object, caller should make the object
|
||||
* sink by g_object_ref_sink.)
|
||||
*/
|
||||
void ibus_panel_service_update_lookup_table_received
|
||||
(IBusPanelService *panel,
|
||||
IBusLookupTable *table,
|
||||
gboolean visible);
|
||||
G_END_DECLS
|
||||
#endif
|
||||
|
|
|
@ -73,6 +73,15 @@
|
|||
*/
|
||||
#define IBUS_SERVICE_PANEL_EXTENSION "org.freedesktop.IBus.Panel.Extension"
|
||||
|
||||
/**
|
||||
* IBUS_SERVICE_PANEL_EXTENSION_EMOJI:
|
||||
*
|
||||
* Address of IBus panel extension service for emoji.
|
||||
* This service provides emoji, Unicode code point, Unicode name features.
|
||||
*/
|
||||
#define IBUS_SERVICE_PANEL_EXTENSION_EMOJI \
|
||||
"org.freedesktop.IBus.Panel.Extension.Emoji"
|
||||
|
||||
/**
|
||||
* IBUS_SERVICE_CONFIG:
|
||||
*
|
||||
|
@ -109,11 +118,13 @@
|
|||
#define IBUS_PATH_PANEL "/org/freedesktop/IBus/Panel"
|
||||
|
||||
/**
|
||||
* IBUS_PATH_PANEL_EXTENSION:
|
||||
* IBUS_PATH_PANEL_EXTENSION_EMOJI:
|
||||
*
|
||||
* D-Bus path for IBus panel.
|
||||
* D-Bus path for IBus extension panel for emoji.
|
||||
* This service provides emoji, Unicode code point, Unicode name features.
|
||||
*/
|
||||
#define IBUS_PATH_PANEL_EXTENSION "/org/freedesktop/IBus/Panel/Extension"
|
||||
#define IBUS_PATH_PANEL_EXTENSION_EMOJI \
|
||||
"/org/freedesktop/IBus/Panel/Extension/Emoji"
|
||||
|
||||
/**
|
||||
* IBUS_PATH_CONFIG:
|
||||
|
|
373
src/ibusxevent.c
373
src/ibusxevent.c
|
@ -22,13 +22,23 @@
|
|||
#include "ibusinternal.h"
|
||||
#include "ibusxevent.h"
|
||||
|
||||
#define IBUS_EXTENSION_EVENT_VERSION 1
|
||||
#define IBUS_EXTENSION_EVENT_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((o), \
|
||||
IBUS_TYPE_EXTENSION_EVENT, \
|
||||
IBusExtensionEventPrivate))
|
||||
|
||||
#define IBUS_X_EVENT_VERSION 1
|
||||
#define IBUS_X_EVENT_GET_PRIVATE(o) \
|
||||
#define IBUS_X_EVENT_GET_PRIVATE(o) \
|
||||
(G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_X_EVENT, IBusXEventPrivate))
|
||||
|
||||
enum {
|
||||
PROP_0,
|
||||
PROP_VERSION,
|
||||
PROP_NAME,
|
||||
PROP_IS_ENABLED,
|
||||
PROP_IS_EXTENSION,
|
||||
PROP_PARAMS,
|
||||
PROP_EVENT_TYPE,
|
||||
PROP_WINDOW,
|
||||
PROP_SEND_EVENT,
|
||||
|
@ -52,6 +62,14 @@ enum {
|
|||
};
|
||||
|
||||
|
||||
struct _IBusExtensionEventPrivate {
|
||||
guint version;
|
||||
gchar *name;
|
||||
gboolean is_enabled;
|
||||
gboolean is_extension;
|
||||
gchar *params;
|
||||
};
|
||||
|
||||
struct _IBusXEventPrivate {
|
||||
guint version;
|
||||
guint32 time;
|
||||
|
@ -73,24 +91,346 @@ struct _IBusXEventPrivate {
|
|||
};
|
||||
|
||||
/* functions prototype */
|
||||
static void ibus_x_event_destroy (IBusXEvent *event);
|
||||
static void ibus_x_event_set_property (IBusXEvent *event,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void ibus_x_event_get_property (IBusXEvent *event,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static gboolean ibus_x_event_serialize (IBusXEvent *event,
|
||||
GVariantBuilder *builder);
|
||||
static gint ibus_x_event_deserialize (IBusXEvent *event,
|
||||
GVariant *variant);
|
||||
static gboolean ibus_x_event_copy (IBusXEvent *dest,
|
||||
const IBusXEvent *src);
|
||||
static void ibus_extension_event_destroy (IBusExtensionEvent *event);
|
||||
static void ibus_extension_event_set_property (IBusExtensionEvent *event,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void ibus_extension_event_get_property (IBusExtensionEvent *event,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static gboolean ibus_extension_event_serialize (IBusExtensionEvent *event,
|
||||
GVariantBuilder
|
||||
*builder);
|
||||
static gint ibus_extension_event_deserialize (IBusExtensionEvent *event,
|
||||
GVariant
|
||||
*variant);
|
||||
static gboolean ibus_extension_event_copy (IBusExtensionEvent
|
||||
*dest,
|
||||
const IBusExtensionEvent
|
||||
*src);
|
||||
static void ibus_x_event_destroy (IBusXEvent *event);
|
||||
static void ibus_x_event_set_property (IBusXEvent *event,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static void ibus_x_event_get_property (IBusXEvent *event,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec);
|
||||
static gboolean ibus_x_event_serialize (IBusXEvent *event,
|
||||
GVariantBuilder
|
||||
*builder);
|
||||
static gint ibus_x_event_deserialize (IBusXEvent *event,
|
||||
GVariant
|
||||
*variant);
|
||||
static gboolean ibus_x_event_copy (IBusXEvent *dest,
|
||||
const IBusXEvent *src);
|
||||
|
||||
G_DEFINE_TYPE (IBusExtensionEvent, ibus_extension_event, IBUS_TYPE_SERIALIZABLE)
|
||||
G_DEFINE_TYPE (IBusXEvent, ibus_x_event, IBUS_TYPE_SERIALIZABLE)
|
||||
|
||||
static void
|
||||
ibus_extension_event_class_init (IBusExtensionEventClass *class)
|
||||
{
|
||||
GObjectClass *gobject_class = G_OBJECT_CLASS (class);
|
||||
IBusObjectClass *object_class = IBUS_OBJECT_CLASS (class);
|
||||
IBusSerializableClass *serializable_class = IBUS_SERIALIZABLE_CLASS (class);
|
||||
|
||||
gobject_class->set_property =
|
||||
(GObjectSetPropertyFunc) ibus_extension_event_set_property;
|
||||
gobject_class->get_property =
|
||||
(GObjectGetPropertyFunc) ibus_extension_event_get_property;
|
||||
|
||||
object_class->destroy =
|
||||
(IBusObjectDestroyFunc) ibus_extension_event_destroy;
|
||||
|
||||
serializable_class->serialize =
|
||||
(IBusSerializableSerializeFunc) ibus_extension_event_serialize;
|
||||
serializable_class->deserialize =
|
||||
(IBusSerializableDeserializeFunc) ibus_extension_event_deserialize;
|
||||
serializable_class->copy =
|
||||
(IBusSerializableCopyFunc) ibus_extension_event_copy;
|
||||
|
||||
/* install properties */
|
||||
/**
|
||||
* IBusExtensionEvent:version:
|
||||
*
|
||||
* Version of the #IBusExtensionEvent.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_VERSION,
|
||||
g_param_spec_uint ("version",
|
||||
"version",
|
||||
"version",
|
||||
0,
|
||||
G_MAXUINT32,
|
||||
IBUS_EXTENSION_EVENT_VERSION,
|
||||
G_PARAM_READABLE));
|
||||
|
||||
/**
|
||||
* IBusExtensionEvent:name:
|
||||
*
|
||||
* Name of the extension in the #IBusExtensionEvent.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_NAME,
|
||||
g_param_spec_string ("name",
|
||||
"name",
|
||||
"name of the extension",
|
||||
"",
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/**
|
||||
* IBusExtensionEvent:is-enabled:
|
||||
*
|
||||
* %TRUE if the extension is enabled in the #IBusExtensionEvent.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_IS_ENABLED,
|
||||
g_param_spec_boolean ("is-enabled",
|
||||
"is enabled",
|
||||
"if the extension is enabled",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/**
|
||||
* IBusExtensionEvent:is-extension:
|
||||
*
|
||||
* %TRUE if the #IBusExtensionEvent is called by an extension.
|
||||
* %FALSE if the #IBusExtensionEvent is called by an active engine or
|
||||
* panel.
|
||||
* If this value is %TRUE, the event is send to ibus-daemon, an active
|
||||
* engine. If it's %FALSE, the event is sned to ibus-daemon, panels.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_IS_EXTENSION,
|
||||
g_param_spec_boolean ("is-extension",
|
||||
"is extension",
|
||||
"if the event is called by an extension",
|
||||
FALSE,
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
/**
|
||||
* IBusExtensionEvent:params:
|
||||
*
|
||||
* Parameters to enable the extension in the #IBusExtensionEvent.
|
||||
*/
|
||||
g_object_class_install_property (gobject_class,
|
||||
PROP_PARAMS,
|
||||
g_param_spec_string ("params",
|
||||
"params",
|
||||
"Parameters to enable the extension",
|
||||
"",
|
||||
G_PARAM_READWRITE |
|
||||
G_PARAM_CONSTRUCT_ONLY));
|
||||
|
||||
g_type_class_add_private (class, sizeof (IBusExtensionEventPrivate));
|
||||
}
|
||||
|
||||
static void
|
||||
ibus_extension_event_init (IBusExtensionEvent *event)
|
||||
{
|
||||
event->priv = IBUS_EXTENSION_EVENT_GET_PRIVATE (event);
|
||||
event->priv->version = IBUS_EXTENSION_EVENT_VERSION;
|
||||
}
|
||||
|
||||
static void
|
||||
ibus_extension_event_destroy (IBusExtensionEvent *event)
|
||||
{
|
||||
g_clear_pointer (&event->priv->name, g_free);
|
||||
|
||||
IBUS_OBJECT_CLASS(ibus_extension_event_parent_class)->
|
||||
destroy (IBUS_OBJECT (event));
|
||||
}
|
||||
|
||||
static void
|
||||
ibus_extension_event_set_property (IBusExtensionEvent *event,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
IBusExtensionEventPrivate *priv = event->priv;
|
||||
|
||||
switch (prop_id) {
|
||||
case PROP_NAME:
|
||||
g_free (priv->name);
|
||||
priv->name = g_value_dup_string (value);
|
||||
break;
|
||||
case PROP_IS_ENABLED:
|
||||
priv->is_enabled = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_IS_EXTENSION:
|
||||
priv->is_extension = g_value_get_boolean (value);
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
priv->params = g_value_dup_string (value);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (event, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ibus_extension_event_get_property (IBusExtensionEvent *event,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
IBusExtensionEventPrivate *priv = event->priv;
|
||||
switch (prop_id) {
|
||||
case PROP_VERSION:
|
||||
g_value_set_uint (value, priv->version);
|
||||
break;
|
||||
case PROP_NAME:
|
||||
g_value_set_string (value, priv->name);
|
||||
break;
|
||||
case PROP_IS_ENABLED:
|
||||
g_value_set_boolean (value, priv->is_enabled);
|
||||
break;
|
||||
case PROP_IS_EXTENSION:
|
||||
g_value_set_boolean (value, priv->is_extension);
|
||||
break;
|
||||
case PROP_PARAMS:
|
||||
g_value_set_string (value, priv->params);
|
||||
break;
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (event, prop_id, pspec);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ibus_extension_event_serialize (IBusExtensionEvent *event,
|
||||
GVariantBuilder *builder)
|
||||
{
|
||||
gboolean retval;
|
||||
IBusExtensionEventPrivate *priv;
|
||||
|
||||
retval = IBUS_SERIALIZABLE_CLASS (ibus_extension_event_parent_class)->
|
||||
serialize ((IBusSerializable *)event, builder);
|
||||
g_return_val_if_fail (retval, FALSE);
|
||||
/* End dict iter */
|
||||
|
||||
priv = event->priv;
|
||||
#define NOTNULL(s) ((s) != NULL ? (s) : "")
|
||||
/* If you will add a new property, you can append it at the end and
|
||||
* you should not change the serialized order of name, longname,
|
||||
* description, ... because the order is also used in other applications
|
||||
* likes ibus-qt. */
|
||||
g_variant_builder_add (builder, "u", priv->version);
|
||||
g_variant_builder_add (builder, "s", NOTNULL (priv->name));
|
||||
g_variant_builder_add (builder, "b", priv->is_enabled);
|
||||
g_variant_builder_add (builder, "b", priv->is_extension);
|
||||
g_variant_builder_add (builder, "s", NOTNULL (priv->params));
|
||||
#undef NOTNULL
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gint
|
||||
ibus_extension_event_deserialize (IBusExtensionEvent *event,
|
||||
GVariant *variant)
|
||||
{
|
||||
gint retval;
|
||||
IBusExtensionEventPrivate *priv;
|
||||
|
||||
retval = IBUS_SERIALIZABLE_CLASS (ibus_extension_event_parent_class)->
|
||||
deserialize ((IBusSerializable *)event, variant);
|
||||
g_return_val_if_fail (retval, 0);
|
||||
|
||||
priv = event->priv;
|
||||
/* If you will add a new property, you can append it at the end and
|
||||
* you should not change the serialized order of name, longname,
|
||||
* description, ... because the order is also used in other applications
|
||||
* likes ibus-qt. */
|
||||
g_variant_get_child (variant, retval++, "u", &priv->version);
|
||||
ibus_g_variant_get_child_string (variant, retval++,
|
||||
&priv->name);
|
||||
g_variant_get_child (variant, retval++, "b", &priv->is_enabled);
|
||||
g_variant_get_child (variant, retval++, "b", &priv->is_extension);
|
||||
ibus_g_variant_get_child_string (variant, retval++,
|
||||
&priv->params);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
ibus_extension_event_copy (IBusExtensionEvent *dest,
|
||||
const IBusExtensionEvent *src)
|
||||
{
|
||||
gboolean retval;
|
||||
IBusExtensionEventPrivate *dest_priv = dest->priv;
|
||||
IBusExtensionEventPrivate *src_priv = src->priv;
|
||||
|
||||
retval = IBUS_SERIALIZABLE_CLASS (ibus_extension_event_parent_class)->
|
||||
copy ((IBusSerializable *)dest, (IBusSerializable *)src);
|
||||
g_return_val_if_fail (retval, FALSE);
|
||||
|
||||
dest_priv->version = src_priv->version;
|
||||
dest_priv->name = g_strdup (src_priv->name);
|
||||
dest_priv->is_enabled = src_priv->is_enabled;
|
||||
dest_priv->is_extension = src_priv->is_extension;
|
||||
dest_priv->params = g_strdup (src_priv->params);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
IBusExtensionEvent *
|
||||
ibus_extension_event_new (const gchar *first_property_name,
|
||||
...)
|
||||
{
|
||||
va_list var_args;
|
||||
IBusExtensionEvent *event;
|
||||
|
||||
va_start (var_args, first_property_name);
|
||||
event = (IBusExtensionEvent *) g_object_new_valist (
|
||||
IBUS_TYPE_EXTENSION_EVENT,
|
||||
first_property_name,
|
||||
var_args);
|
||||
va_end (var_args);
|
||||
g_assert (event->priv->version != 0);
|
||||
return event;
|
||||
}
|
||||
|
||||
guint
|
||||
ibus_extension_event_get_version (IBusExtensionEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), 0);
|
||||
return event->priv->version;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
ibus_extension_event_get_name (IBusExtensionEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), "");
|
||||
return event->priv->name;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ibus_extension_event_is_enabled (IBusExtensionEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), FALSE);
|
||||
return event->priv->is_enabled;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ibus_extension_event_is_extension (IBusExtensionEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), FALSE);
|
||||
return event->priv->is_extension;
|
||||
}
|
||||
|
||||
const gchar *
|
||||
ibus_extension_event_get_params (IBusExtensionEvent *event)
|
||||
{
|
||||
g_return_val_if_fail (IBUS_IS_EXTENSION_EVENT (event), "");
|
||||
return event->priv->params;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
ibus_x_event_class_init (IBusXEventClass *class)
|
||||
{
|
||||
|
@ -454,6 +794,7 @@ static void
|
|||
ibus_x_event_destroy (IBusXEvent *event)
|
||||
{
|
||||
g_clear_pointer (&event->priv->string, g_free);
|
||||
g_clear_pointer (&event->priv->purpose, g_free);
|
||||
|
||||
IBUS_OBJECT_CLASS(ibus_x_event_parent_class)->destroy (IBUS_OBJECT (event));
|
||||
}
|
||||
|
|
143
src/ibusxevent.h
143
src/ibusxevent.h
|
@ -29,8 +29,8 @@
|
|||
|
||||
/**
|
||||
* SECTION: ibusxevent
|
||||
* @short_description: XEvent wrapper object
|
||||
* @title: IBusXEvent
|
||||
* @short_description: Extension Event wrapper object
|
||||
* @title: IBusExtensionEvent
|
||||
* @stability: Unstable
|
||||
*
|
||||
* An IBusXEvent provides a wrapper of XEvent.
|
||||
|
@ -45,25 +45,150 @@
|
|||
*/
|
||||
|
||||
/* define GOBJECT macros */
|
||||
#define IBUS_TYPE_X_EVENT \
|
||||
#define IBUS_TYPE_EXTENSION_EVENT \
|
||||
(ibus_extension_event_get_type ())
|
||||
#define IBUS_EXTENSION_EVENT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), \
|
||||
IBUS_TYPE_EXTENSION_EVENT, \
|
||||
IBusExtensionEvent))
|
||||
#define IBUS_EXTENSION_EVENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), \
|
||||
IBUS_TYPE_EXTENSION_EVENT, \
|
||||
IBusExtensionEventClass))
|
||||
#define IBUS_IS_EXTENSION_EVENT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_EXTENSION_EVENT))
|
||||
#define IBUS_IS_EXTENSION_EVENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_EXTENSION_EVENT))
|
||||
#define IBUS_EXTENSION_EVENT_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), \
|
||||
IBUS_TYPE_EXTENSION_EVENT, \
|
||||
IBusExtensionEventClass))
|
||||
|
||||
#define IBUS_TYPE_X_EVENT \
|
||||
(ibus_x_event_get_type ())
|
||||
#define IBUS_X_EVENT(obj) \
|
||||
#define IBUS_X_EVENT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_X_EVENT, IBusXEvent))
|
||||
#define IBUS_X_EVENT_CLASS(klass) \
|
||||
#define IBUS_X_EVENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_X_EVENT, IBusXEventClass))
|
||||
#define IBUS_IS_X_EVENT(obj) \
|
||||
#define IBUS_IS_X_EVENT(obj) \
|
||||
(G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_X_EVENT))
|
||||
#define IBUS_IS_X_EVENT_CLASS(klass) \
|
||||
#define IBUS_IS_X_EVENT_CLASS(klass) \
|
||||
(G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_X_EVENT))
|
||||
#define IBUS_X_EVENT_GET_CLASS(obj) \
|
||||
#define IBUS_X_EVENT_GET_CLASS(obj) \
|
||||
(G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_X_EVENT, IBusXEventClass))
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
typedef struct _IBusProcessKeyEventData IBusProcessKeyEventData;
|
||||
typedef struct _IBusExtensionEvent IBusExtensionEvent;
|
||||
typedef struct _IBusExtensionEventClass IBusExtensionEventClass;
|
||||
typedef struct _IBusExtensionEventPrivate IBusExtensionEventPrivate;
|
||||
typedef struct _IBusXEvent IBusXEvent;
|
||||
typedef struct _IBusXEventClass IBusXEventClass;
|
||||
typedef struct _IBusXEventPrivate IBusXEventPrivate;
|
||||
|
||||
/**
|
||||
* IBusProcessKeyEventData:
|
||||
*
|
||||
* IBuProcessKeyEventData properties.
|
||||
*/
|
||||
struct _IBusProcessKeyEventData {
|
||||
/*< public >*/
|
||||
guint keyval;
|
||||
guint keycode;
|
||||
guint state;
|
||||
};
|
||||
|
||||
/**
|
||||
* IBusExtensionEvent:
|
||||
*
|
||||
* IBusExtensionEvent properties.
|
||||
*/
|
||||
struct _IBusExtensionEvent {
|
||||
/*< private >*/
|
||||
IBusSerializable parent;
|
||||
IBusExtensionEventPrivate *priv;
|
||||
|
||||
/* instance members */
|
||||
/*< public >*/
|
||||
};
|
||||
|
||||
struct _IBusExtensionEventClass {
|
||||
/*< private >*/
|
||||
IBusSerializableClass parent;
|
||||
|
||||
/* class members */
|
||||
/*< public >*/
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
gpointer pdummy[10];
|
||||
};
|
||||
|
||||
|
||||
GType ibus_extension_event_get_type (void);
|
||||
|
||||
/**
|
||||
* ibus_extension_event_new:
|
||||
* @first_property_name: Name of the first property.
|
||||
* @...: the NULL-terminated arguments of the properties and values.
|
||||
*
|
||||
* Create a new #IBusExtensionEvent.
|
||||
*
|
||||
* Returns: A newly allocated #IBusExtensionEvent. E.g.
|
||||
* ibus_extension_event_new ("name", "emoji", "is-enabled", TRUE, NULL);
|
||||
*/
|
||||
IBusExtensionEvent *ibus_extension_event_new (const gchar
|
||||
*first_property_name,
|
||||
...);
|
||||
|
||||
/**
|
||||
* ibus_extension_event_get_version:
|
||||
* @event: An #IBusExtensionEvent.
|
||||
*
|
||||
* Returns: Version of #IBusExtensionEvent
|
||||
*/
|
||||
guint ibus_extension_event_get_version (IBusExtensionEvent *event);
|
||||
|
||||
/**
|
||||
* ibus_extension_event_get_purpose:
|
||||
* @event: An #IBusExtensionEvent.
|
||||
*
|
||||
* Returns: name of the extension for #IBusXEvent
|
||||
*/
|
||||
const gchar * ibus_extension_event_get_name (IBusExtensionEvent *event);
|
||||
|
||||
/**
|
||||
* ibus_extension_event_is_enabled:
|
||||
* @event: An #IBusExtensionEvent.
|
||||
*
|
||||
* Returns: %TRUE if the extension is enabled for #IBusExtensionEvent
|
||||
*/
|
||||
gboolean ibus_extension_event_is_enabled (IBusExtensionEvent *event);
|
||||
|
||||
/**
|
||||
* ibus_extension_event_is_extension:
|
||||
* @event: An #IBusExtensionEvent.
|
||||
*
|
||||
* Returns: %TRUE if the #IBusExtensionEvent is called by an extension.
|
||||
* %FALSE if the #IBusExtensionEvent is called by an active engine or
|
||||
* panel.
|
||||
* If this value is %TRUE, the event is send to ibus-daemon, an active
|
||||
* engine. If it's %FALSE, the event is sned to ibus-daemon, panels.
|
||||
*/
|
||||
gboolean ibus_extension_event_is_extension
|
||||
(IBusExtensionEvent *event);
|
||||
|
||||
/**
|
||||
* ibus_extension_event_get_params:
|
||||
* @event: An #IBusExtensionEvent.
|
||||
*
|
||||
* Returns: Parameters to enable the extension for #IBusXEvent
|
||||
*/
|
||||
const gchar * ibus_extension_event_get_params (IBusExtensionEvent *event);
|
||||
|
||||
|
||||
|
||||
typedef enum {
|
||||
IBUS_X_EVENT_NOTHING = -1,
|
||||
IBUS_X_EVENT_KEY_PRESS = 0,
|
||||
|
@ -76,7 +201,7 @@ typedef enum {
|
|||
* IBusXEvent:
|
||||
* @type: event type
|
||||
*
|
||||
* IBusEngine properties.
|
||||
* IBusXEvent properties.
|
||||
*/
|
||||
struct _IBusXEvent {
|
||||
/*< private >*/
|
||||
|
|
|
@ -78,6 +78,7 @@ AM_VALAFLAGS = \
|
|||
--pkg=ibus-1.0 \
|
||||
--pkg=config \
|
||||
--pkg=xi \
|
||||
--pkg=gdk-wayland \
|
||||
--target-glib="$(VALA_TARGET_GLIB_VERSION)" \
|
||||
$(NULL)
|
||||
|
||||
|
@ -176,6 +177,7 @@ ibus_ui_emojier_VALASOURCES = \
|
|||
emojier.vala \
|
||||
iconwidget.vala \
|
||||
separator.vala \
|
||||
pango.vala \
|
||||
$(NULL)
|
||||
ibus_ui_emojier_SOURCES = \
|
||||
$(ibus_ui_emojier_VALASOURCES:.vala=.c) \
|
||||
|
@ -213,6 +215,7 @@ ibus_extension_gtk3_VALASOURCES = \
|
|||
iconwidget.vala \
|
||||
keybindingmanager.vala \
|
||||
panelbinding.vala \
|
||||
pango.vala \
|
||||
$(NULL)
|
||||
ibus_extension_gtk3_SOURCES = \
|
||||
$(ibus_extension_gtk3_VALASOURCES:.vala=.c) \
|
||||
|
|
1019
ui/gtk3/emojier.vala
1019
ui/gtk3/emojier.vala
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -28,8 +28,9 @@ int partial_match_condition = -1;
|
|||
|
||||
public class EmojiApplication : Gtk.Application {
|
||||
private IBusEmojier? m_emojier;
|
||||
GLib.Settings m_settings_emoji =
|
||||
private GLib.Settings m_settings_emoji =
|
||||
new GLib.Settings("org.freedesktop.ibus.panel.emoji");
|
||||
private ApplicationCommandLine? m_command_line = null;
|
||||
|
||||
|
||||
private EmojiApplication() {
|
||||
|
@ -40,25 +41,39 @@ public class EmojiApplication : Gtk.Application {
|
|||
|
||||
|
||||
private void show_dialog(ApplicationCommandLine command_line) {
|
||||
m_emojier = new IBusEmojier();
|
||||
// For title handling in gnome-shell
|
||||
add_window(m_emojier);
|
||||
Gdk.Event event = Gtk.get_current_event();
|
||||
// Plasma and GNOME3 desktop returns null event
|
||||
if (event == null) {
|
||||
event = new Gdk.Event(Gdk.EventType.KEY_PRESS);
|
||||
event.key.time = Gdk.CURRENT_TIME;
|
||||
// event.get_seat() refers event.any.window
|
||||
event.key.window = Gdk.get_default_root_window();
|
||||
event.key.window.ref();
|
||||
}
|
||||
string emoji = m_emojier.run("", event);
|
||||
remove_window(m_emojier);
|
||||
if (emoji == null) {
|
||||
m_emojier = null;
|
||||
command_line.print("%s\n", _("Canceled to choose an emoji."));
|
||||
m_command_line = command_line;
|
||||
m_emojier.reset();
|
||||
m_emojier.set_annotation("");
|
||||
m_emojier.show_all();
|
||||
}
|
||||
|
||||
|
||||
public void candidate_clicked_lookup_table(uint index,
|
||||
uint button,
|
||||
uint state) {
|
||||
if (m_command_line == null)
|
||||
return;
|
||||
if (button == IBusEmojier.BUTTON_CLOSE_BUTTON) {
|
||||
m_emojier.hide();
|
||||
m_command_line.print("%s\n", _("Canceled to choose an emoji."));
|
||||
m_command_line = null;
|
||||
return;
|
||||
}
|
||||
if (m_emojier == null)
|
||||
return;
|
||||
bool show_candidate = false;
|
||||
uint ncandidates = m_emojier.get_number_of_candidates();
|
||||
if (ncandidates > 0 && ncandidates >= index) {
|
||||
m_emojier.set_cursor_pos(index);
|
||||
show_candidate = m_emojier.has_variants(index);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (show_candidate) {
|
||||
return;
|
||||
}
|
||||
string emoji = m_emojier.get_current_candidate();
|
||||
m_emojier.hide();
|
||||
Gtk.Clipboard clipboard = Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
|
||||
clipboard.set_text(emoji, -1);
|
||||
clipboard.store();
|
||||
|
@ -75,9 +90,8 @@ public class EmojiApplication : Gtk.Application {
|
|||
emojier_favorites += emoji;
|
||||
m_settings_emoji.set_strv("favorites", emojier_favorites);
|
||||
}
|
||||
|
||||
m_emojier = null;
|
||||
command_line.print("%s\n", _("Copied an emoji to your clipboard."));
|
||||
m_command_line.print("%s\n", _("Copied an emoji to your clipboard."));
|
||||
m_command_line = null;
|
||||
}
|
||||
|
||||
|
||||
|
@ -88,7 +102,7 @@ public class EmojiApplication : Gtk.Application {
|
|||
}
|
||||
|
||||
|
||||
private int _command_line (ApplicationCommandLine command_line) {
|
||||
private int _command_line(ApplicationCommandLine command_line) {
|
||||
// Set default font size
|
||||
IBusEmojier.set_emoji_font(m_settings_emoji.get_string("font"));
|
||||
|
||||
|
@ -181,13 +195,22 @@ public class EmojiApplication : Gtk.Application {
|
|||
|
||||
IBusEmojier.load_unicode_dict();
|
||||
|
||||
if (m_emojier == null) {
|
||||
m_emojier = new IBusEmojier();
|
||||
// For title handling in gnome-shell
|
||||
add_window(m_emojier);
|
||||
m_emojier.candidate_clicked.connect((i, b, s) => {
|
||||
candidate_clicked_lookup_table(i, b, s);
|
||||
});
|
||||
}
|
||||
|
||||
activate_dialog(command_line);
|
||||
|
||||
return Posix.EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
public override int command_line (ApplicationCommandLine command_line) {
|
||||
public override int command_line(ApplicationCommandLine command_line) {
|
||||
// keep the application running until we are done with this commandline
|
||||
this.hold();
|
||||
int result = _command_line(command_line);
|
||||
|
@ -196,6 +219,13 @@ public class EmojiApplication : Gtk.Application {
|
|||
}
|
||||
|
||||
|
||||
public override void shutdown() {
|
||||
base.shutdown();
|
||||
remove_window(m_emojier);
|
||||
m_emojier = null;
|
||||
}
|
||||
|
||||
|
||||
public static int main (string[] args) {
|
||||
GLib.Intl.bindtextdomain(Config.GETTEXT_PACKAGE,
|
||||
Config.GLIB_LOCALE_DIR);
|
||||
|
|
|
@ -50,20 +50,20 @@ class ExtensionGtk : Gtk.Application {
|
|||
"org.freedesktop.DBus",
|
||||
"NameAcquired",
|
||||
"/org/freedesktop/DBus",
|
||||
IBus.SERVICE_PANEL_EXTENSION,
|
||||
IBus.SERVICE_PANEL_EXTENSION_EMOJI,
|
||||
DBusSignalFlags.NONE,
|
||||
bus_name_acquired_cb);
|
||||
connection.signal_subscribe("org.freedesktop.DBus",
|
||||
"org.freedesktop.DBus",
|
||||
"NameLost",
|
||||
"/org/freedesktop/DBus",
|
||||
IBus.SERVICE_PANEL_EXTENSION,
|
||||
IBus.SERVICE_PANEL_EXTENSION_EMOJI,
|
||||
DBusSignalFlags.NONE,
|
||||
bus_name_lost_cb);
|
||||
var flags =
|
||||
IBus.BusNameFlag.ALLOW_REPLACEMENT |
|
||||
IBus.BusNameFlag.REPLACE_EXISTING;
|
||||
m_bus.request_name(IBus.SERVICE_PANEL_EXTENSION, flags);
|
||||
m_bus.request_name(IBus.SERVICE_PANEL_EXTENSION_EMOJI, flags);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1148,26 +1148,15 @@ class Panel : IBus.PanelService {
|
|||
#if EMOJI_DICT
|
||||
item = new Gtk.MenuItem.with_label(_("Emoji Choice"));
|
||||
item.activate.connect((i) => {
|
||||
Gdk.Event event = Gtk.get_current_event();
|
||||
if (event == null) {
|
||||
event = new Gdk.Event(Gdk.EventType.KEY_PRESS);
|
||||
event.key.time = Gdk.CURRENT_TIME;
|
||||
// event.get_seat() refers event.any.window
|
||||
event.key.window = Gdk.get_default_root_window();
|
||||
event.key.window.ref();
|
||||
}
|
||||
IBus.XEvent xevent = new IBus.XEvent(
|
||||
"event-type", IBus.XEventType.KEY_PRESS,
|
||||
"window",
|
||||
(event.key.window as Gdk.X11.Window).get_xid(),
|
||||
"time", event.key.time,
|
||||
"purpose", "emoji");
|
||||
/* new GLib.Variant("(sv)", "emoji", xevent.serialize_object())
|
||||
IBus.ExtensionEvent event = new IBus.ExtensionEvent(
|
||||
"name", "emoji", "is-enabled", true,
|
||||
"params", "category-list");
|
||||
/* new GLib.Variant("(sv)", "emoji", event.serialize_object())
|
||||
* will call g_variant_unref() for the child variant by vala.
|
||||
* I have no idea not to unref the object so integrated
|
||||
* the purpose to IBus.XEvent above.
|
||||
* the purpose to IBus.ExtensionEvent above.
|
||||
*/
|
||||
panel_extension(xevent.serialize_object());
|
||||
panel_extension(event);
|
||||
});
|
||||
m_sys_menu.append(item);
|
||||
#endif
|
||||
|
|
|
@ -21,7 +21,193 @@
|
|||
* USA
|
||||
*/
|
||||
|
||||
class Preedit : Gtk.Window {
|
||||
private Gtk.Label m_extension_preedit_text;
|
||||
private Gtk.Label m_extension_preedit_emoji;
|
||||
private IBus.Text? m_engine_preedit_text;
|
||||
private bool m_engine_preedit_text_show;
|
||||
private uint m_engine_preedit_cursor_pos;
|
||||
private string m_prefix = "@";
|
||||
private bool m_is_shown = true;
|
||||
|
||||
|
||||
public Preedit() {
|
||||
GLib.Object(
|
||||
name : "IBusPreedit",
|
||||
type: Gtk.WindowType.POPUP
|
||||
);
|
||||
m_extension_preedit_text = new Gtk.Label("");
|
||||
m_extension_preedit_emoji = new Gtk.Label("");
|
||||
}
|
||||
|
||||
|
||||
public new void hide() {
|
||||
reset();
|
||||
base.hide();
|
||||
m_is_shown = false;
|
||||
}
|
||||
|
||||
|
||||
public bool is_shown() {
|
||||
return m_is_shown;
|
||||
}
|
||||
|
||||
|
||||
public void reset() {
|
||||
set_emoji("");
|
||||
set_text("");
|
||||
resize(1, 1);
|
||||
m_is_shown = true;
|
||||
}
|
||||
|
||||
public void append_text(string text) {
|
||||
if (text.length == 0)
|
||||
return;
|
||||
string total = m_extension_preedit_text.get_text();
|
||||
total += text;
|
||||
m_extension_preedit_text.set_text(total);
|
||||
}
|
||||
|
||||
|
||||
public string get_text() {
|
||||
return m_extension_preedit_text.get_text();
|
||||
}
|
||||
|
||||
|
||||
public void set_text(string text) {
|
||||
m_extension_preedit_text.set_text(text);
|
||||
}
|
||||
|
||||
|
||||
public string get_emoji() {
|
||||
return m_extension_preedit_emoji.get_text();
|
||||
}
|
||||
|
||||
|
||||
public void set_emoji(string text) {
|
||||
m_extension_preedit_emoji.set_text(text);
|
||||
}
|
||||
|
||||
|
||||
public bool backspace() {
|
||||
string total = m_extension_preedit_emoji.get_text();
|
||||
if (total.length > 0) {
|
||||
m_extension_preedit_emoji.set_text("");
|
||||
resize(1, 1);
|
||||
return false;
|
||||
}
|
||||
total = m_extension_preedit_text.get_text();
|
||||
int char_count = total.char_count();
|
||||
if (char_count == 0)
|
||||
return true;
|
||||
total = total[0:total.index_of_nth_char(char_count - 1)];
|
||||
resize(1, 1);
|
||||
m_extension_preedit_text.set_text(total);
|
||||
if (total.length == 0)
|
||||
resize(1, 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
private string get_extension_text () {
|
||||
string extension_text = m_extension_preedit_emoji.get_text();
|
||||
if (extension_text.length == 0)
|
||||
extension_text = m_extension_preedit_text.get_text();
|
||||
return m_prefix + extension_text;
|
||||
}
|
||||
|
||||
|
||||
private void set_preedit_color(IBus.Text text,
|
||||
uint start_index,
|
||||
uint end_index) {
|
||||
text.append_attribute(IBus.AttrType.UNDERLINE,
|
||||
IBus.AttrUnderline.SINGLE,
|
||||
start_index, (int)end_index);
|
||||
}
|
||||
|
||||
|
||||
public IBus.Text get_engine_preedit_text() {
|
||||
string extension_text = get_extension_text();
|
||||
uint char_count = extension_text.char_count();
|
||||
IBus.Text retval;
|
||||
if (m_engine_preedit_text == null || !m_engine_preedit_text_show) {
|
||||
retval = new IBus.Text.from_string(extension_text);
|
||||
set_preedit_color(retval, 0, char_count);
|
||||
return retval;
|
||||
}
|
||||
retval = new IBus.Text.from_string(
|
||||
extension_text + m_engine_preedit_text.get_text());
|
||||
set_preedit_color(retval, 0, char_count);
|
||||
|
||||
unowned IBus.AttrList attrs = m_engine_preedit_text.get_attributes();
|
||||
|
||||
if (attrs == null)
|
||||
return retval;
|
||||
|
||||
int i = 0;
|
||||
while (true) {
|
||||
IBus.Attribute attr = attrs.get(i++);
|
||||
if (attr == null)
|
||||
break;
|
||||
long start_index = attr.start_index;
|
||||
long end_index = attr.end_index;
|
||||
if (start_index < 0)
|
||||
start_index = 0;
|
||||
if (end_index < 0)
|
||||
end_index = m_engine_preedit_text.get_length();
|
||||
retval.append_attribute(attr.type, attr.value,
|
||||
char_count + (uint)start_index,
|
||||
(int)char_count + (int)end_index);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
public void set_engine_preedit_text(IBus.Text? text) {
|
||||
m_engine_preedit_text = text;
|
||||
}
|
||||
|
||||
|
||||
public void show_engine_preedit_text() {
|
||||
m_engine_preedit_text_show = true;
|
||||
}
|
||||
|
||||
|
||||
public void hide_engine_preedit_text() {
|
||||
m_engine_preedit_text_show = false;
|
||||
}
|
||||
|
||||
|
||||
public uint get_engine_preedit_cursor_pos() {
|
||||
return get_extension_text().char_count() + m_engine_preedit_cursor_pos;
|
||||
}
|
||||
|
||||
|
||||
public void set_engine_preedit_cursor_pos(uint cursor_pos) {
|
||||
m_engine_preedit_cursor_pos = cursor_pos;
|
||||
}
|
||||
|
||||
|
||||
public IBus.Text get_commit_text() {
|
||||
string extension_text = m_extension_preedit_emoji.get_text();
|
||||
if (extension_text.length == 0)
|
||||
extension_text = m_extension_preedit_text.get_text();
|
||||
return new IBus.Text.from_string(extension_text);
|
||||
}
|
||||
|
||||
|
||||
public void set_extension_name(string extension_name) {
|
||||
if (extension_name.length == 0)
|
||||
m_prefix = "@";
|
||||
else
|
||||
m_prefix = extension_name[0:1];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class PanelBinding : IBus.PanelService {
|
||||
private bool m_is_wayland;
|
||||
private bool m_wayland_lookup_table_is_visible;
|
||||
private IBus.Bus m_bus;
|
||||
private Gtk.Application m_application;
|
||||
private GLib.Settings m_settings_panel = null;
|
||||
|
@ -38,18 +224,26 @@ class PanelBinding : IBus.PanelService {
|
|||
private bool m_loaded_emoji = false;
|
||||
private bool m_load_unicode_at_startup;
|
||||
private bool m_loaded_unicode = false;
|
||||
private bool m_enable_extension;
|
||||
private string m_extension_name = "";
|
||||
private Preedit m_preedit;
|
||||
|
||||
public PanelBinding(IBus.Bus bus,
|
||||
Gtk.Application application) {
|
||||
GLib.assert(bus.is_connected());
|
||||
// Chain up base class constructor
|
||||
GLib.Object(connection : bus.get_connection(),
|
||||
object_path : IBus.PATH_PANEL_EXTENSION);
|
||||
object_path : IBus.PATH_PANEL_EXTENSION_EMOJI);
|
||||
|
||||
Type instance_type = Gdk.Display.get_default().get_type();
|
||||
Type wayland_type = typeof(GdkWayland.Display);
|
||||
m_is_wayland = instance_type.is_a(wayland_type);
|
||||
|
||||
m_bus = bus;
|
||||
m_application = application;
|
||||
|
||||
init_settings();
|
||||
m_preedit = new Preedit();
|
||||
}
|
||||
|
||||
|
||||
|
@ -69,12 +263,20 @@ class PanelBinding : IBus.PanelService {
|
|||
ref m_css_provider);
|
||||
});
|
||||
|
||||
m_settings_emoji.changed["unicode-hotkey"].connect((key) => {
|
||||
set_emoji_hotkey();
|
||||
});
|
||||
|
||||
m_settings_emoji.changed["font"].connect((key) => {
|
||||
BindingCommon.set_custom_font(m_settings_panel,
|
||||
m_settings_emoji,
|
||||
ref m_css_provider);
|
||||
});
|
||||
|
||||
m_settings_emoji.changed["hotkey"].connect((key) => {
|
||||
set_emoji_hotkey();
|
||||
});
|
||||
|
||||
m_settings_emoji.changed["favorites"].connect((key) => {
|
||||
set_emoji_favorites();
|
||||
});
|
||||
|
@ -109,6 +311,54 @@ class PanelBinding : IBus.PanelService {
|
|||
}
|
||||
|
||||
|
||||
private unowned
|
||||
IBus.ProcessKeyEventData? parse_accelerator(string accelerator) {
|
||||
IBus.ProcessKeyEventData key = {};
|
||||
uint keysym = 0;
|
||||
IBus.ModifierType modifiers = 0;
|
||||
IBus.accelerator_parse(accelerator,
|
||||
out keysym, out modifiers);
|
||||
if (keysym == 0U && modifiers == 0) {
|
||||
warning("Failed to parse shortcut key '%s'".printf(accelerator));
|
||||
return null;
|
||||
}
|
||||
if ((modifiers & IBus.ModifierType.SUPER_MASK) != 0) {
|
||||
modifiers ^= IBus.ModifierType.SUPER_MASK;
|
||||
modifiers |= IBus.ModifierType.MOD4_MASK;
|
||||
}
|
||||
key.keyval = keysym;
|
||||
key.state = modifiers;
|
||||
return key;
|
||||
}
|
||||
|
||||
|
||||
private void set_emoji_hotkey() {
|
||||
IBus.ProcessKeyEventData[] emoji_keys = {};
|
||||
IBus.ProcessKeyEventData key;
|
||||
string[] accelerators = m_settings_emoji.get_strv("hotkey");
|
||||
foreach (var accelerator in accelerators) {
|
||||
key = parse_accelerator(accelerator);
|
||||
emoji_keys += key;
|
||||
}
|
||||
|
||||
/* Since {} is not allocated, parse_accelerator() should be unowned. */
|
||||
key = {};
|
||||
emoji_keys += key;
|
||||
|
||||
IBus.ProcessKeyEventData[] unicode_keys = {};
|
||||
accelerators = m_settings_emoji.get_strv("unicode-hotkey");
|
||||
foreach (var accelerator in accelerators) {
|
||||
key = parse_accelerator(accelerator);
|
||||
unicode_keys += key;
|
||||
}
|
||||
key = {};
|
||||
unicode_keys += key;
|
||||
|
||||
panel_extension_register_keys("emoji", emoji_keys,
|
||||
"unicode", unicode_keys);
|
||||
}
|
||||
|
||||
|
||||
private void set_emoji_favorites() {
|
||||
m_emojier_favorites = m_settings_emoji.get_strv("favorites");
|
||||
IBusEmojier.set_favorites(
|
||||
|
@ -159,6 +409,7 @@ class PanelBinding : IBus.PanelService {
|
|||
|
||||
public void load_settings() {
|
||||
|
||||
set_emoji_hotkey();
|
||||
set_load_emoji_at_startup();
|
||||
set_load_unicode_at_startup();
|
||||
BindingCommon.set_custom_font(m_settings_panel,
|
||||
|
@ -181,36 +432,37 @@ class PanelBinding : IBus.PanelService {
|
|||
GLib.Source.remove(m_emojier_set_emoji_lang_id);
|
||||
m_emojier_set_emoji_lang_id = 0;
|
||||
}
|
||||
if (m_emojier != null) {
|
||||
m_application.remove_window(m_emojier);
|
||||
m_emojier = null;
|
||||
}
|
||||
m_application = null;
|
||||
}
|
||||
|
||||
|
||||
private void show_emojier(Gdk.Event event) {
|
||||
if (!m_loaded_emoji)
|
||||
set_emoji_lang();
|
||||
if (!m_loaded_unicode && m_loaded_emoji) {
|
||||
IBusEmojier.load_unicode_dict();
|
||||
m_loaded_unicode = true;
|
||||
}
|
||||
m_emojier = new IBusEmojier();
|
||||
// For title handling in gnome-shell
|
||||
m_application.add_window(m_emojier);
|
||||
string emoji = m_emojier.run(m_real_current_context_path, event);
|
||||
m_application.remove_window(m_emojier);
|
||||
if (emoji == null) {
|
||||
m_emojier = null;
|
||||
private void commit_text_update_favorites(IBus.Text text) {
|
||||
commit_text(text);
|
||||
IBus.ExtensionEvent event = new IBus.ExtensionEvent(
|
||||
"name", m_extension_name,
|
||||
"is-enabled", false,
|
||||
"is-extension", true);
|
||||
panel_extension(event);
|
||||
string committed_string = text.text;
|
||||
string preedit_string = m_preedit.get_text();
|
||||
m_preedit.hide();
|
||||
if (preedit_string == committed_string)
|
||||
return;
|
||||
bool has_favorite = false;
|
||||
foreach (unowned string favorite in m_emojier_favorites) {
|
||||
if (favorite == committed_string) {
|
||||
has_favorite = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.emojier_focus_commit();
|
||||
}
|
||||
|
||||
|
||||
private void handle_emoji_typing(Gdk.Event event) {
|
||||
if (m_emojier != null && m_emojier.is_running()) {
|
||||
m_emojier.present_centralize(event);
|
||||
return;
|
||||
if (!has_favorite) {
|
||||
m_emojier_favorites += committed_string;
|
||||
m_settings_emoji.set_strv("favorites", m_emojier_favorites);
|
||||
}
|
||||
show_emojier(event);
|
||||
}
|
||||
|
||||
|
||||
|
@ -223,19 +475,8 @@ class PanelBinding : IBus.PanelService {
|
|||
prev_context_path != "" &&
|
||||
prev_context_path == m_current_context_path) {
|
||||
IBus.Text text = new IBus.Text.from_string(selected_string);
|
||||
commit_text(text);
|
||||
m_emojier = null;
|
||||
bool has_favorite = false;
|
||||
foreach (unowned string favorite in m_emojier_favorites) {
|
||||
if (favorite == selected_string) {
|
||||
has_favorite = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!has_favorite) {
|
||||
m_emojier_favorites += selected_string;
|
||||
m_settings_emoji.set_strv("favorites", m_emojier_favorites);
|
||||
}
|
||||
commit_text_update_favorites(text);
|
||||
m_emojier.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -249,8 +490,7 @@ class PanelBinding : IBus.PanelService {
|
|||
string selected_string = m_emojier.get_selected_string();
|
||||
string prev_context_path = m_emojier.get_input_context_path();
|
||||
if (selected_string == null &&
|
||||
prev_context_path != "" &&
|
||||
m_emojier.is_running()) {
|
||||
prev_context_path != "") {
|
||||
var context = GLib.MainContext.default();
|
||||
if (m_emojier_focus_commit_text_id > 0 &&
|
||||
context.find_source_by_id(m_emojier_focus_commit_text_id)
|
||||
|
@ -277,6 +517,243 @@ class PanelBinding : IBus.PanelService {
|
|||
}
|
||||
|
||||
|
||||
private bool key_press_escape() {
|
||||
if (is_emoji_lookup_table()) {
|
||||
bool show_candidate = m_emojier.key_press_escape();
|
||||
convert_preedit_text();
|
||||
return show_candidate;
|
||||
}
|
||||
if (m_preedit.get_emoji() != "") {
|
||||
m_preedit.set_emoji("");
|
||||
string annotation = m_preedit.get_text();
|
||||
m_emojier.set_annotation(annotation);
|
||||
return false;
|
||||
}
|
||||
m_enable_extension = false;
|
||||
hide_emoji_lookup_table();
|
||||
m_preedit.hide();
|
||||
IBus.ExtensionEvent event = new IBus.ExtensionEvent(
|
||||
"name", m_extension_name,
|
||||
"is-enabled", false,
|
||||
"is-extension", true);
|
||||
panel_extension(event);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private bool key_press_enter() {
|
||||
if (m_extension_name != "unicode" && is_emoji_lookup_table()) {
|
||||
// Check if variats exist
|
||||
if (m_emojier.key_press_enter())
|
||||
return true;
|
||||
}
|
||||
IBus.Text text = m_preedit.get_commit_text();
|
||||
commit_text_update_favorites(text);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private void convert_preedit_text() {
|
||||
if (m_emojier.get_number_of_candidates() > 0)
|
||||
m_preedit.set_emoji(m_emojier.get_current_candidate());
|
||||
else
|
||||
m_preedit.set_emoji("");
|
||||
}
|
||||
|
||||
|
||||
private bool key_press_space() {
|
||||
bool show_candidate = false;
|
||||
if (m_preedit.get_emoji() != "") {
|
||||
m_emojier.key_press_cursor_horizontal(Gdk.Key.Right, 0);
|
||||
show_candidate = true;
|
||||
} else {
|
||||
string annotation = m_preedit.get_text();
|
||||
if (annotation.length == 0) {
|
||||
show_candidate = true;
|
||||
if (is_emoji_lookup_table())
|
||||
m_emojier.key_press_cursor_horizontal(Gdk.Key.Right, 0);
|
||||
} else {
|
||||
m_emojier.set_annotation(annotation);
|
||||
}
|
||||
}
|
||||
convert_preedit_text();
|
||||
return show_candidate;
|
||||
}
|
||||
|
||||
|
||||
private bool key_press_cursor_horizontal(uint keyval,
|
||||
uint modifiers) {
|
||||
if (is_emoji_lookup_table()) {
|
||||
m_emojier.key_press_cursor_horizontal(keyval, modifiers);
|
||||
convert_preedit_text();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private bool key_press_cursor_vertical(uint keyval,
|
||||
uint modifiers) {
|
||||
if (is_emoji_lookup_table()) {
|
||||
m_emojier.key_press_cursor_vertical(keyval, modifiers);
|
||||
convert_preedit_text();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private bool key_press_cursor_home_end(uint keyval,
|
||||
uint modifiers) {
|
||||
if (is_emoji_lookup_table()) {
|
||||
m_emojier.key_press_cursor_home_end(keyval, modifiers);
|
||||
convert_preedit_text();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private bool key_press_control_keyval(uint keyval,
|
||||
uint modifiers) {
|
||||
bool show_candidate = false;
|
||||
switch(keyval) {
|
||||
case Gdk.Key.f:
|
||||
show_candidate = key_press_cursor_horizontal(Gdk.Key.Right,
|
||||
modifiers);
|
||||
break;
|
||||
case Gdk.Key.b:
|
||||
show_candidate = key_press_cursor_horizontal(Gdk.Key.Left,
|
||||
modifiers);
|
||||
break;
|
||||
case Gdk.Key.n:
|
||||
case Gdk.Key.N:
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Down, modifiers);
|
||||
break;
|
||||
case Gdk.Key.p:
|
||||
case Gdk.Key.P:
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Up, modifiers);
|
||||
break;
|
||||
case Gdk.Key.h:
|
||||
show_candidate = key_press_cursor_home_end(Gdk.Key.Home, modifiers);
|
||||
break;
|
||||
case Gdk.Key.e:
|
||||
show_candidate = key_press_cursor_home_end(Gdk.Key.End, modifiers);
|
||||
break;
|
||||
case Gdk.Key.u:
|
||||
m_preedit.reset();
|
||||
m_emojier.set_annotation("");
|
||||
hide_emoji_lookup_table();
|
||||
break;
|
||||
case Gdk.Key.C:
|
||||
case Gdk.Key.c:
|
||||
if ((modifiers & Gdk.ModifierType.SHIFT_MASK) != 0) {
|
||||
if (!m_is_wayland && m_emojier != null &&
|
||||
m_emojier.get_number_of_candidates() > 0) {
|
||||
var text = m_emojier.get_current_candidate();
|
||||
Gtk.Clipboard clipboard =
|
||||
Gtk.Clipboard.get(Gdk.SELECTION_CLIPBOARD);
|
||||
clipboard.set_text(text, -1);
|
||||
clipboard.store();
|
||||
}
|
||||
show_candidate = is_emoji_lookup_table();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
show_candidate = is_emoji_lookup_table();
|
||||
break;
|
||||
}
|
||||
return show_candidate;
|
||||
}
|
||||
|
||||
|
||||
private void hide_wayland_lookup_table() {
|
||||
m_wayland_lookup_table_is_visible = false;
|
||||
var text = new IBus.Text.from_string("");
|
||||
update_auxiliary_text_received(text, false);
|
||||
update_lookup_table_received(
|
||||
new IBus.LookupTable(1, 0, false, true),
|
||||
false);
|
||||
}
|
||||
|
||||
|
||||
private void show_wayland_lookup_table(IBus.Text text) {
|
||||
m_wayland_lookup_table_is_visible = true;
|
||||
var table = m_emojier.get_one_dimension_lookup_table();
|
||||
uint ncandidates = table.get_number_of_candidates();
|
||||
update_auxiliary_text_received(
|
||||
text,
|
||||
ncandidates > 0 ? true : false);
|
||||
update_lookup_table_received(
|
||||
table,
|
||||
ncandidates > 0 ? true : false);
|
||||
}
|
||||
|
||||
|
||||
private bool is_visible_wayland_lookup_table() {
|
||||
return m_wayland_lookup_table_is_visible;
|
||||
}
|
||||
|
||||
|
||||
private void hide_emoji_lookup_table() {
|
||||
if (m_emojier == null)
|
||||
return;
|
||||
if (m_is_wayland)
|
||||
hide_wayland_lookup_table();
|
||||
else
|
||||
m_emojier.hide();
|
||||
}
|
||||
|
||||
|
||||
private void show_emoji_lookup_table() {
|
||||
/* Emojier category_list is shown in both Xorg and Wayland
|
||||
* because the annotation information is useful but the Wayland lookup
|
||||
* window is alway one dimension. So the category_list is shown
|
||||
* when the user annotation is null.
|
||||
*/
|
||||
if (m_is_wayland && m_preedit.get_text() != "") {
|
||||
var text = m_emojier.get_title_text();
|
||||
show_wayland_lookup_table(text);
|
||||
} else {
|
||||
// POPUP window takes the focus in Wayland.
|
||||
if (m_is_wayland)
|
||||
m_emojier.set_input_context_path(m_real_current_context_path);
|
||||
m_emojier.show_all();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private bool is_emoji_lookup_table() {
|
||||
if (m_is_wayland)
|
||||
return is_visible_wayland_lookup_table();
|
||||
else
|
||||
return m_emojier.get_visible();
|
||||
}
|
||||
|
||||
|
||||
private void show_preedit_and_candidate(bool show_candidate) {
|
||||
uint cursor_pos = 0;
|
||||
if (!show_candidate)
|
||||
cursor_pos = m_preedit.get_engine_preedit_cursor_pos();
|
||||
update_preedit_text_received(
|
||||
m_preedit.get_engine_preedit_text(),
|
||||
cursor_pos,
|
||||
true);
|
||||
if (!show_candidate) {
|
||||
hide_emoji_lookup_table();
|
||||
return;
|
||||
}
|
||||
if (m_emojier == null)
|
||||
return;
|
||||
/* Wayland gives the focus on Emojir which is a GTK popup window
|
||||
* and move the focus fom the current input context to Emojier.
|
||||
* This forwards the lookup table to gnome-shell's lookup table
|
||||
* but it enables one dimension lookup table only.
|
||||
*/
|
||||
show_emoji_lookup_table();
|
||||
}
|
||||
|
||||
|
||||
public override void focus_in(string input_context_path) {
|
||||
m_current_context_path = input_context_path;
|
||||
|
||||
|
@ -299,48 +776,280 @@ class PanelBinding : IBus.PanelService {
|
|||
}
|
||||
|
||||
|
||||
public override void panel_extension_received(GLib.Variant data) {
|
||||
IBus.XEvent? xevent = IBus.Serializable.deserialize_object(data)
|
||||
as IBus.XEvent;
|
||||
if (xevent == null) {
|
||||
warning ("Failed to deserialize IBusXEvent");
|
||||
public override void panel_extension_received(IBus.ExtensionEvent event) {
|
||||
m_extension_name = event.get_name();
|
||||
if (m_extension_name != "emoji" && m_extension_name != "unicode") {
|
||||
string format = "The name %s is not implemented in PanelExtension";
|
||||
warning (format.printf(m_extension_name));
|
||||
m_extension_name = "";
|
||||
return;
|
||||
}
|
||||
if (xevent.get_purpose() != "emoji") {
|
||||
string format = "The purpose %s is not implemented in PanelExtension";
|
||||
warning (format.printf(xevent.get_purpose()));
|
||||
m_enable_extension = event.is_enabled;
|
||||
if (!m_enable_extension) {
|
||||
hide_emoji_lookup_table();
|
||||
return;
|
||||
}
|
||||
Gdk.EventType event_type;
|
||||
if (xevent.get_event_type() == IBus.XEventType.KEY_PRESS) {
|
||||
event_type = Gdk.EventType.KEY_PRESS;
|
||||
} else if (xevent.get_event_type() == IBus.XEventType.KEY_RELEASE) {
|
||||
event_type = Gdk.EventType.KEY_RELEASE;
|
||||
if (!m_loaded_emoji)
|
||||
set_emoji_lang();
|
||||
if (!m_loaded_unicode && m_loaded_emoji) {
|
||||
IBusEmojier.load_unicode_dict();
|
||||
m_loaded_unicode = true;
|
||||
}
|
||||
if (m_emojier == null) {
|
||||
m_emojier = new IBusEmojier();
|
||||
// For title handling in gnome-shell
|
||||
m_application.add_window(m_emojier);
|
||||
m_emojier.candidate_clicked.connect((i, b, s) => {
|
||||
if (!m_is_wayland)
|
||||
candidate_clicked_lookup_table(i, b, s);
|
||||
});
|
||||
}
|
||||
m_emojier.reset();
|
||||
m_emojier.set_annotation("");
|
||||
m_preedit.set_extension_name(m_extension_name);
|
||||
m_preedit.reset();
|
||||
update_preedit_text_received(
|
||||
m_preedit.get_engine_preedit_text(),
|
||||
m_preedit.get_engine_preedit_cursor_pos(),
|
||||
true);
|
||||
string params = event.get_params();
|
||||
if (params == "category-list") {
|
||||
key_press_space();
|
||||
show_preedit_and_candidate(true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public override void set_cursor_location(int x,
|
||||
int y,
|
||||
int width,
|
||||
int height) {
|
||||
if (m_emojier != null)
|
||||
m_emojier.set_cursor_location(x, y, width, height);
|
||||
}
|
||||
|
||||
|
||||
public override void update_preedit_text(IBus.Text text,
|
||||
uint cursor_pos,
|
||||
bool visible) {
|
||||
m_preedit.set_engine_preedit_text(text);
|
||||
if (visible)
|
||||
m_preedit.show_engine_preedit_text();
|
||||
else
|
||||
m_preedit.hide_engine_preedit_text();
|
||||
m_preedit.set_engine_preedit_cursor_pos(cursor_pos);
|
||||
update_preedit_text_received(m_preedit.get_engine_preedit_text(),
|
||||
m_preedit.get_engine_preedit_cursor_pos(),
|
||||
visible);
|
||||
}
|
||||
|
||||
|
||||
public override void show_preedit_text() {
|
||||
m_preedit.show_engine_preedit_text();
|
||||
show_preedit_and_candidate(false);
|
||||
}
|
||||
|
||||
|
||||
public override void hide_preedit_text() {
|
||||
m_preedit.hide_engine_preedit_text();
|
||||
show_preedit_and_candidate(false);
|
||||
}
|
||||
|
||||
|
||||
public override bool process_key_event(uint keyval,
|
||||
uint keycode,
|
||||
uint state) {
|
||||
if ((state & IBus.ModifierType.RELEASE_MASK) != 0)
|
||||
return false;
|
||||
uint modifiers = state;
|
||||
bool show_candidate = false;
|
||||
switch(keyval) {
|
||||
case Gdk.Key.Escape:
|
||||
show_candidate = key_press_escape();
|
||||
if (!m_preedit.is_shown())
|
||||
return true;
|
||||
break;
|
||||
case Gdk.Key.Return:
|
||||
case Gdk.Key.KP_Enter:
|
||||
if (m_extension_name == "unicode")
|
||||
key_press_space();
|
||||
show_candidate = key_press_enter();
|
||||
if (!m_preedit.is_shown()) {
|
||||
hide_emoji_lookup_table();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Gdk.Key.BackSpace:
|
||||
m_preedit.backspace();
|
||||
string annotation = m_preedit.get_text();
|
||||
if (annotation == "" && m_extension_name == "unicode") {
|
||||
key_press_escape();
|
||||
return true;
|
||||
}
|
||||
m_emojier.set_annotation(annotation);
|
||||
break;
|
||||
case Gdk.Key.space:
|
||||
case Gdk.Key.KP_Space:
|
||||
show_candidate = key_press_space();
|
||||
if (m_extension_name == "unicode") {
|
||||
key_press_enter();
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case Gdk.Key.Right:
|
||||
case Gdk.Key.KP_Right:
|
||||
/* one dimension in Wayland, two dimensions in X11 */
|
||||
if (m_is_wayland) {
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Down,
|
||||
modifiers);
|
||||
} else {
|
||||
show_candidate = key_press_cursor_horizontal(Gdk.Key.Right,
|
||||
modifiers);
|
||||
}
|
||||
break;
|
||||
case Gdk.Key.Left:
|
||||
case Gdk.Key.KP_Left:
|
||||
if (m_is_wayland) {
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Up,
|
||||
modifiers);
|
||||
} else {
|
||||
show_candidate = key_press_cursor_horizontal(Gdk.Key.Left,
|
||||
modifiers);
|
||||
}
|
||||
break;
|
||||
case Gdk.Key.Down:
|
||||
case Gdk.Key.KP_Down:
|
||||
if (m_is_wayland) {
|
||||
show_candidate = key_press_cursor_horizontal(Gdk.Key.Right,
|
||||
modifiers);
|
||||
} else {
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Down,
|
||||
modifiers);
|
||||
}
|
||||
break;
|
||||
case Gdk.Key.Up:
|
||||
case Gdk.Key.KP_Up:
|
||||
if (m_is_wayland) {
|
||||
show_candidate = key_press_cursor_horizontal(Gdk.Key.Left,
|
||||
modifiers);
|
||||
} else {
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Up,
|
||||
modifiers);
|
||||
}
|
||||
break;
|
||||
case Gdk.Key.Page_Down:
|
||||
case Gdk.Key.KP_Page_Down:
|
||||
if (m_is_wayland) {
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Down,
|
||||
modifiers);
|
||||
} else {
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Page_Down,
|
||||
modifiers);
|
||||
}
|
||||
break;
|
||||
case Gdk.Key.Page_Up:
|
||||
case Gdk.Key.KP_Page_Up:
|
||||
if (m_is_wayland) {
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Up,
|
||||
modifiers);
|
||||
} else {
|
||||
show_candidate = key_press_cursor_vertical(Gdk.Key.Page_Up,
|
||||
modifiers);
|
||||
}
|
||||
break;
|
||||
case Gdk.Key.Home:
|
||||
case Gdk.Key.KP_Home:
|
||||
show_candidate = key_press_cursor_home_end(Gdk.Key.Home, modifiers);
|
||||
break;
|
||||
case Gdk.Key.End:
|
||||
case Gdk.Key.KP_End:
|
||||
show_candidate = key_press_cursor_home_end(Gdk.Key.End, modifiers);
|
||||
break;
|
||||
default:
|
||||
if ((modifiers & Gdk.ModifierType.CONTROL_MASK) != 0) {
|
||||
show_candidate = key_press_control_keyval(keyval, modifiers);
|
||||
break;
|
||||
}
|
||||
unichar ch = IBus.keyval_to_unicode(keyval);
|
||||
if (ch.iscntrl())
|
||||
return true;
|
||||
string str = ch.to_string();
|
||||
m_preedit.append_text(str);
|
||||
string annotation = m_preedit.get_text();
|
||||
m_emojier.set_annotation(annotation);
|
||||
m_preedit.set_emoji("");
|
||||
show_candidate = is_emoji_lookup_table();
|
||||
break;
|
||||
}
|
||||
show_preedit_and_candidate(show_candidate);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void commit_text_received(IBus.Text text) {
|
||||
unowned string? str = text.text;
|
||||
if (str == null)
|
||||
return;
|
||||
/* Do not call convert_preedit_text() because it depends on
|
||||
* each IME whether process_key_event() receives Shift-space or not.
|
||||
*/
|
||||
m_preedit.append_text(str);
|
||||
m_preedit.set_emoji("");
|
||||
string annotation = m_preedit.get_text();
|
||||
m_emojier.set_annotation(annotation);
|
||||
show_preedit_and_candidate(false);
|
||||
}
|
||||
|
||||
public override void page_up_lookup_table() {
|
||||
bool show_candidate = key_press_cursor_vertical(Gdk.Key.Up, 0);
|
||||
show_preedit_and_candidate(show_candidate);
|
||||
}
|
||||
|
||||
public override void page_down_lookup_table() {
|
||||
bool show_candidate = key_press_cursor_vertical(Gdk.Key.Down, 0);
|
||||
show_preedit_and_candidate(show_candidate);
|
||||
}
|
||||
|
||||
public override void cursor_up_lookup_table() {
|
||||
bool show_candidate = key_press_cursor_horizontal(Gdk.Key.Left, 0);
|
||||
show_preedit_and_candidate(show_candidate);
|
||||
}
|
||||
|
||||
public override void cursor_down_lookup_table() {
|
||||
bool show_candidate = key_press_cursor_horizontal(Gdk.Key.Right, 0);
|
||||
show_preedit_and_candidate(show_candidate);
|
||||
}
|
||||
|
||||
public override void candidate_clicked_lookup_table(uint index,
|
||||
uint button,
|
||||
uint state) {
|
||||
if (button == IBusEmojier.BUTTON_CLOSE_BUTTON) {
|
||||
m_enable_extension = false;
|
||||
hide_emoji_lookup_table();
|
||||
m_preedit.hide();
|
||||
IBus.ExtensionEvent event = new IBus.ExtensionEvent(
|
||||
"name", m_extension_name,
|
||||
"is-enabled", false,
|
||||
"is-extension", true);
|
||||
panel_extension(event);
|
||||
return;
|
||||
}
|
||||
if (m_emojier == null)
|
||||
return;
|
||||
bool show_candidate = false;
|
||||
uint ncandidates = m_emojier.get_number_of_candidates();
|
||||
if (ncandidates > 0 && ncandidates >= index) {
|
||||
m_emojier.set_cursor_pos(index);
|
||||
show_candidate = m_emojier.has_variants(index);
|
||||
m_preedit.set_emoji(m_emojier.get_current_candidate());
|
||||
} else {
|
||||
warning ("Not supported type %d".printf(xevent.get_event_type()));
|
||||
return;
|
||||
}
|
||||
Gdk.Event event = new Gdk.Event(event_type);
|
||||
uint32 time = xevent.get_time();
|
||||
if (time == 0)
|
||||
time = Gtk.get_current_event_time();
|
||||
event.key.time = time;
|
||||
X.Window xid = xevent.get_window();
|
||||
Gdk.Display? display = Gdk.Display.get_default();
|
||||
Gdk.Window? window = null;
|
||||
if (window == null && xid != 0) {
|
||||
window = Gdk.X11.Window.lookup_for_display(
|
||||
display as Gdk.X11.Display, xid);
|
||||
if (!show_candidate) {
|
||||
IBus.Text text = m_preedit.get_commit_text();
|
||||
commit_text_update_favorites(text);
|
||||
hide_emoji_lookup_table();
|
||||
return;
|
||||
}
|
||||
if (window == null && xid != 0) {
|
||||
window = new Gdk.X11.Window.foreign_for_display(
|
||||
display as Gdk.X11.Display, xid);
|
||||
}
|
||||
if (window == null) {
|
||||
window = Gdk.get_default_root_window();
|
||||
window.ref();
|
||||
}
|
||||
event.key.window = window;
|
||||
handle_emoji_typing(event);
|
||||
show_preedit_and_candidate(show_candidate);
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче