Added ibus-621795-engineproxy-segv.patch
Fixes crash in ibus_object_destroy Added ibus-626652-leak.patch Fixes Bug 626652 - ibus memory leak with ibus_input_context_process_key_event Added ibus-541492-xkb.patch Fixes Bug 541492 - ibus needs to support some xkb layout switching Added ibus-435880-surrounding-text.patch Fixes Bug 435880 - ibus-gtk requires surrounding-text support
This commit is contained in:
parent
9b3b7484f1
commit
6cc8efa2db
659
ibus-435880-surrounding-text.patch
Normal file
659
ibus-435880-surrounding-text.patch
Normal file
@ -0,0 +1,659 @@
|
||||
From 34e8a6e359ac7c44ec6e66776feb8b47d12ec2c2 Mon Sep 17 00:00:00 2001
|
||||
From: Daiki Ueno <ueno@unixuser.org>
|
||||
Date: Tue, 14 Sep 2010 10:09:56 +0900
|
||||
Subject: [PATCH] Support surrounding-text retrieval.
|
||||
|
||||
This change adds a new API function ibus_engine_get_surrounding_text().
|
||||
In the implementation, engines do not proactively requests surrounding-text to
|
||||
target applications via the GTK+ client (IBusIMContext) every time the
|
||||
function is called. Instead, IBusIMContext retrieves surrounding-text when
|
||||
certain events occur in the input context (IBusInputContext) and maintains
|
||||
it within the input context.
|
||||
|
||||
This logic is similar to Qt's QInputContext. The following events trigger
|
||||
surrounding-text retrieval:
|
||||
|
||||
- focus_in
|
||||
- commit_text
|
||||
- show_preedit_text
|
||||
- (just before) process_key_event
|
||||
|
||||
Also,
|
||||
- destroy
|
||||
resets the current surrounding-text.
|
||||
---
|
||||
bus/engineproxy.c | 14 ++++++
|
||||
bus/engineproxy.h | 4 ++
|
||||
bus/inputcontext.c | 67 +++++++++++++++++++++++++++++++
|
||||
bus/inputcontext.h | 4 ++
|
||||
client/gtk2/ibusimcontext.c | 84 +++++++++++++++++++++++++++++++++++---
|
||||
src/ibusengine.c | 93 +++++++++++++++++++++++++++++++++++++++++++
|
||||
src/ibusengine.h | 21 +++++++++-
|
||||
src/ibusinputcontext.c | 14 ++++++
|
||||
src/ibusinputcontext.h | 11 +++++
|
||||
src/ibusmarshalers.list | 1 +
|
||||
10 files changed, 305 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/bus/engineproxy.c b/bus/engineproxy.c
|
||||
index 64dda4f..4193a30 100644
|
||||
--- a/bus/engineproxy.c
|
||||
+++ b/bus/engineproxy.c
|
||||
@@ -730,6 +730,20 @@ void bus_engine_proxy_property_hide (BusEngineProxy *engine,
|
||||
G_TYPE_INVALID);
|
||||
}
|
||||
|
||||
+void bus_engine_proxy_set_surrounding_text (BusEngineProxy *engine,
|
||||
+ IBusText *text,
|
||||
+ guint cursor_pos)
|
||||
+{
|
||||
+ g_assert (BUS_IS_ENGINE_PROXY (engine));
|
||||
+ g_assert (text != NULL);
|
||||
+
|
||||
+ ibus_proxy_call ((IBusProxy *) engine,
|
||||
+ "SetSurroundingText",
|
||||
+ IBUS_TYPE_TEXT, &text,
|
||||
+ G_TYPE_UINT, &cursor_pos,
|
||||
+ G_TYPE_INVALID);
|
||||
+}
|
||||
+
|
||||
#define DEFINE_FUNCTION(Name, name) \
|
||||
void \
|
||||
bus_engine_proxy_##name (BusEngineProxy *engine) \
|
||||
diff --git a/bus/engineproxy.h b/bus/engineproxy.h
|
||||
index 7c2626f..ae85da9 100644
|
||||
--- a/bus/engineproxy.h
|
||||
+++ b/bus/engineproxy.h
|
||||
@@ -111,5 +111,9 @@ void bus_engine_proxy_property_show (BusEngineProxy *engine,
|
||||
void bus_engine_proxy_property_hide (BusEngineProxy *engine,
|
||||
const gchar *prop_name);
|
||||
gboolean bus_engine_proxy_is_enabled (BusEngineProxy *engine);
|
||||
+void bus_engine_proxy_set_surrounding_text
|
||||
+ (BusEngineProxy *engine,
|
||||
+ IBusText *text,
|
||||
+ guint cursor_pos);
|
||||
G_END_DECLS
|
||||
#endif
|
||||
diff --git a/bus/inputcontext.c b/bus/inputcontext.c
|
||||
index d610515..f980108 100644
|
||||
--- a/bus/inputcontext.c
|
||||
+++ b/bus/inputcontext.c
|
||||
@@ -472,6 +472,9 @@ bus_input_context_init (BusInputContext *context)
|
||||
context->lookup_table = lookup_table_empty;
|
||||
context->lookup_table_visible = FALSE;
|
||||
|
||||
+ g_object_ref_sink (text_empty);
|
||||
+ context->surrounding_text = text_empty;
|
||||
+ context->surrounding_cursor_pos = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -514,6 +517,11 @@ bus_input_context_destroy (BusInputContext *context)
|
||||
context->client = NULL;
|
||||
}
|
||||
|
||||
+ if (context->surrounding_text) {
|
||||
+ g_object_unref (context->surrounding_text);
|
||||
+ context->surrounding_text = NULL;
|
||||
+ }
|
||||
+
|
||||
IBUS_OBJECT_CLASS(bus_input_context_parent_class)->destroy (IBUS_OBJECT (context));
|
||||
}
|
||||
|
||||
@@ -568,6 +576,10 @@ _ibus_introspect (BusInputContext *context,
|
||||
" <arg name=\"desc\" direction=\"out\" type=\"v\"/>\n"
|
||||
" </method>\n"
|
||||
" <method name=\"Destroy\"/>\n"
|
||||
+ " <method name=\"SetSurroundingText\">\n"
|
||||
+ " <arg name=\"text\" direction=\"in\" type=\"v\"/>\n"
|
||||
+ " <arg name=\"cursor_pos\" direction=\"in\" type=\"u\"/>\n"
|
||||
+ " </method>\n"
|
||||
|
||||
/* signals */
|
||||
" <signal name=\"CommitText\">\n"
|
||||
@@ -1097,6 +1109,60 @@ _ic_destroy (BusInputContext *context,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+static IBusMessage *
|
||||
+_ic_set_surrounding_text (BusInputContext *context,
|
||||
+ IBusMessage *message,
|
||||
+ BusConnection *connection)
|
||||
+{
|
||||
+ g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
+ g_assert (message != NULL);
|
||||
+ g_assert (BUS_IS_CONNECTION (connection));
|
||||
+
|
||||
+ IBusMessage *reply;
|
||||
+ IBusText *text;
|
||||
+ guint cursor_pos = 0;
|
||||
+ gboolean retval;
|
||||
+ IBusError *error;
|
||||
+
|
||||
+ retval = ibus_message_get_args (message,
|
||||
+ &error,
|
||||
+ IBUS_TYPE_TEXT, &text,
|
||||
+ G_TYPE_UINT, &cursor_pos,
|
||||
+ G_TYPE_INVALID);
|
||||
+
|
||||
+ if (!retval) {
|
||||
+ reply = ibus_message_new_error (message,
|
||||
+ error->name,
|
||||
+ error->message);
|
||||
+ ibus_error_free (error);
|
||||
+ return reply;
|
||||
+ }
|
||||
+
|
||||
+ if ((context->capabilities & IBUS_CAP_SURROUNDING_TEXT) &&
|
||||
+ (!context->surrounding_text ||
|
||||
+ g_strcmp0 (text->text, context->surrounding_text->text) != 0 ||
|
||||
+ cursor_pos != context->surrounding_cursor_pos)) {
|
||||
+ if (context->surrounding_text) {
|
||||
+ g_object_unref (context->surrounding_text);
|
||||
+ }
|
||||
+
|
||||
+ context->surrounding_text = (IBusText *) g_object_ref_sink (text ? text : text_empty);
|
||||
+ context->surrounding_cursor_pos = cursor_pos;
|
||||
+
|
||||
+ if (context->has_focus && context->enabled && context->engine) {
|
||||
+ bus_engine_proxy_set_surrounding_text (context->engine,
|
||||
+ text,
|
||||
+ cursor_pos);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (g_object_is_floating (text))
|
||||
+ g_object_unref (text);
|
||||
+
|
||||
+ reply = ibus_message_new_method_return (message);
|
||||
+ return reply;
|
||||
+}
|
||||
+
|
||||
static gboolean
|
||||
bus_input_context_ibus_message (BusInputContext *context,
|
||||
BusConnection *connection,
|
||||
@@ -1131,6 +1197,7 @@ bus_input_context_ibus_message (BusInputContext *context,
|
||||
{ IBUS_INTERFACE_INPUT_CONTEXT, "SetEngine", _ic_set_engine },
|
||||
{ IBUS_INTERFACE_INPUT_CONTEXT, "GetEngine", _ic_get_engine },
|
||||
{ IBUS_INTERFACE_INPUT_CONTEXT, "Destroy", _ic_destroy },
|
||||
+ { IBUS_INTERFACE_INPUT_CONTEXT, "SetSurroundingText",_ic_set_surrounding_text },
|
||||
};
|
||||
|
||||
ibus_message_set_sender (message, bus_connection_get_unique_name (connection));
|
||||
diff --git a/bus/inputcontext.h b/bus/inputcontext.h
|
||||
index ebbe4ba..4b20768 100644
|
||||
--- a/bus/inputcontext.h
|
||||
+++ b/bus/inputcontext.h
|
||||
@@ -91,6 +91,10 @@ struct _BusInputContext {
|
||||
|
||||
/* is fake context */
|
||||
gboolean fake;
|
||||
+
|
||||
+ /* surrounding text */
|
||||
+ IBusText *surrounding_text;
|
||||
+ guint surrounding_cursor_pos;
|
||||
};
|
||||
|
||||
struct _BusInputContextClass {
|
||||
diff --git a/client/gtk2/ibusimcontext.c b/client/gtk2/ibusimcontext.c
|
||||
index 2ddae8c..09a2260 100644
|
||||
--- a/client/gtk2/ibusimcontext.c
|
||||
+++ b/client/gtk2/ibusimcontext.c
|
||||
@@ -106,6 +106,12 @@ static void ibus_im_context_set_cursor_location
|
||||
static void ibus_im_context_set_use_preedit
|
||||
(GtkIMContext *context,
|
||||
gboolean use_preedit);
|
||||
+static void ibus_im_context_set_surrounding
|
||||
+ (GtkIMContext *slave,
|
||||
+ const gchar *text,
|
||||
+ gint len,
|
||||
+ gint cursor_index);
|
||||
+
|
||||
|
||||
/* static methods*/
|
||||
static void _create_input_context (IBusIMContext *context);
|
||||
@@ -124,10 +130,10 @@ static void _slave_preedit_start_cb (GtkIMContext *slave,
|
||||
IBusIMContext *context);
|
||||
static void _slave_preedit_end_cb (GtkIMContext *slave,
|
||||
IBusIMContext *context);
|
||||
-static void _slave_retrieve_surrounding_cb
|
||||
+static gboolean _slave_retrieve_surrounding_cb
|
||||
(GtkIMContext *slave,
|
||||
IBusIMContext *context);
|
||||
-static void _slave_delete_surrounding_cb
|
||||
+static gboolean _slave_delete_surrounding_cb
|
||||
(GtkIMContext *slave,
|
||||
gint offset_from_cursor,
|
||||
guint nchars,
|
||||
@@ -238,6 +244,12 @@ _key_snooper_cb (GtkWidget *widget,
|
||||
_input_window = event->window;
|
||||
}
|
||||
|
||||
+ if (ibusimcontext->enable) {
|
||||
+ gboolean return_value;
|
||||
+ g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
|
||||
+ &return_value);
|
||||
+ }
|
||||
+
|
||||
switch (event->type) {
|
||||
case GDK_KEY_RELEASE:
|
||||
retval = ibus_input_context_process_key_event (ibuscontext,
|
||||
@@ -284,6 +296,7 @@ ibus_im_context_class_init (IBusIMContextClass *klass)
|
||||
im_context_class->set_client_window = ibus_im_context_set_client_window;
|
||||
im_context_class->set_cursor_location = ibus_im_context_set_cursor_location;
|
||||
im_context_class->set_use_preedit = ibus_im_context_set_use_preedit;
|
||||
+ im_context_class->set_surrounding = ibus_im_context_set_surrounding;
|
||||
gobject_class->finalize = ibus_im_context_finalize;
|
||||
|
||||
_signal_commit_id =
|
||||
@@ -476,6 +489,12 @@ ibus_im_context_filter_keypress (GtkIMContext *context,
|
||||
if (ibusimcontext->client_window == NULL && event->window != NULL)
|
||||
gtk_im_context_set_client_window ((GtkIMContext *)ibusimcontext, event->window);
|
||||
|
||||
+ if (ibusimcontext->enable) {
|
||||
+ gboolean return_value;
|
||||
+ g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
|
||||
+ &return_value);
|
||||
+ }
|
||||
+
|
||||
switch (event->type) {
|
||||
case GDK_KEY_RELEASE:
|
||||
retval = ibus_input_context_process_key_event (ibusimcontext->ibuscontext,
|
||||
@@ -540,6 +559,12 @@ ibus_im_context_focus_in (GtkIMContext *context)
|
||||
g_object_weak_ref ((GObject *) context, _weak_notify_cb, NULL);
|
||||
_focus_im_context = context;
|
||||
}
|
||||
+
|
||||
+ if (ibusimcontext->enable) {
|
||||
+ gboolean return_value;
|
||||
+ g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
|
||||
+ &return_value);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -705,6 +730,34 @@ ibus_im_context_set_use_preedit (GtkIMContext *context, gboolean use_preedit)
|
||||
}
|
||||
|
||||
static void
|
||||
+ibus_im_context_set_surrounding (GtkIMContext *context,
|
||||
+ const gchar *text,
|
||||
+ gint len,
|
||||
+ gint cursor_index)
|
||||
+{
|
||||
+ g_return_if_fail (context != NULL);
|
||||
+ g_return_if_fail (IBUS_IS_IM_CONTEXT (context));
|
||||
+
|
||||
+ IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
||||
+
|
||||
+ if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
+ IBusText *ibustext;
|
||||
+ guint cursor_pos;
|
||||
+
|
||||
+ ibustext = ibus_text_new_from_string (text);
|
||||
+ cursor_pos = g_utf8_strlen (text, cursor_index);
|
||||
+ ibus_input_context_set_surrounding_text (ibusimcontext->ibuscontext,
|
||||
+ ibustext,
|
||||
+ cursor_pos);
|
||||
+ g_object_unref (ibustext);
|
||||
+ }
|
||||
+ gtk_im_context_set_surrounding (ibusimcontext->slave,
|
||||
+ text,
|
||||
+ len,
|
||||
+ cursor_index);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
_bus_connected_cb (IBusBus *bus,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
@@ -723,6 +776,12 @@ _ibus_context_commit_text_cb (IBusInputContext *ibuscontext,
|
||||
IDEBUG ("%s", __FUNCTION__);
|
||||
|
||||
g_signal_emit (ibusimcontext, _signal_commit_id, 0, text->text);
|
||||
+
|
||||
+ if (ibusimcontext->enable) {
|
||||
+ gboolean return_value;
|
||||
+ g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
|
||||
+ &return_value);
|
||||
+ }
|
||||
}
|
||||
|
||||
static gboolean
|
||||
@@ -953,6 +1012,12 @@ _ibus_context_show_preedit_text_cb (IBusInputContext *ibuscontext,
|
||||
ibusimcontext->preedit_visible = TRUE;
|
||||
g_signal_emit (ibusimcontext, _signal_preedit_start_id, 0);
|
||||
g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
|
||||
+
|
||||
+ if (ibusimcontext->enable) {
|
||||
+ gboolean return_value;
|
||||
+ g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
|
||||
+ &return_value);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -1117,17 +1182,21 @@ _slave_preedit_end_cb (GtkIMContext *slave,
|
||||
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
|
||||
}
|
||||
|
||||
-static void
|
||||
+static gboolean
|
||||
_slave_retrieve_surrounding_cb (GtkIMContext *slave,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
+ gboolean return_value;
|
||||
+
|
||||
if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
- return;
|
||||
+ return FALSE;
|
||||
}
|
||||
- g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0);
|
||||
+ g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
|
||||
+ &return_value);
|
||||
+ return return_value;
|
||||
}
|
||||
|
||||
-static void
|
||||
+static gboolean
|
||||
_slave_delete_surrounding_cb (GtkIMContext *slave,
|
||||
gint offset_from_cursor,
|
||||
guint nchars,
|
||||
@@ -1136,9 +1205,10 @@ _slave_delete_surrounding_cb (GtkIMContext *slave,
|
||||
gboolean return_value;
|
||||
|
||||
if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
- return;
|
||||
+ return FALSE;
|
||||
}
|
||||
g_signal_emit (ibusimcontext, _signal_delete_surrounding_id, 0, offset_from_cursor, nchars, &return_value);
|
||||
+ return return_value;
|
||||
}
|
||||
|
||||
#ifdef OS_CHROMEOS
|
||||
diff --git a/src/ibusengine.c b/src/ibusengine.c
|
||||
index 899d7c8..a5101bb 100644
|
||||
--- a/src/ibusengine.c
|
||||
+++ b/src/ibusengine.c
|
||||
@@ -44,6 +44,7 @@ enum {
|
||||
PROPERTY_SHOW,
|
||||
PROPERTY_HIDE,
|
||||
CANDIDATE_CLICKED,
|
||||
+ SET_SURROUNDING_TEXT,
|
||||
LAST_SIGNAL,
|
||||
};
|
||||
|
||||
@@ -58,11 +59,16 @@ enum {
|
||||
struct _IBusEnginePrivate {
|
||||
gchar *name;
|
||||
IBusConnection *connection;
|
||||
+
|
||||
+ IBusText *surrounding_text;
|
||||
+ guint surrounding_cursor_pos;
|
||||
};
|
||||
typedef struct _IBusEnginePrivate IBusEnginePrivate;
|
||||
|
||||
static guint engine_signals[LAST_SIGNAL] = { 0 };
|
||||
|
||||
+static IBusText *text_empty = NULL;
|
||||
+
|
||||
/* functions prototype */
|
||||
static void ibus_engine_destroy (IBusEngine *engine);
|
||||
static void ibus_engine_set_property (IBusEngine *engine,
|
||||
@@ -112,6 +118,10 @@ static void ibus_engine_property_show (IBusEngine *engine,
|
||||
const gchar *prop_name);
|
||||
static void ibus_engine_property_hide (IBusEngine *engine,
|
||||
const gchar *prop_name);
|
||||
+static void ibus_engine_set_surrounding_text
|
||||
+ (IBusEngine *engine,
|
||||
+ IBusText *text,
|
||||
+ guint cursor_pos);
|
||||
|
||||
|
||||
G_DEFINE_TYPE (IBusEngine, ibus_engine, IBUS_TYPE_SERVICE)
|
||||
@@ -142,6 +152,7 @@ ibus_engine_class_init (IBusEngineClass *klass)
|
||||
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
|
||||
|
||||
g_type_class_add_private (klass, sizeof (IBusEnginePrivate));
|
||||
+ text_empty = ibus_text_new_from_string ("");
|
||||
|
||||
gobject_class->set_property = (GObjectSetPropertyFunc) ibus_engine_set_property;
|
||||
gobject_class->get_property = (GObjectGetPropertyFunc) ibus_engine_get_property;
|
||||
@@ -166,6 +177,7 @@ ibus_engine_class_init (IBusEngineClass *klass)
|
||||
klass->property_hide = ibus_engine_property_hide;
|
||||
klass->set_cursor_location = ibus_engine_set_cursor_location;
|
||||
klass->set_capabilities = ibus_engine_set_capabilities;
|
||||
+ klass->set_surrounding_text = ibus_engine_set_surrounding_text;
|
||||
|
||||
|
||||
/* install properties */
|
||||
@@ -543,6 +555,27 @@ ibus_engine_class_init (IBusEngineClass *klass)
|
||||
1,
|
||||
G_TYPE_STRING);
|
||||
|
||||
+ /**
|
||||
+ * IBusEngine::set-surrounding-text:
|
||||
+ * @engine: An IBusEngine.
|
||||
+ *
|
||||
+ * Emitted when a surrounding text is set.
|
||||
+ * Implement the member function set_surrounding_text() in extended class to receive this signal.
|
||||
+ *
|
||||
+ * <note><para>Argument @user_data is ignored in this function.</para></note>
|
||||
+ */
|
||||
+ engine_signals[SET_SURROUNDING_TEXT] =
|
||||
+ g_signal_new (I_("set-surrounding-text"),
|
||||
+ G_TYPE_FROM_CLASS (gobject_class),
|
||||
+ G_SIGNAL_RUN_LAST,
|
||||
+ G_STRUCT_OFFSET (IBusEngineClass, set_surrounding_text),
|
||||
+ NULL, NULL,
|
||||
+ ibus_marshal_VOID__POINTER_UINT,
|
||||
+ G_TYPE_NONE,
|
||||
+ 2,
|
||||
+ G_TYPE_POINTER,
|
||||
+ G_TYPE_UINT);
|
||||
+
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -553,6 +586,10 @@ ibus_engine_init (IBusEngine *engine)
|
||||
|
||||
priv->name = NULL;
|
||||
priv->connection = NULL;
|
||||
+
|
||||
+ g_object_ref_sink (text_empty);
|
||||
+ priv->surrounding_text = text_empty;
|
||||
+ priv->surrounding_cursor_pos = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -568,6 +605,11 @@ ibus_engine_destroy (IBusEngine *engine)
|
||||
priv->connection = NULL;
|
||||
}
|
||||
|
||||
+ if (priv->surrounding_text) {
|
||||
+ g_object_unref (priv->surrounding_text);
|
||||
+ priv->surrounding_text = NULL;
|
||||
+ }
|
||||
+
|
||||
IBUS_OBJECT_CLASS(ibus_engine_parent_class)->destroy (IBUS_OBJECT (engine));
|
||||
}
|
||||
|
||||
@@ -878,6 +920,37 @@ ibus_engine_ibus_message (IBusEngine *engine,
|
||||
ibus_object_destroy ((IBusObject *) engine);
|
||||
return TRUE;
|
||||
}
|
||||
+ else if (g_strcmp0 (name, "SetSurroundingText") == 0) {
|
||||
+ IBusText *text;
|
||||
+ guint cursor_pos;
|
||||
+
|
||||
+ retval = ibus_message_get_args (message,
|
||||
+ &error,
|
||||
+ IBUS_TYPE_TEXT, &text,
|
||||
+ G_TYPE_UINT, &cursor_pos,
|
||||
+ G_TYPE_INVALID);
|
||||
+
|
||||
+ if (!retval) {
|
||||
+ reply = ibus_message_new_error_printf (message,
|
||||
+ DBUS_ERROR_INVALID_ARGS,
|
||||
+ "%s.%s: Can not match signature (u) of method",
|
||||
+ IBUS_INTERFACE_ENGINE, "SetSurroundingText");
|
||||
+ ibus_error_free (error);
|
||||
+ }
|
||||
+ else {
|
||||
+ if (priv->surrounding_text &&
|
||||
+ priv->surrounding_text != text_empty) {
|
||||
+ g_object_unref (priv->surrounding_text);
|
||||
+ }
|
||||
+
|
||||
+ priv->surrounding_text = (IBusText *) g_object_ref_sink (text ? text : text_empty);
|
||||
+ priv->surrounding_cursor_pos = cursor_pos;
|
||||
+ g_signal_emit (engine, engine_signals[SET_SURROUNDING_TEXT], 0,
|
||||
+ priv->surrounding_text,
|
||||
+ priv->surrounding_cursor_pos);
|
||||
+ reply = ibus_message_new_method_return (message);
|
||||
+ }
|
||||
+ }
|
||||
else {
|
||||
reply = ibus_message_new_error_printf (message,
|
||||
DBUS_ERROR_UNKNOWN_METHOD,
|
||||
@@ -1002,6 +1075,14 @@ ibus_engine_property_hide (IBusEngine *engine, const gchar *prop_name)
|
||||
}
|
||||
|
||||
static void
|
||||
+ibus_engine_set_surrounding_text (IBusEngine *engine,
|
||||
+ IBusText *text,
|
||||
+ guint cursor_pos)
|
||||
+{
|
||||
+ // g_debug ("set-surrounding-text ('%s', %d)", text->text, cursor_pos);
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
_send_signal (IBusEngine *engine,
|
||||
const gchar *name,
|
||||
GType first_arg_type,
|
||||
@@ -1209,6 +1290,18 @@ void ibus_engine_delete_surrounding_text (IBusEngine *engine,
|
||||
G_TYPE_INVALID);
|
||||
}
|
||||
|
||||
+void ibus_engine_get_surrounding_text (IBusEngine *engine,
|
||||
+ IBusText **text,
|
||||
+ guint *cursor_pos)
|
||||
+{
|
||||
+ IBusEnginePrivate *priv;
|
||||
+
|
||||
+ priv = IBUS_ENGINE_GET_PRIVATE (engine);
|
||||
+
|
||||
+ *text = priv->surrounding_text;
|
||||
+ *cursor_pos = priv->surrounding_cursor_pos;
|
||||
+}
|
||||
+
|
||||
void
|
||||
ibus_engine_register_properties (IBusEngine *engine,
|
||||
IBusPropList *prop_list)
|
||||
diff --git a/src/ibusengine.h b/src/ibusengine.h
|
||||
index 80e87c7..f39b523 100644
|
||||
--- a/src/ibusengine.h
|
||||
+++ b/src/ibusengine.h
|
||||
@@ -123,10 +123,14 @@ struct _IBusEngineClass {
|
||||
guint index,
|
||||
guint button,
|
||||
guint state);
|
||||
+ void (* set_surrounding_text)
|
||||
+ (IBusEngine *engine,
|
||||
+ IBusText *text,
|
||||
+ guint cursor_index);
|
||||
|
||||
/*< private >*/
|
||||
/* padding */
|
||||
- gpointer pdummy[8];
|
||||
+ gpointer pdummy[7];
|
||||
};
|
||||
|
||||
GType ibus_engine_get_type (void);
|
||||
@@ -366,6 +370,21 @@ void ibus_engine_delete_surrounding_text(IBusEngine *engine,
|
||||
guint nchars);
|
||||
|
||||
/**
|
||||
+ * ibus_engine_get_surrounding_text:
|
||||
+ * @engine: An IBusEngine.
|
||||
+ * @text: Location to store surrounding text.
|
||||
+ * @cursor_pos: Cursor position in characters in @text.
|
||||
+ *
|
||||
+ * Get surrounding text.
|
||||
+ *
|
||||
+ * @see_also #IBusEngine::set-surrounding-text
|
||||
+ */
|
||||
+void ibus_engine_get_surrounding_text(IBusEngine *engine,
|
||||
+ IBusText **text,
|
||||
+ guint *cursor_pos);
|
||||
+
|
||||
+
|
||||
+/**
|
||||
* ibus_engine_get_name:
|
||||
* @engine: An IBusEngine.
|
||||
* @returns: Name of IBusEngine.
|
||||
diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c
|
||||
index 7359de0..2610333 100644
|
||||
--- a/src/ibusinputcontext.c
|
||||
+++ b/src/ibusinputcontext.c
|
||||
@@ -913,6 +913,20 @@ ibus_input_context_property_hide (IBusInputContext *context,
|
||||
G_TYPE_INVALID);
|
||||
}
|
||||
|
||||
+void
|
||||
+ibus_input_context_set_surrounding_text (IBusInputContext *context,
|
||||
+ IBusText *text,
|
||||
+ guint32 cursor_pos)
|
||||
+{
|
||||
+ g_assert (IBUS_IS_INPUT_CONTEXT (context));
|
||||
+
|
||||
+ ibus_proxy_call ((IBusProxy *) context,
|
||||
+ "SetSurroundingText",
|
||||
+ IBUS_TYPE_TEXT, &text,
|
||||
+ G_TYPE_UINT, &cursor_pos,
|
||||
+ G_TYPE_INVALID);
|
||||
+}
|
||||
+
|
||||
gboolean
|
||||
ibus_input_context_is_enabled (IBusInputContext *context)
|
||||
{
|
||||
diff --git a/src/ibusinputcontext.h b/src/ibusinputcontext.h
|
||||
index 026460b..7f2538b 100644
|
||||
--- a/src/ibusinputcontext.h
|
||||
+++ b/src/ibusinputcontext.h
|
||||
@@ -35,6 +35,7 @@
|
||||
|
||||
#include "ibusproxy.h"
|
||||
#include "ibusenginedesc.h"
|
||||
+#include "ibustext.h"
|
||||
|
||||
/*
|
||||
* Type macros.
|
||||
@@ -266,6 +267,16 @@ IBusEngineDesc
|
||||
void ibus_input_context_set_engine (IBusInputContext *context,
|
||||
const gchar *name);
|
||||
|
||||
+/**
|
||||
+ * ibus_input_context_set_surrounding_text:
|
||||
+ * @context: An IBusInputContext.
|
||||
+ * @text: An IBusText surrounding the current cursor on the application.
|
||||
+ * @cursor_po: Current cursor position in characters in @text.
|
||||
+*/
|
||||
+void ibus_input_context_set_surrounding_text
|
||||
+ (IBusInputContext *context,
|
||||
+ IBusText *text,
|
||||
+ guint32 cursor_pos);
|
||||
|
||||
G_END_DECLS
|
||||
#endif
|
||||
diff --git a/src/ibusmarshalers.list b/src/ibusmarshalers.list
|
||||
index 4473dab..622c59a 100644
|
||||
--- a/src/ibusmarshalers.list
|
||||
+++ b/src/ibusmarshalers.list
|
||||
@@ -22,3 +22,4 @@ VOID:STRING,STRING,BOXED
|
||||
VOID:STRING,STRING,STRING
|
||||
VOID:UINT
|
||||
VOID:UINT,POINTER
|
||||
+VOID:POINTER,UINT
|
||||
--
|
||||
1.7.2.1
|
||||
|
@ -1,6 +1,6 @@
|
||||
From 509ffdfc4b27f977f255f348c84743b4be40f25f Mon Sep 17 00:00:00 2001
|
||||
From c51da8c58033550aa65613c1901205305e5bfcd8 Mon Sep 17 00:00:00 2001
|
||||
From: fujiwarat <takao.fujiwara1@gmail.com>
|
||||
Date: Mon, 30 Aug 2010 10:58:41 +0900
|
||||
Date: Thu, 9 Sep 2010 00:03:56 +0900
|
||||
Subject: [PATCH] Add XKB layouts
|
||||
|
||||
---
|
||||
@ -14,7 +14,7 @@ Subject: [PATCH] Add XKB layouts
|
||||
ibus/xkblayout.py.in | 91 ++++++
|
||||
ibus/xkbxml.py.in | 337 +++++++++++++++++++++
|
||||
setup/main.py | 228 ++++++++++++++-
|
||||
setup/setup.ui | 300 +++++++++++++++++++-
|
||||
setup/setup.ui | 297 +++++++++++++++++++-
|
||||
src/ibusfactory.c | 17 +-
|
||||
src/ibusfactory.h | 5 +-
|
||||
ui/gtk/panel.py | 30 ++
|
||||
@ -28,7 +28,7 @@ Subject: [PATCH] Add XKB layouts
|
||||
xkb/xkblib.h | 36 +++
|
||||
xkb/xkbxml.c | 695 ++++++++++++++++++++++++++++++++++++++++++++
|
||||
xkb/xkbxml.h | 188 ++++++++++++
|
||||
24 files changed, 2946 insertions(+), 7 deletions(-)
|
||||
24 files changed, 2943 insertions(+), 7 deletions(-)
|
||||
create mode 100644 ibus/xkblayout.py.in
|
||||
create mode 100644 ibus/xkbxml.py.in
|
||||
create mode 100644 xkb/Makefile.am
|
||||
@ -68,7 +68,7 @@ index 7895940..9f534a4 100644
|
||||
|
||||
ACLOCAL_AMFLAGS = -I m4
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index 3346d0c..15788bd 100644
|
||||
index 3346d0c..4611776 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -168,6 +168,57 @@ else
|
||||
@ -113,7 +113,7 @@ index 3346d0c..15788bd 100644
|
||||
+ [Set preload xkb layouts (default: us,fr,de,...)]),
|
||||
+ XKB_PRELOAD_LAYOUTS=$with_xkb_preload_layouts,
|
||||
+ [XKB_PRELOAD_LAYOUTS=""\
|
||||
+"us,us(chr),ad,al,am,ar,az,ba,bd,be,bg,br,bt,by,"\
|
||||
+"us,us(chr),ad,al,am,ara,az,ba,bd,be,bg,br,bt,by,"\
|
||||
+"de,dk,ca,ch,cn,cn(tib),cz,ee,epo,es,et,fi,fo,fr,"\
|
||||
+"gb,ge,ge(dsb),ge(ru),ge(os),gh,gh(akan),gh(ewe),gh(fula),gh(ga),gh(hausa),"\
|
||||
+"gn,gr,hu,hr,ie,ie(CloGaelach),il,"\
|
||||
@ -146,10 +146,10 @@ index 3346d0c..15788bd 100644
|
||||
Build gconf modules $enable_gconf
|
||||
Build memconf modules $enable_memconf
|
||||
diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in
|
||||
index 4695d0b..98a786e 100644
|
||||
index fae710a..4290a48 100644
|
||||
--- a/data/ibus.schemas.in
|
||||
+++ b/data/ibus.schemas.in
|
||||
@@ -167,6 +167,30 @@
|
||||
@@ -194,6 +194,30 @@
|
||||
</locale>
|
||||
</schema>
|
||||
<schema>
|
||||
@ -703,7 +703,7 @@ index 0000000..5880104
|
||||
+ test()
|
||||
+ test2()
|
||||
diff --git a/setup/main.py b/setup/main.py
|
||||
index d778ac3..1335215 100644
|
||||
index c6612d2..b8dd1cf 100644
|
||||
--- a/setup/main.py
|
||||
+++ b/setup/main.py
|
||||
@@ -183,10 +183,20 @@ class Setup(object):
|
||||
@ -729,7 +729,7 @@ index d778ac3..1335215 100644
|
||||
# use global ime setting
|
||||
self.__checkbutton_use_global_engine = self.__builder.get_object("checkbutton_use_global_engine")
|
||||
self.__checkbutton_use_global_engine.set_active(
|
||||
@@ -223,6 +233,145 @@ class Setup(object):
|
||||
@@ -233,6 +243,145 @@ class Setup(object):
|
||||
self.__combobox.connect("notify::active-engine", self.__combobox_notify_active_engine_cb)
|
||||
self.__treeview.connect("notify", self.__treeview_notify_cb)
|
||||
|
||||
@ -875,9 +875,9 @@ index d778ac3..1335215 100644
|
||||
def __combobox_notify_active_engine_cb(self, combobox, property):
|
||||
engine = self.__combobox.get_active_engine()
|
||||
button = self.__builder.get_object("button_engine_add")
|
||||
@@ -255,6 +404,80 @@ class Setup(object):
|
||||
about.run()
|
||||
about.destroy()
|
||||
@@ -282,6 +431,80 @@ class Setup(object):
|
||||
dlg.run()
|
||||
dlg.destroy()
|
||||
|
||||
+ def __button_config_layouts_cb(self, button):
|
||||
+ self.__dialog_config_layouts.run()
|
||||
@ -956,7 +956,7 @@ index d778ac3..1335215 100644
|
||||
def __init_bus(self):
|
||||
try:
|
||||
self.__bus = ibus.Bus()
|
||||
@@ -439,6 +662,7 @@ class Setup(object):
|
||||
@@ -470,6 +693,7 @@ class Setup(object):
|
||||
def __checkbutton_use_sys_layout_toggled_cb(self, button):
|
||||
value = self.__checkbutton_use_sys_layout.get_active()
|
||||
self.__config.set_value("general", "use_system_keyboard_layout", value)
|
||||
@ -965,7 +965,7 @@ index d778ac3..1335215 100644
|
||||
def __checkbutton_use_global_engine_toggled_cb(self, button):
|
||||
value = self.__checkbutton_use_global_engine.get_active()
|
||||
diff --git a/setup/setup.ui b/setup/setup.ui
|
||||
index 0e31a78..cb275a9 100644
|
||||
index 703b4d8..c73a613 100644
|
||||
--- a/setup/setup.ui
|
||||
+++ b/setup/setup.ui
|
||||
@@ -129,7 +129,6 @@
|
||||
@ -992,38 +992,7 @@ index 0e31a78..cb275a9 100644
|
||||
<property name="can_focus">True</property>
|
||||
<property name="receives_default">False</property>
|
||||
<property name="use_underline">True</property>
|
||||
@@ -550,6 +547,7 @@
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">5</property>
|
||||
<property name="layout_style">start</property>
|
||||
+ <property name="no_show_all">True</property>
|
||||
<child>
|
||||
<object class="GtkButton" id="button_engine_add">
|
||||
<property name="label">gtk-add</property>
|
||||
@@ -630,6 +628,22 @@
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
+ <child>
|
||||
+ <object class="GtkButton" id="button_config_layouts">
|
||||
+ <property name="label">Configure _Layouts</property>
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="sensitive">False</property>
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <property name="receives_default">True</property>
|
||||
+ <property name="tooltip_text" translatable="yes">Configure keyboard layouts</property>
|
||||
+ <property name="use_underline">True</property>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="expand">False</property>
|
||||
+ <property name="fill">False</property>
|
||||
+ <property name="position">5</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -729,6 +743,7 @@ You may use up/down buttons to change it.</i></small></property>
|
||||
@@ -745,6 +742,7 @@ You may use up/down buttons to change it.</i></small></property>
|
||||
<property name="visible">True</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">6</property>
|
||||
@ -1031,7 +1000,7 @@ index 0e31a78..cb275a9 100644
|
||||
<child>
|
||||
<object class="GtkCheckButton" id="checkbutton_use_sys_layout">
|
||||
<property name="label" translatable="yes">Use system keyboard layout</property>
|
||||
@@ -744,6 +759,43 @@ You may use up/down buttons to change it.</i></small></property>
|
||||
@@ -760,6 +758,57 @@ You may use up/down buttons to change it.</i></small></property>
|
||||
<property name="position">0</property>
|
||||
</packing>
|
||||
</child>
|
||||
@ -1042,7 +1011,7 @@ index 0e31a78..cb275a9 100644
|
||||
+ <child>
|
||||
+ <object class="GtkLabel" id="label18">
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="label" translatable="yes">System Layout:</property>
|
||||
+ <property name="label" translatable="yes">Input Method Layout:</property>
|
||||
+ <property name="use_markup">True</property>
|
||||
+ <property name="justify">center</property>
|
||||
+ </object>
|
||||
@ -1071,11 +1040,25 @@ index 0e31a78..cb275a9 100644
|
||||
+ <property name="fill">False</property>
|
||||
+ <property name="position">1</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
+ <child>
|
||||
+ <object class="GtkButton" id="button_config_layouts">
|
||||
+ <property name="label">Add or remove layouts in 'Select an input method' list</property>
|
||||
+ <property name="visible">True</property>
|
||||
+ <property name="can_focus">True</property>
|
||||
+ <property name="receives_default">False</property>
|
||||
+ <property name="tooltip_text" translatable="yes">Add or remove keyboard layouts in all input method engnines</property>
|
||||
+ </object>
|
||||
+ <packing>
|
||||
+ <property name="expand">False</property>
|
||||
+ <property name="fill">False</property>
|
||||
+ <property name="position">2</property>
|
||||
+ </packing>
|
||||
+ </child>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
@@ -942,4 +994,246 @@ Homepage: http://code.google.com/p/ibus
|
||||
@@ -958,4 +1007,246 @@ Homepage: http://code.google.com/p/ibus
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
|
27
ibus-621795-engineproxy-segv.patch
Normal file
27
ibus-621795-engineproxy-segv.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 85565b7a146e5ccbd484273b647b6195b6c08b03 Mon Sep 17 00:00:00 2001
|
||||
From: fujiwarat <takao.fujiwara1@gmail.com>
|
||||
Date: Thu, 2 Sep 2010 12:58:42 +0900
|
||||
Subject: [PATCH] Fix segv in bus_engine_proxy_process_key_event_reply_cb
|
||||
|
||||
---
|
||||
bus/engineproxy.c | 4 +++-
|
||||
1 files changed, 3 insertions(+), 1 deletions(-)
|
||||
|
||||
diff --git a/bus/engineproxy.c b/bus/engineproxy.c
|
||||
index adda91c..64dda4f 100644
|
||||
--- a/bus/engineproxy.c
|
||||
+++ b/bus/engineproxy.c
|
||||
@@ -564,7 +564,9 @@ bus_engine_proxy_process_key_event_reply_cb (IBusPendingCall *pending,
|
||||
/* reply timeout */
|
||||
IBusObject *connection;
|
||||
connection = (IBusObject *) ibus_proxy_get_connection ((IBusProxy *)call_data->engine);
|
||||
- ibus_object_destroy (connection);
|
||||
+ if (connection) {
|
||||
+ ibus_object_destroy (connection);
|
||||
+ }
|
||||
}
|
||||
g_warning ("%s: %s", error->name, error->message);
|
||||
ibus_error_free (error);
|
||||
--
|
||||
1.7.2.1
|
||||
|
27
ibus-626652-leak.patch
Normal file
27
ibus-626652-leak.patch
Normal file
@ -0,0 +1,27 @@
|
||||
From 888189eba783ac014e7c367004a70dad6f7b8ac0 Mon Sep 17 00:00:00 2001
|
||||
From: Peng Huang <shawn.p.huang@gmail.com>
|
||||
Date: Mon, 6 Sep 2010 17:17:24 +0800
|
||||
Subject: [PATCH] Fix memory leak in ibus_input_context_process_key_event by Fujiwarat
|
||||
|
||||
---
|
||||
src/ibusinputcontext.c | 4 ++++
|
||||
1 files changed, 4 insertions(+), 0 deletions(-)
|
||||
|
||||
diff --git a/src/ibusinputcontext.c b/src/ibusinputcontext.c
|
||||
index 6755727..7359de0 100644
|
||||
--- a/src/ibusinputcontext.c
|
||||
+++ b/src/ibusinputcontext.c
|
||||
@@ -775,6 +775,10 @@ _process_key_event_reply_cb (IBusPendingCall *pending,
|
||||
call_data->keycode,
|
||||
call_data->state | IBUS_FORWARD_MASK);
|
||||
}
|
||||
+
|
||||
+ if (reply_message != NULL) {
|
||||
+ dbus_message_unref (reply_message);
|
||||
+ }
|
||||
}
|
||||
|
||||
static void
|
||||
--
|
||||
1.7.2.1
|
||||
|
28
ibus.spec
28
ibus.spec
@ -11,7 +11,7 @@
|
||||
|
||||
Name: ibus
|
||||
Version: 1.3.7
|
||||
Release: 3%{?dist}
|
||||
Release: 4%{?dist}
|
||||
Summary: Intelligent Input Bus for Linux OS
|
||||
License: LGPLv2+
|
||||
Group: System Environment/Libraries
|
||||
@ -19,7 +19,12 @@ URL: http://code.google.com/p/ibus/
|
||||
Source0: http://ibus.googlecode.com/files/%{name}-%{version}.tar.gz
|
||||
Source1: xinput-ibus
|
||||
# Patch0: ibus-HEAD.patch
|
||||
Patch1: ibus-541492-xkb.patch
|
||||
Patch1: ibus-621795-engineproxy-segv.patch
|
||||
Patch2: ibus-626652-leak.patch
|
||||
# Patch3: ibus-xx-va_list.patch
|
||||
# Patch4: ibus-530711-preload-sys.patch
|
||||
Patch5: ibus-541492-xkb.patch
|
||||
Patch6: ibus-435880-surrounding-text.patch
|
||||
|
||||
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
|
||||
@ -124,9 +129,14 @@ The ibus-devel-docs package contains developer documentation for ibus
|
||||
%prep
|
||||
%setup -q
|
||||
# %patch0 -p1
|
||||
%patch1 -p1 -b .segv
|
||||
%patch2 -p1 -b .leak
|
||||
# %patch3 -p1 -b .valist
|
||||
# %patch4 -p1 -b .preload-sys
|
||||
%if %have_libxkbfile
|
||||
%patch1 -p1 -b .xkb
|
||||
%patch5 -p1 -b .xkb
|
||||
%endif
|
||||
%patch6 -p1 -b .surrounding
|
||||
|
||||
%build
|
||||
%if %have_libxkbfile
|
||||
@ -269,9 +279,15 @@ fi
|
||||
%{_datadir}/gtk-doc/html/*
|
||||
|
||||
%changelog
|
||||
* Mon Aug 30 2010 Takao Fujiwara <tfujiwar@redhat.com> - 1.3.7-3
|
||||
- Fix #627107 and update ibus-541492-xkb.patch
|
||||
- Fix #628161 and update ibus-541492-xkb.patch
|
||||
* Tue Sep 14 2010 Takao Fujiwara <tfujiwar@redhat.com> - 1.3.7-4
|
||||
- Added ibus-621795-engineproxy-segv.patch
|
||||
Fixes crash in ibus_object_destroy
|
||||
- Added ibus-626652-leak.patch
|
||||
Fixes Bug 626652 - ibus memory leak with ibus_input_context_process_key_event
|
||||
- Added ibus-541492-xkb.patch
|
||||
Fixes Bug 541492 - ibus needs to support some xkb layout switching
|
||||
- Added ibus-435880-surrounding-text.patch
|
||||
Fixes Bug 435880 - ibus-gtk requires surrounding-text support
|
||||
|
||||
* Mon Aug 23 2010 Takao Fujiwara <tfujiwar@redhat.com> - 1.3.7-1
|
||||
- Update to 1.3.7
|
||||
|
Loading…
Reference in New Issue
Block a user