Remove enable status of input context and hotkey logic in ibus-daemon
This commit is contained in:
Родитель
60587bf804
Коммит
53d33ec4e6
|
@ -22,4 +22,4 @@ which gnome-autogen.sh || {
|
|||
touch $srcdir/ChangeLog
|
||||
}
|
||||
|
||||
ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4" REQUIRED_AUTOMAKE_VERSION=1.10 CFLAGS="-Wall -Werror $CFLAGS" . gnome-autogen.sh
|
||||
ACLOCAL_FLAGS="$ACLOCAL_FLAGS -I m4" REQUIRED_AUTOMAKE_VERSION=1.10 CFLAGS="-Wall $CFLAGS" . gnome-autogen.sh
|
||||
|
|
944
bus/ibusimpl.c
944
bus/ibusimpl.c
Разница между файлами не показана из-за своего большого размера
Загрузить разницу
|
@ -50,8 +50,6 @@
|
|||
|
||||
#define BUS_DEFAULT_IBUS \
|
||||
(bus_ibus_impl_get_default ())
|
||||
#define BUS_DEFAULT_HOTKEY_PROFILE \
|
||||
(bus_ibus_impl_get_hotkey_profile (BUS_DEFAULT_IBUS))
|
||||
#define BUS_DEFAULT_KEYMAP \
|
||||
(bus_ibus_impl_get_keymap (BUS_DEFAULT_IBUS))
|
||||
#define BUS_DEFAULT_REGISTRY \
|
||||
|
@ -90,8 +88,6 @@ gboolean bus_ibus_impl_filter_keyboard_shortcuts
|
|||
/* accessors */
|
||||
BusFactoryProxy *bus_ibus_impl_lookup_factory (BusIBusImpl *ibus,
|
||||
const gchar *path);
|
||||
IBusHotkeyProfile
|
||||
*bus_ibus_impl_get_hotkey_profile (BusIBusImpl *ibus);
|
||||
IBusKeymap *bus_ibus_impl_get_keymap (BusIBusImpl *ibus);
|
||||
BusRegistry *bus_ibus_impl_get_registry (BusIBusImpl *ibus);
|
||||
gboolean bus_ibus_impl_is_use_sys_layout (BusIBusImpl *ibus);
|
||||
|
|
|
@ -53,7 +53,6 @@ struct _BusInputContext {
|
|||
gchar *client;
|
||||
|
||||
gboolean has_focus;
|
||||
gboolean enabled;
|
||||
|
||||
/* client capabilities */
|
||||
guint capabilities;
|
||||
|
@ -96,6 +95,7 @@ struct _BusInputContextClass {
|
|||
IBusServiceClass parent;
|
||||
|
||||
/* class members */
|
||||
IBusEngineDesc *default_engine_desc;
|
||||
};
|
||||
|
||||
enum {
|
||||
|
@ -118,8 +118,6 @@ enum {
|
|||
CURSOR_DOWN_LOOKUP_TABLE,
|
||||
REGISTER_PROPERTIES,
|
||||
UPDATE_PROPERTY,
|
||||
ENABLED,
|
||||
DISABLED,
|
||||
ENGINE_CHANGED,
|
||||
REQUEST_ENGINE,
|
||||
LAST_SIGNAL,
|
||||
|
@ -163,12 +161,6 @@ static gboolean bus_input_context_service_set_property
|
|||
GVariant *value,
|
||||
GError **error);
|
||||
*/
|
||||
static gboolean bus_input_context_filter_keyboard_shortcuts
|
||||
(BusInputContext *context,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
guint modifiers);
|
||||
|
||||
static void bus_input_context_unset_engine (BusInputContext *context);
|
||||
static void bus_input_context_commit_text (BusInputContext *context,
|
||||
IBusText *text);
|
||||
|
@ -247,11 +239,6 @@ static const gchar introspection_xml[] =
|
|||
" <method name='FocusIn' />"
|
||||
" <method name='FocusOut' />"
|
||||
" <method name='Reset' />"
|
||||
" <method name='Enable' />"
|
||||
" <method name='Disable' />"
|
||||
" <method name='IsEnabled'>"
|
||||
" <arg direction='out' type='b' name='enable' />"
|
||||
" </method>"
|
||||
" <method name='SetCapabilities'>"
|
||||
" <arg direction='in' type='u' name='caps' />"
|
||||
" </method>"
|
||||
|
@ -275,8 +262,6 @@ static const gchar introspection_xml[] =
|
|||
" <signal name='CommitText'>"
|
||||
" <arg type='v' name='text' />"
|
||||
" </signal>"
|
||||
" <signal name='Enabled'/>"
|
||||
" <signal name='Disabled'/>"
|
||||
" <signal name='ForwardKeyEvent'>"
|
||||
" <arg type='u' name='keyval' />"
|
||||
" <arg type='u' name='keycode' />"
|
||||
|
@ -337,6 +322,16 @@ bus_input_context_class_init (BusInputContextClass *class)
|
|||
{
|
||||
IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (class);
|
||||
|
||||
class->default_engine_desc = ibus_engine_desc_new ("dummy",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"",
|
||||
"ibus-engine",
|
||||
"");
|
||||
g_object_ref_sink (class->default_engine_desc);
|
||||
|
||||
ibus_object_class->destroy = (IBusObjectDestroyFunc) bus_input_context_destroy;
|
||||
|
||||
/* override the parent class's implementation. */
|
||||
|
@ -543,26 +538,6 @@ bus_input_context_class_init (BusInputContextClass *class)
|
|||
1,
|
||||
IBUS_TYPE_PROPERTY);
|
||||
|
||||
context_signals[ENABLED] =
|
||||
g_signal_new (I_("enabled"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
bus_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
context_signals[DISABLED] =
|
||||
g_signal_new (I_("disabled"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
G_SIGNAL_RUN_LAST,
|
||||
0,
|
||||
NULL, NULL,
|
||||
bus_marshal_VOID__VOID,
|
||||
G_TYPE_NONE,
|
||||
0);
|
||||
|
||||
context_signals[ENGINE_CHANGED] =
|
||||
g_signal_new (I_("engine-changed"),
|
||||
G_TYPE_FROM_CLASS (class),
|
||||
|
@ -732,17 +707,8 @@ _ic_process_key_event (BusInputContext *context,
|
|||
}
|
||||
}
|
||||
|
||||
if (G_LIKELY (context->has_focus)) {
|
||||
gboolean retval = bus_input_context_filter_keyboard_shortcuts (context, keyval, keycode, modifiers);
|
||||
/* If it is keyboard shortcut, reply TRUE to client */
|
||||
if (G_UNLIKELY (retval)) {
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", TRUE));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* ignore key events, if it is a fake input context */
|
||||
if (context->has_focus && context->enabled && context->engine && context->fake == FALSE) {
|
||||
if (context->has_focus && context->engine && context->fake == FALSE) {
|
||||
bus_engine_proxy_process_key_event (context->engine,
|
||||
keyval,
|
||||
keycode,
|
||||
|
@ -770,7 +736,7 @@ _ic_set_cursor_location (BusInputContext *context,
|
|||
g_variant_get (parameters, "(iiii)",
|
||||
&context->x, &context->y, &context->w, &context->h);
|
||||
|
||||
if (context->has_focus && context->enabled && context->engine) {
|
||||
if (context->has_focus && context->engine) {
|
||||
bus_engine_proxy_set_cursor_location (context->engine,
|
||||
context->x, context->y, context->w, context->h);
|
||||
}
|
||||
|
@ -792,7 +758,7 @@ _ic_process_hand_writing_event (BusInputContext *context,
|
|||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
/* do nothing if it is a fake input context */
|
||||
if (context->has_focus && context->enabled &&
|
||||
if (context->has_focus &&
|
||||
context->engine && context->fake == FALSE) {
|
||||
bus_engine_proxy_process_hand_writing_event (context->engine, parameters);
|
||||
}
|
||||
|
@ -808,7 +774,7 @@ _ic_cancel_hand_writing (BusInputContext *context,
|
|||
g_variant_get (parameters, "(u)", &n_strokes);
|
||||
|
||||
/* do nothing if it is a fake input context */
|
||||
if (context->has_focus && context->enabled &&
|
||||
if (context->has_focus &&
|
||||
context->engine && context->fake == FALSE) {
|
||||
bus_engine_proxy_cancel_hand_writing (context->engine, n_strokes);
|
||||
}
|
||||
|
@ -865,7 +831,7 @@ _ic_reset (BusInputContext *context,
|
|||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
if (context->enabled && context->engine) {
|
||||
if (context->engine) {
|
||||
bus_engine_proxy_reset (context->engine);
|
||||
}
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
|
@ -903,7 +869,7 @@ _ic_property_activate (BusInputContext *context,
|
|||
guint prop_state = 0;
|
||||
g_variant_get (parameters, "(&su)", &prop_name, &prop_state);
|
||||
|
||||
if (context->enabled && context->engine) {
|
||||
if (context->engine) {
|
||||
bus_engine_proxy_property_activate (context->engine, prop_name, prop_state);
|
||||
}
|
||||
|
||||
|
@ -921,47 +887,6 @@ _ic_property_activate (BusInputContext *context,
|
|||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* _ic_enable:
|
||||
*
|
||||
* Implement the "Enable" method call of the org.freedesktop.IBus.InputContext interface.
|
||||
*/
|
||||
static void
|
||||
_ic_enable (BusInputContext *context,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
bus_input_context_enable (context);
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* _ic_disable:
|
||||
*
|
||||
* Implement the "Disable" method call of the org.freedesktop.IBus.InputContext interface.
|
||||
*/
|
||||
static void
|
||||
_ic_disable (BusInputContext *context,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
bus_input_context_disable (context);
|
||||
g_dbus_method_invocation_return_value (invocation, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* _ic_is_enabled:
|
||||
*
|
||||
* Implement the "IsEnabled" method call of the org.freedesktop.IBus.InputContext interface.
|
||||
*/
|
||||
static void
|
||||
_ic_is_enabled (BusInputContext *context,
|
||||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
g_dbus_method_invocation_return_value (invocation, g_variant_new ("(b)", context->enabled));
|
||||
}
|
||||
|
||||
static void
|
||||
_ic_set_engine_done (BusInputContext *context,
|
||||
GAsyncResult *res,
|
||||
|
@ -1033,18 +958,13 @@ _ic_get_engine (BusInputContext *context,
|
|||
GVariant *parameters,
|
||||
GDBusMethodInvocation *invocation)
|
||||
{
|
||||
if (context->engine) {
|
||||
IBusEngineDesc *desc = bus_engine_proxy_get_desc (context->engine);
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(v)", ibus_serializable_serialize ((IBusSerializable *)desc)));
|
||||
}
|
||||
else {
|
||||
g_dbus_method_invocation_return_error (
|
||||
invocation,
|
||||
IBUS_ERROR,
|
||||
IBUS_ERROR_NO_ENGINE,
|
||||
"Input context does not have engine.");
|
||||
}
|
||||
IBusEngineDesc *desc = context->engine ?
|
||||
bus_engine_proxy_get_desc (context->engine) :
|
||||
BUS_INPUT_CONTEXT_GET_CLASS (context)->default_engine_desc;
|
||||
|
||||
|
||||
g_dbus_method_invocation_return_value (invocation,
|
||||
g_variant_new ("(v)", ibus_serializable_serialize ((IBusSerializable *)desc)));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1071,7 +991,7 @@ _ic_set_surrounding_text (BusInputContext *context,
|
|||
g_variant_unref (variant);
|
||||
|
||||
if ((context->capabilities & IBUS_CAP_SURROUNDING_TEXT) &&
|
||||
context->has_focus && context->enabled && context->engine) {
|
||||
context->has_focus && context->engine) {
|
||||
bus_engine_proxy_set_surrounding_text (context->engine,
|
||||
text,
|
||||
cursor_pos,
|
||||
|
@ -1121,9 +1041,6 @@ bus_input_context_service_method_call (IBusService *service,
|
|||
{ "Reset", _ic_reset },
|
||||
{ "SetCapabilities", _ic_set_capabilities },
|
||||
{ "PropertyActivate", _ic_property_activate },
|
||||
{ "Enable", _ic_enable },
|
||||
{ "Disable", _ic_disable },
|
||||
{ "IsEnabled", _ic_is_enabled },
|
||||
{ "SetEngine", _ic_set_engine },
|
||||
{ "GetEngine", _ic_get_engine },
|
||||
{ "SetSurroundingText", _ic_set_surrounding_text},
|
||||
|
@ -1163,7 +1080,7 @@ bus_input_context_focus_in (BusInputContext *context)
|
|||
context->prev_keyval = IBUS_VoidSymbol;
|
||||
context->prev_modifiers = 0;
|
||||
|
||||
if (context->engine == NULL && context->enabled) {
|
||||
if (context->engine == NULL) {
|
||||
/* request an engine, e.g. a global engine if the feature is enabled. */
|
||||
IBusEngineDesc *desc = NULL;
|
||||
g_signal_emit (context,
|
||||
|
@ -1181,7 +1098,7 @@ bus_input_context_focus_in (BusInputContext *context)
|
|||
}
|
||||
}
|
||||
|
||||
if (context->engine && context->enabled) {
|
||||
if (context->engine) {
|
||||
bus_engine_proxy_focus_in (context->engine);
|
||||
bus_engine_proxy_enable (context->engine);
|
||||
bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
|
||||
|
@ -1190,7 +1107,7 @@ bus_input_context_focus_in (BusInputContext *context)
|
|||
|
||||
if (context->capabilities & IBUS_CAP_FOCUS) {
|
||||
g_signal_emit (context, context_signals[FOCUS_IN], 0);
|
||||
if (context->engine && context->enabled) {
|
||||
if (context->engine) {
|
||||
/* if necessary, emit glib signals to the context object to update panel status. see the comment for PREEDIT_CONDITION
|
||||
* for details. */
|
||||
if (context->preedit_visible && !PREEDIT_CONDITION) {
|
||||
|
@ -1252,7 +1169,7 @@ bus_input_context_focus_out (BusInputContext *context)
|
|||
bus_input_context_update_lookup_table (context, lookup_table_empty, FALSE);
|
||||
bus_input_context_register_properties (context, props_empty);
|
||||
|
||||
if (context->engine && context->enabled) {
|
||||
if (context->engine) {
|
||||
bus_engine_proxy_focus_out (context->engine);
|
||||
}
|
||||
|
||||
|
@ -1269,7 +1186,7 @@ bus_input_context_focus_out (BusInputContext *context)
|
|||
{ \
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context)); \
|
||||
\
|
||||
if (context->has_focus && context->enabled && context->engine) { \
|
||||
if (context->has_focus && context->engine) { \
|
||||
bus_engine_proxy_##name (context->engine); \
|
||||
} \
|
||||
}
|
||||
|
@ -1289,7 +1206,7 @@ bus_input_context_candidate_clicked (BusInputContext *context,
|
|||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (context->enabled && context->engine) {
|
||||
if (context->engine) {
|
||||
bus_engine_proxy_candidate_clicked (context->engine,
|
||||
index,
|
||||
button,
|
||||
|
@ -1304,7 +1221,7 @@ bus_input_context_property_activate (BusInputContext *context,
|
|||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (context->enabled && context->engine) {
|
||||
if (context->engine) {
|
||||
bus_engine_proxy_property_activate (context->engine, prop_name, prop_state);
|
||||
}
|
||||
}
|
||||
|
@ -1315,9 +1232,6 @@ bus_input_context_commit_text (BusInputContext *context,
|
|||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
if (text == text_empty || text == NULL)
|
||||
return;
|
||||
|
||||
|
@ -1829,9 +1743,6 @@ _engine_forward_key_event_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
bus_input_context_emit_signal (context,
|
||||
"ForwardKeyEvent",
|
||||
g_variant_new ("(uuu)", keyval, keycode, state),
|
||||
|
@ -1854,9 +1765,6 @@ _engine_delete_surrounding_text_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
bus_input_context_emit_signal (context,
|
||||
"DeleteSurroundingText",
|
||||
g_variant_new ("(iu)", offset_from_cursor, nchars),
|
||||
|
@ -1877,9 +1785,6 @@ _engine_require_surrounding_text_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
bus_input_context_emit_signal (context,
|
||||
"RequireSurroundingText",
|
||||
NULL,
|
||||
|
@ -1905,9 +1810,6 @@ _engine_update_preedit_text_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
bus_input_context_update_preedit_text (context, text, cursor_pos, visible, mode);
|
||||
}
|
||||
|
||||
|
@ -1928,9 +1830,6 @@ _engine_update_auxiliary_text_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
bus_input_context_update_auxiliary_text (context, text, visible);
|
||||
}
|
||||
|
||||
|
@ -1951,9 +1850,6 @@ _engine_update_lookup_table_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
bus_input_context_update_lookup_table (context, table, visible);
|
||||
}
|
||||
|
||||
|
@ -1973,9 +1869,6 @@ _engine_register_properties_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
bus_input_context_register_properties (context, props);
|
||||
}
|
||||
|
||||
|
@ -1995,9 +1888,6 @@ _engine_update_property_cb (BusEngineProxy *engine,
|
|||
|
||||
g_assert (context->engine == engine);
|
||||
|
||||
if (!context->enabled)
|
||||
return;
|
||||
|
||||
bus_input_context_update_property (context, prop);
|
||||
}
|
||||
|
||||
|
@ -2011,9 +1901,6 @@ _engine_update_property_cb (BusEngineProxy *engine,
|
|||
\
|
||||
g_assert (context->engine == engine); \
|
||||
\
|
||||
if (!context->enabled) \
|
||||
return; \
|
||||
\
|
||||
bus_input_context_##name (context); \
|
||||
}
|
||||
|
||||
|
@ -2077,7 +1964,6 @@ bus_input_context_enable (BusInputContext *context)
|
|||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
if (!context->has_focus) {
|
||||
context->enabled = TRUE;
|
||||
/* FIXME Do we need to emit "enabled" signal? */
|
||||
return;
|
||||
}
|
||||
|
@ -2101,20 +1987,10 @@ bus_input_context_enable (BusInputContext *context)
|
|||
if (context->engine == NULL)
|
||||
return;
|
||||
|
||||
context->enabled = TRUE;
|
||||
|
||||
bus_engine_proxy_focus_in (context->engine);
|
||||
bus_engine_proxy_enable (context->engine);
|
||||
bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
|
||||
bus_engine_proxy_set_cursor_location (context->engine, context->x, context->y, context->w, context->h);
|
||||
|
||||
bus_input_context_emit_signal (context,
|
||||
"Enabled",
|
||||
NULL,
|
||||
NULL);
|
||||
g_signal_emit (context,
|
||||
context_signals[ENABLED],
|
||||
0);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -2131,24 +2007,6 @@ bus_input_context_disable (BusInputContext *context)
|
|||
bus_engine_proxy_focus_out (context->engine);
|
||||
bus_engine_proxy_disable (context->engine);
|
||||
}
|
||||
|
||||
bus_input_context_emit_signal (context,
|
||||
"Disabled",
|
||||
NULL,
|
||||
NULL);
|
||||
g_signal_emit (context,
|
||||
context_signals[DISABLED],
|
||||
0);
|
||||
|
||||
context->enabled = FALSE;
|
||||
}
|
||||
|
||||
gboolean
|
||||
bus_input_context_is_enabled (BusInputContext *context)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
return context->enabled;
|
||||
}
|
||||
|
||||
/* A list of signals (and their handler functions) that could be emit by the engine proxy object. */
|
||||
|
@ -2228,7 +2086,7 @@ bus_input_context_set_engine (BusInputContext *context,
|
|||
engine_signals[i].callback,
|
||||
context);
|
||||
}
|
||||
if (context->has_focus && context->enabled) {
|
||||
if (context->has_focus) {
|
||||
bus_engine_proxy_focus_in (context->engine);
|
||||
bus_engine_proxy_enable (context->engine);
|
||||
bus_engine_proxy_set_capabilities (context->engine, context->capabilities);
|
||||
|
@ -2461,44 +2319,6 @@ bus_input_context_get_engine_desc (BusInputContext *context)
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
bus_input_context_filter_keyboard_shortcuts (BusInputContext *context,
|
||||
guint keyval,
|
||||
guint keycode,
|
||||
guint modifiers)
|
||||
{
|
||||
g_assert (BUS_IS_INPUT_CONTEXT (context));
|
||||
|
||||
gboolean retval = FALSE;
|
||||
|
||||
if (context->filter_release){
|
||||
if (modifiers & IBUS_RELEASE_MASK) {
|
||||
/* filter release key event */
|
||||
return TRUE;
|
||||
}
|
||||
else {
|
||||
/* stop filter release key event */
|
||||
context->filter_release = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
retval = bus_ibus_impl_filter_keyboard_shortcuts (BUS_DEFAULT_IBUS,
|
||||
context,
|
||||
keyval,
|
||||
modifiers,
|
||||
context->prev_keyval,
|
||||
context->prev_modifiers);
|
||||
context->prev_keyval = keyval;
|
||||
context->prev_modifiers = modifiers;
|
||||
|
||||
if (retval == TRUE) {
|
||||
/* begin filter release key event */
|
||||
context->filter_release = TRUE;
|
||||
}
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
guint
|
||||
bus_input_context_get_capabilities (BusInputContext *context)
|
||||
{
|
||||
|
|
|
@ -91,12 +91,6 @@ void bus_input_context_enable (BusInputContext *con
|
|||
*/
|
||||
void bus_input_context_disable (BusInputContext *context);
|
||||
|
||||
/**
|
||||
* bus_input_context_is_enabled:
|
||||
* @returns: context->enabled.
|
||||
*/
|
||||
gboolean bus_input_context_is_enabled (BusInputContext *context);
|
||||
|
||||
/**
|
||||
* bus_input_context_page_up:
|
||||
*
|
||||
|
|
|
@ -625,8 +625,6 @@ static const struct {
|
|||
{ "register-properties", G_CALLBACK (_context_register_properties_cb) },
|
||||
{ "update-property", G_CALLBACK (_context_update_property_cb) },
|
||||
|
||||
{ "enabled", G_CALLBACK (_context_state_changed_cb) },
|
||||
{ "disabled", G_CALLBACK (_context_state_changed_cb) },
|
||||
{ "engine-changed", G_CALLBACK (_context_state_changed_cb) },
|
||||
|
||||
{ "destroy", G_CALLBACK (_context_destroy_cb) },
|
||||
|
|
|
@ -47,8 +47,6 @@ struct _IBusIMContext {
|
|||
GtkIMContext *slave;
|
||||
GdkWindow *client_window;
|
||||
|
||||
/* enabled */
|
||||
gboolean enable;
|
||||
IBusInputContext *ibuscontext;
|
||||
|
||||
/* preedit status */
|
||||
|
@ -271,7 +269,7 @@ _process_key_event_done (GObject *object,
|
|||
static void
|
||||
_request_surrounding_text (IBusIMContext *context)
|
||||
{
|
||||
if (context && context->enable &&
|
||||
if (context &&
|
||||
(context->caps & IBUS_CAP_SURROUNDING_TEXT) != 0 &&
|
||||
context->ibuscontext != NULL &&
|
||||
ibus_input_context_needs_surrounding_text (context->ibuscontext)) {
|
||||
|
@ -566,9 +564,6 @@ ibus_im_context_init (GObject *obj)
|
|||
|
||||
ibusimcontext->client_window = NULL;
|
||||
|
||||
// Init ibus status
|
||||
ibusimcontext->enable = FALSE;
|
||||
|
||||
// Init preedit status
|
||||
ibusimcontext->preedit_string = NULL;
|
||||
ibusimcontext->preedit_attrs = NULL;
|
||||
|
@ -840,36 +835,31 @@ ibus_im_context_get_preedit_string (GtkIMContext *context,
|
|||
|
||||
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
||||
|
||||
if (ibusimcontext->enable) {
|
||||
if (ibusimcontext->preedit_visible) {
|
||||
if (str) {
|
||||
*str = g_strdup (ibusimcontext->preedit_string ? ibusimcontext->preedit_string: "");
|
||||
}
|
||||
|
||||
if (attrs) {
|
||||
*attrs = ibusimcontext->preedit_attrs ?
|
||||
pango_attr_list_ref (ibusimcontext->preedit_attrs):
|
||||
pango_attr_list_new ();
|
||||
}
|
||||
|
||||
if (cursor_pos) {
|
||||
*cursor_pos = ibusimcontext->preedit_cursor_pos;
|
||||
}
|
||||
if (ibusimcontext->preedit_visible) {
|
||||
if (str) {
|
||||
*str = g_strdup (ibusimcontext->preedit_string ? ibusimcontext->preedit_string: "");
|
||||
}
|
||||
else {
|
||||
if (str) {
|
||||
*str = g_strdup ("");
|
||||
}
|
||||
if (attrs) {
|
||||
*attrs = pango_attr_list_new ();
|
||||
}
|
||||
if (cursor_pos) {
|
||||
*cursor_pos = 0;
|
||||
}
|
||||
|
||||
if (attrs) {
|
||||
*attrs = ibusimcontext->preedit_attrs ?
|
||||
pango_attr_list_ref (ibusimcontext->preedit_attrs):
|
||||
pango_attr_list_new ();
|
||||
}
|
||||
|
||||
if (cursor_pos) {
|
||||
*cursor_pos = ibusimcontext->preedit_cursor_pos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
gtk_im_context_get_preedit_string (ibusimcontext->slave, str, attrs, cursor_pos);
|
||||
if (str) {
|
||||
*str = g_strdup ("");
|
||||
}
|
||||
if (attrs) {
|
||||
*attrs = pango_attr_list_new ();
|
||||
}
|
||||
if (cursor_pos) {
|
||||
*cursor_pos = 0;
|
||||
}
|
||||
}
|
||||
IDEBUG ("str=%s", *str);
|
||||
}
|
||||
|
@ -1040,7 +1030,7 @@ ibus_im_context_set_surrounding (GtkIMContext *context,
|
|||
|
||||
IBusIMContext *ibusimcontext = IBUS_IM_CONTEXT (context);
|
||||
|
||||
if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
if (ibusimcontext->ibuscontext) {
|
||||
IBusText *ibustext;
|
||||
guint cursor_pos;
|
||||
guint utf8_len;
|
||||
|
@ -1399,36 +1389,6 @@ _ibus_context_hide_preedit_text_cb (IBusInputContext *ibuscontext,
|
|||
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_enabled_cb (IBusInputContext *ibuscontext,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG ("%s", __FUNCTION__);
|
||||
|
||||
ibusimcontext->enable = TRUE;
|
||||
|
||||
/* retrieve the initial surrounding-text (regardless of whether
|
||||
* the current IBus engine needs surrounding-text) */
|
||||
_request_surrounding_text (ibusimcontext);
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_disabled_cb (IBusInputContext *ibuscontext,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
IDEBUG ("%s", __FUNCTION__);
|
||||
ibusimcontext->enable = FALSE;
|
||||
|
||||
/* clear preedit */
|
||||
ibusimcontext->preedit_visible = FALSE;
|
||||
ibusimcontext->preedit_cursor_pos = 0;
|
||||
g_free (ibusimcontext->preedit_string);
|
||||
ibusimcontext->preedit_string = NULL;
|
||||
|
||||
g_signal_emit (ibusimcontext, _signal_preedit_changed_id, 0);
|
||||
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
_ibus_context_destroy_cb (IBusInputContext *ibuscontext,
|
||||
IBusIMContext *ibusimcontext)
|
||||
|
@ -1439,8 +1399,6 @@ _ibus_context_destroy_cb (IBusInputContext *ibuscontext,
|
|||
g_object_unref (ibusimcontext->ibuscontext);
|
||||
ibusimcontext->ibuscontext = NULL;
|
||||
|
||||
ibusimcontext->enable = FALSE;
|
||||
|
||||
/* clear preedit */
|
||||
ibusimcontext->preedit_visible = FALSE;
|
||||
ibusimcontext->preedit_cursor_pos = 0;
|
||||
|
@ -1497,14 +1455,6 @@ _create_input_context_done (IBusBus *bus,
|
|||
"hide-preedit-text",
|
||||
G_CALLBACK (_ibus_context_hide_preedit_text_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect (ibusimcontext->ibuscontext,
|
||||
"enabled",
|
||||
G_CALLBACK (_ibus_context_enabled_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect (ibusimcontext->ibuscontext,
|
||||
"disabled",
|
||||
G_CALLBACK (_ibus_context_disabled_cb),
|
||||
ibusimcontext);
|
||||
g_signal_connect (ibusimcontext->ibuscontext, "destroy",
|
||||
G_CALLBACK (_ibus_context_destroy_cb),
|
||||
ibusimcontext);
|
||||
|
@ -1549,10 +1499,6 @@ _slave_commit_cb (GtkIMContext *slave,
|
|||
gchar *string,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
#if 0
|
||||
if ((GtkIMContext *)context == CURRENT_CONTEXT && ibus_im_client_is_enabled (_client))
|
||||
return;
|
||||
#endif
|
||||
g_signal_emit (ibusimcontext, _signal_commit_id, 0, string);
|
||||
}
|
||||
|
||||
|
@ -1560,7 +1506,7 @@ static void
|
|||
_slave_preedit_changed_cb (GtkIMContext *slave,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
if (ibusimcontext->ibuscontext) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1571,7 +1517,7 @@ static void
|
|||
_slave_preedit_start_cb (GtkIMContext *slave,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
if (ibusimcontext->ibuscontext) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -1582,7 +1528,7 @@ static void
|
|||
_slave_preedit_end_cb (GtkIMContext *slave,
|
||||
IBusIMContext *ibusimcontext)
|
||||
{
|
||||
if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
if (ibusimcontext->ibuscontext) {
|
||||
return;
|
||||
}
|
||||
g_signal_emit (ibusimcontext, _signal_preedit_end_id, 0);
|
||||
|
@ -1594,7 +1540,7 @@ _slave_retrieve_surrounding_cb (GtkIMContext *slave,
|
|||
{
|
||||
gboolean return_value;
|
||||
|
||||
if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
if (ibusimcontext->ibuscontext) {
|
||||
return FALSE;
|
||||
}
|
||||
g_signal_emit (ibusimcontext, _signal_retrieve_surrounding_id, 0,
|
||||
|
@ -1610,7 +1556,7 @@ _slave_delete_surrounding_cb (GtkIMContext *slave,
|
|||
{
|
||||
gboolean return_value;
|
||||
|
||||
if (ibusimcontext->enable && ibusimcontext->ibuscontext) {
|
||||
if (ibusimcontext->ibuscontext) {
|
||||
return FALSE;
|
||||
}
|
||||
g_signal_emit (ibusimcontext, _signal_delete_surrounding_id, 0, offset_from_cursor, nchars, &return_value);
|
||||
|
|
|
@ -105,6 +105,7 @@ AC_SUBST(DATE_DISPLAY)
|
|||
AC_PROG_CC
|
||||
AM_PROG_CC_C_O
|
||||
AC_PROG_CC_STDC
|
||||
AM_PROG_VALAC([0.14])
|
||||
AC_PROG_INSTALL
|
||||
AC_PROG_MAKE_SET
|
||||
|
||||
|
@ -473,6 +474,7 @@ ui/Makefile
|
|||
ui/gtk/Makefile
|
||||
ui/gtk/ibus-ui-gtk
|
||||
ui/gtk/gtkpanel.xml.in
|
||||
ui/gtk3/Makefile
|
||||
setup/Makefile
|
||||
setup/ibus-setup
|
||||
gconf/Makefile
|
||||
|
|
|
@ -137,6 +137,10 @@ class Bus(object.Object):
|
|||
def list_engines(self):
|
||||
engines = self.__ibus.ListEngines()
|
||||
return map(serializable.deserialize_object, engines)
|
||||
|
||||
def get_engines_by_names(self, names):
|
||||
engines = self.__ibus.GetEnginesByNames(names)
|
||||
return map(serializable.deserialize_object, engines)
|
||||
|
||||
def list_active_engines(self):
|
||||
engines = self.__ibus.ListActiveEngines()
|
||||
|
|
|
@ -153,10 +153,6 @@ class InputContext(object.Object):
|
|||
self.__signal_matches.append(m)
|
||||
m = self.__context.connect_to_signal("RequireSurroundingText", self.__require_surrounding_text_cb)
|
||||
self.__signal_matches.append(m)
|
||||
m = self.__context.connect_to_signal("Enabled", self.__enabled_cb)
|
||||
self.__signal_matches.append(m)
|
||||
m = self.__context.connect_to_signal("Disabled", self.__disabled_cb)
|
||||
self.__signal_matches.append(m)
|
||||
|
||||
m = self.__context.connect_to_signal("ForwardKeyEvent", lambda *args: self.emit("forward-key-event", *args))
|
||||
self.__signal_matches.append(m)
|
||||
|
@ -185,14 +181,6 @@ class InputContext(object.Object):
|
|||
m = self.__context.connect_to_signal("CursorDownLookupTable", lambda *args: self.emit("cursor-down-lookup-table"))
|
||||
self.__signal_matches.append(m)
|
||||
|
||||
def __enabled_cb(self, *args):
|
||||
self.__needs_surrounding_text = False
|
||||
self.emit("enabled")
|
||||
|
||||
def __disabled_cb(self, *args):
|
||||
self.__needs_surrounding_text = False
|
||||
self.emit("disabled")
|
||||
|
||||
def __commit_text_cb(self, *args):
|
||||
text = serializable.deserialize_object(args[0])
|
||||
self.emit("commit-text", text)
|
||||
|
@ -253,15 +241,6 @@ class InputContext(object.Object):
|
|||
def reset(self):
|
||||
return self.__context.Reset()
|
||||
|
||||
def enable(self):
|
||||
return self.__context.Enable()
|
||||
|
||||
def disable(self):
|
||||
return self.__context.Disable()
|
||||
|
||||
def is_enabled(self):
|
||||
return self.__context.IsEnabled()
|
||||
|
||||
def set_capabilities(self, caps):
|
||||
caps = dbus.UInt32(caps)
|
||||
return self.__context.SetCapabilities(caps)
|
||||
|
@ -319,8 +298,6 @@ def test():
|
|||
self.__context.connect("show-preedit-text", self.__show_preedit_text_cb)
|
||||
self.__context.connect("update-auxiliary-text", self.__update_auxiliary_text_cb)
|
||||
self.__context.connect("update-lookup-table", self.__update_lookup_table_cb)
|
||||
self.__context.connect("enabled", self.__enabled_cb)
|
||||
self.__context.connect("disabled", self.__disabled_cb)
|
||||
|
||||
self.set_events(gtk.gdk.KEY_PRESS_MASK | gtk.gdk.KEY_RELEASE_MASK | gtk.gdk.FOCUS_CHANGE_MASK)
|
||||
|
||||
|
@ -350,14 +327,6 @@ def test():
|
|||
def __update_lookup_table_cb(self, context, table, visible):
|
||||
print "update-lookup-table:", visible
|
||||
|
||||
def __enabled_cb(self, context):
|
||||
print "enabled"
|
||||
info = context.get_factory_info()
|
||||
print "factory = %s" % info.name
|
||||
|
||||
def __disabled_cb(self, context):
|
||||
print "disabled"
|
||||
|
||||
def __key_press_event_cb(self, widget, event):
|
||||
self.__context.process_key_event(event.keyval, event.state)
|
||||
|
||||
|
|
|
@ -62,6 +62,9 @@ class IIBus(dbus.service.Object):
|
|||
|
||||
@method(out_signature="av")
|
||||
def ListEngines(self, dbusconn): pass
|
||||
|
||||
@method(in_signature="as", out_signature="av")
|
||||
def GetEnginesByNames(self, names, dbusconn): pass
|
||||
|
||||
@method(out_signature="av")
|
||||
def ListActiveEngines(self, dbusconn): pass
|
||||
|
|
|
@ -61,15 +61,6 @@ class IInputContext(dbus.service.Object):
|
|||
@method()
|
||||
def Reset(self): pass
|
||||
|
||||
@method()
|
||||
def Enable(self): pass
|
||||
|
||||
@method()
|
||||
def Disable(self): pass
|
||||
|
||||
@method(out_signature="b")
|
||||
def IsEnabled(self): pass
|
||||
|
||||
@method(in_signature="u")
|
||||
def SetCapabilities(self, caps): pass
|
||||
|
||||
|
@ -86,12 +77,6 @@ class IInputContext(dbus.service.Object):
|
|||
@signal(signature="v")
|
||||
def CommitText(self, text): pass
|
||||
|
||||
@signal()
|
||||
def Enabled(self): pass
|
||||
|
||||
@signal()
|
||||
def Disabled(self): pass
|
||||
|
||||
@signal(signature="uuu")
|
||||
def ForwardKeyEvent(self, keyval, keycode, state): pass
|
||||
|
||||
|
|
|
@ -1478,6 +1478,37 @@ ibus_bus_list_active_engines_async_finish (IBusBus *bus,
|
|||
return ibus_bus_list_engines_async_finish (bus, res, error);
|
||||
}
|
||||
|
||||
IBusEngineDesc **
|
||||
ibus_bus_get_engines_by_names (IBusBus *bus,
|
||||
const gchar * const *names)
|
||||
{
|
||||
g_return_val_if_fail (IBUS_IS_BUS (bus), NULL);
|
||||
|
||||
GVariant *result;
|
||||
result = ibus_bus_call_sync (bus,
|
||||
IBUS_SERVICE_IBUS,
|
||||
IBUS_PATH_IBUS,
|
||||
IBUS_INTERFACE_IBUS,
|
||||
"GetEnginesByNames",
|
||||
g_variant_new("(^as)", names),
|
||||
G_VARIANT_TYPE ("(av)"));
|
||||
if (result == NULL)
|
||||
return NULL;
|
||||
|
||||
GArray *array = g_array_new (TRUE, TRUE, sizeof (IBusEngineDesc *));
|
||||
GVariantIter *iter = NULL;
|
||||
g_variant_get (result, "(av)", &iter);
|
||||
GVariant *var;
|
||||
while (g_variant_iter_loop (iter, "v", &var)) {
|
||||
IBusEngineDesc *desc = (IBusEngineDesc *) ibus_serializable_deserialize (var);
|
||||
g_array_append_val (array, desc);
|
||||
}
|
||||
g_variant_iter_free (iter);
|
||||
g_variant_unref (result);
|
||||
|
||||
return (IBusEngineDesc **)g_array_free (array, FALSE);
|
||||
}
|
||||
|
||||
static void
|
||||
_config_destroy_cb (IBusConfig *config,
|
||||
IBusBus *bus)
|
||||
|
|
|
@ -710,6 +710,19 @@ GList *ibus_bus_list_active_engines_async_finish
|
|||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* ibus_bus_get_engines_by_names:
|
||||
* @bus: An #IBusBus.
|
||||
* @names: A %NULL-terminated array of names.
|
||||
* @returns: (transfer container) (element-type IBusEngineDesc): A %NULL-terminated array of engines.
|
||||
*
|
||||
* Get engines by given names synchronously.
|
||||
* TODO(penghuang): add asynchronous version
|
||||
*/
|
||||
IBusEngineDesc **
|
||||
ibus_bus_get_engines_by_names
|
||||
(IBusBus *bus,
|
||||
const gchar * const *names);
|
||||
/**
|
||||
* ibus_bus_get_use_sys_layout:
|
||||
* @bus: An #IBusBus.
|
||||
|
|
|
@ -1009,45 +1009,6 @@ ibus_input_context_property_hide (IBusInputContext *context,
|
|||
);
|
||||
}
|
||||
|
||||
void
|
||||
ibus_input_context_is_enabled_async (IBusInputContext *context,
|
||||
gint timeout_msec,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data)
|
||||
{
|
||||
g_assert (IBUS_IS_INPUT_CONTEXT (context));
|
||||
g_dbus_proxy_call ((GDBusProxy *) context,
|
||||
"IsEnabled", /* method_name */
|
||||
NULL, /* parameters */
|
||||
G_DBUS_CALL_FLAGS_NONE, /* flags */
|
||||
timeout_msec,
|
||||
cancellable,
|
||||
callback,
|
||||
user_data);
|
||||
}
|
||||
|
||||
gboolean
|
||||
ibus_input_context_is_enabled_async_finish (IBusInputContext *context,
|
||||
GAsyncResult *res,
|
||||
GError **error)
|
||||
{
|
||||
g_assert (IBUS_IS_INPUT_CONTEXT (context));
|
||||
g_assert (G_IS_ASYNC_RESULT (res));
|
||||
g_assert (error == NULL || *error == NULL);
|
||||
|
||||
gboolean enabled = FALSE;
|
||||
|
||||
GVariant *variant = g_dbus_proxy_call_finish ((GDBusProxy *) context,
|
||||
res, error);
|
||||
if (variant != NULL) {
|
||||
g_variant_get (variant, "(b)", &enabled);
|
||||
g_variant_unref (variant);
|
||||
}
|
||||
|
||||
return enabled;
|
||||
}
|
||||
|
||||
void
|
||||
ibus_input_context_set_surrounding_text (IBusInputContext *context,
|
||||
IBusText *text,
|
||||
|
@ -1096,34 +1057,6 @@ ibus_input_context_needs_surrounding_text (IBusInputContext *context)
|
|||
return priv->needs_surrounding_text;
|
||||
}
|
||||
|
||||
gboolean
|
||||
ibus_input_context_is_enabled (IBusInputContext *context)
|
||||
{
|
||||
g_assert (IBUS_IS_INPUT_CONTEXT (context));
|
||||
GVariant *result;
|
||||
GError *error = NULL;
|
||||
result = g_dbus_proxy_call_sync ((GDBusProxy *) context,
|
||||
"IsEnabled", /* method_name */
|
||||
NULL, /* parameters */
|
||||
G_DBUS_CALL_FLAGS_NONE, /* flags */
|
||||
-1, /* timeout */
|
||||
NULL, /* cancellable */
|
||||
&error /* error */
|
||||
);
|
||||
|
||||
if (result == NULL) {
|
||||
g_warning ("%s.IsEnabled: %s", IBUS_INTERFACE_INPUT_CONTEXT, error->message);
|
||||
g_error_free (error);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
gboolean retval = FALSE;
|
||||
g_variant_get (result, "(b)", &retval);
|
||||
g_variant_unref (result);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
ibus_input_context_get_engine_async (IBusInputContext *context,
|
||||
gint timeout_msec,
|
||||
|
@ -1242,6 +1175,4 @@ DEFINE_FUNC(page_up, PageUp);
|
|||
DEFINE_FUNC(page_down, PageDown);
|
||||
DEFINE_FUNC(cursor_up, CursorUp);
|
||||
DEFINE_FUNC(cursor_down, CursorDown);
|
||||
DEFINE_FUNC(enable, Enable);
|
||||
DEFINE_FUNC(disable, Disable);
|
||||
#undef DEFINE_FUNC
|
||||
|
|
|
@ -371,73 +371,6 @@ void ibus_input_context_focus_out (IBusInputContext *context);
|
|||
*/
|
||||
void ibus_input_context_reset (IBusInputContext *context);
|
||||
|
||||
/**
|
||||
* ibus_input_context_enable:
|
||||
* @context: An IBusInputContext.
|
||||
*
|
||||
* Invoked when the IME is enabled, either by IME switch hotkey or select from the menu.
|
||||
* An asynchronous IPC will be performed.
|
||||
*
|
||||
* see_also: #IBusEngine::enable
|
||||
*/
|
||||
void ibus_input_context_enable (IBusInputContext *context);
|
||||
|
||||
/**
|
||||
* ibus_input_context_disable:
|
||||
* @context: An IBusInputContext.
|
||||
*
|
||||
* Invoked when the IME is disabled, either by IME switch hotkey or select from the menu.
|
||||
* An asynchronous IPC will be performed.
|
||||
*
|
||||
* see_also: #IBusEngine::disable
|
||||
*/
|
||||
void ibus_input_context_disable (IBusInputContext *context);
|
||||
|
||||
|
||||
/**
|
||||
* ibus_input_context_is_enabled_async:
|
||||
* @context: An #IBusInputContext.
|
||||
* @timeout_msec: The timeout in milliseconds or -1 to use the default timeout.
|
||||
* @cancellable: A #GCancellable or %NULL.
|
||||
* @callback: A #GAsyncReadyCallback to call when the request is satisfied or %NULL
|
||||
* if you don't care about the result of the method invocation.
|
||||
* @user_data: The data to pass to callback.
|
||||
*
|
||||
* An asynchronous IPC will be performed.
|
||||
*/
|
||||
void ibus_input_context_is_enabled_async
|
||||
(IBusInputContext *context,
|
||||
gint timeout_msec,
|
||||
GCancellable *cancellable,
|
||||
GAsyncReadyCallback callback,
|
||||
gpointer user_data);
|
||||
|
||||
/**
|
||||
* ibus_input_context_is_enabled_async_finish:
|
||||
* @context: An #IBusInputContext.
|
||||
* @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to
|
||||
* ibus_input_context_is_enabled_async().
|
||||
* @error: Return location for error or %NULL.
|
||||
* @returns: %TRUE if the IME is enabled on the contextfor success;
|
||||
* %FALSE otherwise or some errors happen and the @error will be set.
|
||||
*
|
||||
* Finishes an operation started with ibus_input_context_is_enabled_async().
|
||||
*/
|
||||
gboolean ibus_input_context_is_enabled_async_finish
|
||||
(IBusInputContext *context,
|
||||
GAsyncResult *res,
|
||||
GError **error);
|
||||
|
||||
/**
|
||||
* ibus_input_context_is_enabled:
|
||||
* @context: An IBusInputContext.
|
||||
* @returns: TRUE if the IME is enabled on the context.
|
||||
*
|
||||
* Returns TRUE if the IME is enabled on the context.
|
||||
* A asynchronous IPC will be performed.
|
||||
*/
|
||||
gboolean ibus_input_context_is_enabled (IBusInputContext *context);
|
||||
|
||||
/**
|
||||
* ibus_input_context_get_engine_async:
|
||||
* @context: An #IBusInputContext.
|
||||
|
|
|
@ -56,10 +56,6 @@ call_basic_ipcs (IBusInputContext *context)
|
|||
ibus_input_context_set_capabilities (context, IBUS_CAP_FOCUS);
|
||||
ibus_input_context_property_activate (context, "dummy.prop.name", PROP_STATE_CHECKED);
|
||||
ibus_input_context_reset (context);
|
||||
ibus_input_context_disable (context);
|
||||
/* g_assert (ibus_input_context_is_enabled (context) == FALSE); */ /* see below. */
|
||||
ibus_input_context_enable (context);
|
||||
/* g_assert (ibus_input_context_is_enabled (context) == TRUE); */ /* see below. */
|
||||
|
||||
/* When enable() is called, ibus-daemon may start a global (or preloaded,
|
||||
* or default) engine in an asynchrnous manner and return immediately.
|
||||
|
@ -119,31 +115,6 @@ test_input_context (void)
|
|||
g_list_free (engines);
|
||||
}
|
||||
|
||||
static void
|
||||
finish_is_enabled_async (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
gpointer user_data)
|
||||
{
|
||||
IBusInputContext *context = IBUS_INPUT_CONTEXT (source_object);
|
||||
GError *error = NULL;
|
||||
gboolean result = ibus_input_context_is_enabled_async_finish (context,
|
||||
res,
|
||||
&error);
|
||||
g_assert (result);
|
||||
g_debug ("ibus_context_is_enabled_async_finish: OK");
|
||||
call_next_async_function (context);
|
||||
}
|
||||
|
||||
static void
|
||||
start_is_enabled_async (IBusInputContext *context)
|
||||
{
|
||||
ibus_input_context_is_enabled_async (context,
|
||||
-1, /* timeout */
|
||||
NULL, /* cancellable */
|
||||
finish_is_enabled_async,
|
||||
NULL); /* user_data */
|
||||
}
|
||||
|
||||
static void
|
||||
finish_get_engine_async (GObject *source_object,
|
||||
GAsyncResult *res,
|
||||
|
@ -220,7 +191,6 @@ static void
|
|||
call_next_async_function (IBusInputContext *context)
|
||||
{
|
||||
static void (*async_functions[])(IBusInputContext *) = {
|
||||
start_is_enabled_async,
|
||||
start_get_engine_async,
|
||||
start_process_key_event_async,
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@
|
|||
if ENABLE_PYTHON
|
||||
SUBDIRS = \
|
||||
gtk \
|
||||
gtk3 \
|
||||
$(NULL)
|
||||
endif
|
||||
|
||||
|
|
|
@ -202,7 +202,6 @@ class CandidatePanel(gtk.VBox):
|
|||
gdk.BUTTON_PRESS_MASK | \
|
||||
gdk.BUTTON_RELEASE_MASK | \
|
||||
gdk.BUTTON1_MOTION_MASK)
|
||||
self.__begin_move = False
|
||||
self.__toplevel.connect("size-allocate", lambda w, a: self.__check_position())
|
||||
|
||||
self.__orientation = ibus.ORIENTATION_VERTICAL
|
||||
|
|
|
@ -354,7 +354,7 @@ class LanguageBar(gtk.Toolbar):
|
|||
self.__properties.append(item)
|
||||
menu.insert(item, 0)
|
||||
|
||||
about_label = _("About") + " - " + self.__im_name
|
||||
about_label = _("About") + " - " + (self.__im_name or "")
|
||||
prop = ibus.Property(key=u"about",
|
||||
label=unicode(about_label),
|
||||
icon=unicode(gtk.STOCK_ABOUT),
|
||||
|
|
|
@ -220,7 +220,7 @@ class Panel(ibus.PanelBase):
|
|||
def focus_in(self, ic):
|
||||
self.reset()
|
||||
self.__focus_ic = ibus.InputContext(self.__bus, ic)
|
||||
enabled = self.__focus_ic.is_enabled()
|
||||
enabled = True or self.__focus_ic.is_enabled()
|
||||
self.__language_bar.set_enabled(enabled)
|
||||
|
||||
if not enabled:
|
||||
|
@ -414,7 +414,11 @@ class Panel(ibus.PanelBase):
|
|||
# return menu
|
||||
|
||||
def __create_im_menu(self):
|
||||
engines = self.__bus.list_active_engines()
|
||||
# FIXME
|
||||
# engines = self.__bus.list_engines()
|
||||
names = self.__config.get_value("general", "preload_engines",
|
||||
["xkb:us::eng", "xkb:us:intl:eng", "pinyin"])
|
||||
engines = self.__bus.get_engines_by_names(names)
|
||||
current_engine = \
|
||||
(self.__focus_ic != None and self.__focus_ic.get_engine()) or \
|
||||
(engines and engines[0]) or \
|
||||
|
@ -439,7 +443,7 @@ class Panel(ibus.PanelBase):
|
|||
item = gtk.ImageMenuItem(_("Turn off input method"))
|
||||
item.set_image(_icon.IconWidget("gtk-close", size[0]))
|
||||
item.connect("activate", self.__im_menu_item_activate_cb, None)
|
||||
if self.__focus_ic == None or not self.__focus_ic.is_enabled():
|
||||
if self.__focus_ic == None:
|
||||
item.set_sensitive(False)
|
||||
menu.add(item)
|
||||
|
||||
|
|
|
@ -0,0 +1,84 @@
|
|||
# vim:set noet ts=4:
|
||||
#
|
||||
# ibus - The Input Bus
|
||||
#
|
||||
# Copyright (c) 2007-2010 Peng Huang <shawn.p.huang@gmail.com>
|
||||
# Copyright (c) 2007-2010 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
|
||||
# License as published by the Free Software Foundation; either
|
||||
# version 2 of the License, or (at your option) any later version.
|
||||
#
|
||||
# This library is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public
|
||||
# License along with this program; if not, write to the
|
||||
# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
# Boston, MA 02111-1307 USA
|
||||
|
||||
NULL =
|
||||
|
||||
libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la
|
||||
|
||||
INCLUDES = \
|
||||
-I$(top_srcdir)/src \
|
||||
-I$(top_builddir)/src \
|
||||
$(NULL)
|
||||
|
||||
AM_CFLAGS = \
|
||||
@GLIB2_CFLAGS@ \
|
||||
@GIO2_CFLAGS@ \
|
||||
@GTHREAD2_CFLAGS@ \
|
||||
@GTK3_CFLAGS@ \
|
||||
@X11_CFLAGS@ \
|
||||
-DG_LOG_DOMAIN=\"IBUS\" \
|
||||
-DPKGDATADIR=\"$(pkgdatadir)\" \
|
||||
-DLIBEXECDIR=\"$(libexecdir)\" \
|
||||
-DBINDIR=\"@bindir@\" \
|
||||
$(INCLUDES) \
|
||||
$(NULL)
|
||||
|
||||
AM_LDADD = \
|
||||
@GOBJECT2_LIBS@ \
|
||||
@GLIB2_LIBS@ \
|
||||
@GIO2_LIBS@ \
|
||||
@GTHREAD2_LIBS@ \
|
||||
@GTK3_LIBS@ \
|
||||
@X11_LIBS@ \
|
||||
$(libibus) \
|
||||
$(NULL)
|
||||
|
||||
AM_VALAFLAGS = \
|
||||
--vapidir=$(top_builddir)/bindings/vala \
|
||||
--pkg=gtk+-3.0 \
|
||||
--pkg=gdk-x11-3.0 \
|
||||
--pkg=ibus-1.0 \
|
||||
$(NULL)
|
||||
|
||||
bin_PROGRAMS = ibus-ui-gtk3
|
||||
|
||||
ibus_ui_gtk3_SOURCES = \
|
||||
application.vala \
|
||||
candidatearea.vala \
|
||||
candidatepanel.vala \
|
||||
handle.vala \
|
||||
iconwidget.vala \
|
||||
keybindingmanager.vala \
|
||||
panel.vala \
|
||||
pango.vala \
|
||||
separator.vala \
|
||||
$(NULL)
|
||||
|
||||
ibus_ui_gtk3_CFLAGS = \
|
||||
$(AM_CFLAGS) \
|
||||
$(NULL)
|
||||
|
||||
ibus_ui_gtk3_LDADD = \
|
||||
$(AM_LDADD) \
|
||||
$(NULL)
|
||||
|
||||
-include $(top_srcdir)/git.mk
|
|
@ -0,0 +1,109 @@
|
|||
/* vim:set et sts=4 sw=4:
|
||||
*
|
||||
* ibus - The Input Bus
|
||||
*
|
||||
* Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or(at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using IBus;
|
||||
using GLib;
|
||||
using Gtk;
|
||||
|
||||
class Application {
|
||||
private IBus.Bus m_bus;
|
||||
private Panel m_panel;
|
||||
private KeybindingManager m_keybinding_manager;
|
||||
|
||||
public Application(string[] argv) {
|
||||
IBus.init();
|
||||
Gtk.init(ref argv);
|
||||
|
||||
m_keybinding_manager = new KeybindingManager();
|
||||
m_bus = new IBus.Bus();
|
||||
m_panel = new Panel(m_bus);
|
||||
|
||||
m_bus.connected.connect(bus_connected);
|
||||
m_bus.disconnected.connect(bus_disconnected);
|
||||
|
||||
if (m_bus.is_connected()) {
|
||||
init();
|
||||
}
|
||||
m_keybinding_manager.bind("<Ctrl><Alt>V", hotkey_triggered);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
DBusConnection connection = m_bus.get_connection();
|
||||
connection.signal_subscribe("org.freedesktop.DBus",
|
||||
"org.freedesktop.DBus",
|
||||
"NameAcquired",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.IBus.Panel",
|
||||
DBusSignalFlags.NONE,
|
||||
this.bus_name_acquired);
|
||||
connection.signal_subscribe("org.freedesktop.DBus",
|
||||
"org.freedesktop.DBus",
|
||||
"NameLost",
|
||||
"/org/freedesktop/DBus",
|
||||
"org.freedesktop.IBus.Panel",
|
||||
DBusSignalFlags.NONE,
|
||||
this.bus_name_lost);
|
||||
|
||||
m_bus.request_name("org.freedesktop.IBus.Panel", 2);
|
||||
}
|
||||
|
||||
public int run() {
|
||||
Gtk.main();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private void bus_name_acquired(DBusConnection connection,
|
||||
string sender_name,
|
||||
string object_path,
|
||||
string interface_name,
|
||||
string signal_name,
|
||||
Variant parameters) {
|
||||
debug("signal_name = %s", signal_name);
|
||||
}
|
||||
|
||||
private void bus_name_lost(DBusConnection connection,
|
||||
string sender_name,
|
||||
string object_path,
|
||||
string interface_name,
|
||||
string signal_name,
|
||||
Variant parameters) {
|
||||
debug("signal_name = %s", signal_name);
|
||||
}
|
||||
|
||||
private void bus_disconnected(IBus.Bus bus) {
|
||||
debug("connection is lost.");
|
||||
Gtk.main_quit();
|
||||
}
|
||||
|
||||
private void bus_connected(IBus.Bus bus) {
|
||||
init();
|
||||
}
|
||||
|
||||
private void hotkey_triggered() {
|
||||
debug("hotkey");
|
||||
}
|
||||
|
||||
public static void main(string[] argv) {
|
||||
Application app = new Application(argv);
|
||||
app.run();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,252 @@
|
|||
/* vim:set et sts=4 sw=4:
|
||||
*
|
||||
* ibus - The Input Bus
|
||||
*
|
||||
* Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or(at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using Gtk;
|
||||
using IBus;
|
||||
using Pango;
|
||||
|
||||
class CandidateArea : Gtk.Box {
|
||||
private bool m_vertical;
|
||||
private Gtk.Label[] m_labels;
|
||||
private Gtk.Label[] m_candidates;
|
||||
private Gtk.Widget[] m_widgets;
|
||||
|
||||
private IBus.Text[] m_ibus_candidates;
|
||||
private uint m_focus_candidate;
|
||||
private bool m_show_cursor;
|
||||
|
||||
public signal void candidate_clicked(uint index, uint button, uint state);
|
||||
public signal void page_up();
|
||||
public signal void page_down();
|
||||
public signal void cursor_up();
|
||||
public signal void cursor_down();
|
||||
|
||||
public CandidateArea(bool vertical) {
|
||||
GLib.Object(
|
||||
orientation: vertical ? Gtk.Orientation.VERTICAL : Gtk.Orientation.HORIZONTAL
|
||||
);
|
||||
m_vertical = vertical;
|
||||
recreate_ui();
|
||||
show_all();
|
||||
}
|
||||
|
||||
public void set_vertical(bool vertical) {
|
||||
if (m_vertical == vertical)
|
||||
return;
|
||||
m_vertical = vertical;
|
||||
recreate_ui();
|
||||
|
||||
// Workaround a vala issue https://bugzilla.gnome.org/show_bug.cgi?id=661130
|
||||
set_candidates((owned)m_ibus_candidates, m_focus_candidate, m_show_cursor);
|
||||
if (m_candidates.length > 0)
|
||||
show_all();
|
||||
}
|
||||
|
||||
public void set_labels(string[] labels) {
|
||||
if (labels == null) {
|
||||
const string labels[] = {
|
||||
"1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
|
||||
"9.", "0.", "a.", "b.", "c.", "d.", "e.", "f."
|
||||
};
|
||||
for (int i = 0 ; i < 16; i++)
|
||||
m_labels[i].set_text(labels[i]);
|
||||
} else {
|
||||
int i = 0;
|
||||
foreach (string label in labels)
|
||||
m_labels[i].set_text(label);
|
||||
}
|
||||
}
|
||||
|
||||
public void set_candidates(IBus.Text[] candidates,
|
||||
uint focus_candidate = 0,
|
||||
bool show_cursor = true) {
|
||||
m_ibus_candidates = candidates;
|
||||
m_focus_candidate = focus_candidate;
|
||||
m_show_cursor = show_cursor;
|
||||
|
||||
assert(candidates.length < 16);
|
||||
for (int i = 0 ; i < 16 ; i++) {
|
||||
Gtk.Label label = m_candidates[i];
|
||||
bool visible = false;
|
||||
if (i < candidates.length) {
|
||||
Pango.AttrList attrs = get_pango_attr_list_from_ibus_text(candidates[i]);
|
||||
if (i == focus_candidate && show_cursor) {
|
||||
Gtk.StyleContext context = m_candidates[i].get_style_context();
|
||||
Gdk.RGBA color = context.get_color(Gtk.StateFlags.SELECTED);
|
||||
Pango.Attribute pango_attr = Pango.attr_foreground_new(
|
||||
(uint16)(color.red * uint16.MAX),
|
||||
(uint16)(color.green * uint16.MAX),
|
||||
(uint16)(color.blue * uint16.MAX));
|
||||
pango_attr.start_index = 0;
|
||||
pango_attr.end_index = candidates[i].get_text().length;
|
||||
attrs.insert((owned)pango_attr);
|
||||
|
||||
color = context.get_background_color(Gtk.StateFlags.SELECTED);
|
||||
pango_attr = Pango.attr_background_new(
|
||||
(uint16)(color.red * uint16.MAX),
|
||||
(uint16)(color.green * uint16.MAX),
|
||||
(uint16)(color.blue * uint16.MAX));
|
||||
pango_attr.start_index = 0;
|
||||
pango_attr.end_index = candidates[i].get_text().length;
|
||||
attrs.insert((owned)pango_attr);
|
||||
}
|
||||
label.set_text(candidates[i].get_text());
|
||||
label.set_attributes(attrs);
|
||||
visible = true;
|
||||
} else {
|
||||
label.set_text("");
|
||||
label.set_attributes(new Pango.AttrList());
|
||||
}
|
||||
if (m_vertical) {
|
||||
m_widgets[i * 2].set_visible(visible);
|
||||
m_widgets[i * 2 +1].set_visible(visible);
|
||||
} else {
|
||||
m_widgets[i].set_visible(visible);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void recreate_ui() {
|
||||
foreach (Gtk.Widget w in get_children()) {
|
||||
w.destroy();
|
||||
}
|
||||
|
||||
const string labels[] = {
|
||||
"1.", "2.", "3.", "4.", "5.", "6.", "7.", "8.",
|
||||
"9.", "0.", "a.", "b.", "c.", "d.", "e.", "f."
|
||||
};
|
||||
|
||||
Gtk.Button prev_button = new Gtk.Button();
|
||||
prev_button.clicked.connect((b) => page_up());
|
||||
prev_button.set_image(new Gtk.Image.from_icon_name(Gtk.Stock.GO_UP, Gtk.IconSize.MENU));
|
||||
prev_button.set_relief(Gtk.ReliefStyle.NONE);
|
||||
|
||||
Gtk.Button next_button = new Gtk.Button();
|
||||
next_button.clicked.connect((b) => page_down());
|
||||
next_button.set_image(new Gtk.Image.from_icon_name(Gtk.Stock.GO_DOWN, Gtk.IconSize.MENU));
|
||||
next_button.set_relief(Gtk.ReliefStyle.NONE);
|
||||
|
||||
if (m_vertical) {
|
||||
// Add Candidates
|
||||
Gtk.HBox candidates_hbox = new Gtk.HBox(false, 0);
|
||||
pack_start(candidates_hbox, false, false, 0);
|
||||
Gtk.VBox labels_vbox = new Gtk.VBox(true, 0);
|
||||
Gtk.VBox candidates_vbox = new Gtk.VBox(true, 0);
|
||||
candidates_hbox.pack_start(labels_vbox, false, false, 4);
|
||||
candidates_hbox.pack_start(new VSeparator(), false, false, 0);
|
||||
candidates_hbox.pack_start(candidates_vbox, true, true, 4);
|
||||
|
||||
// Add HSeparator
|
||||
pack_start(new HSeparator(), false, false, 0);
|
||||
|
||||
// Add buttons
|
||||
Gtk.HBox buttons_hbox = new Gtk.HBox(false, 0);
|
||||
Gtk.Label state_label = new Gtk.Label(null);
|
||||
state_label.set_size_request(20, -1);
|
||||
buttons_hbox.pack_start(state_label, true, true, 0);
|
||||
buttons_hbox.pack_start(prev_button, false, false, 0);
|
||||
buttons_hbox.pack_start(next_button, false, false, 0);
|
||||
pack_start(buttons_hbox, false, false, 0);
|
||||
|
||||
m_labels = {};
|
||||
m_candidates = {};
|
||||
m_widgets = {};
|
||||
for (int i = 0; i < 16; i++) {
|
||||
Gtk.Label label = new Gtk.Label(labels[i]);
|
||||
label.set_alignment(0.0f, 0.5f);
|
||||
label.show();
|
||||
m_labels += label;
|
||||
|
||||
Gtk.Label candidate = new Gtk.Label("test");
|
||||
candidate.set_alignment(0.0f, 0.5f);
|
||||
candidate.show();
|
||||
m_candidates += candidate;
|
||||
|
||||
label.set_property("xpad", 8);
|
||||
candidate.set_property("xpad", 8);
|
||||
|
||||
// Make a copy of i to workaround a bug in vala.
|
||||
// https://bugzilla.gnome.org/show_bug.cgi?id=628336
|
||||
int index = i;
|
||||
Gtk.EventBox label_ebox = new Gtk.EventBox();
|
||||
label_ebox.set_no_show_all(true);
|
||||
label_ebox.button_press_event.connect((w, e) => {
|
||||
candidate_clicked(i, e.button, e.state);
|
||||
return true;
|
||||
});
|
||||
label_ebox.add(label);
|
||||
labels_vbox.pack_start(label_ebox, false, false, 2);
|
||||
m_widgets += label_ebox;
|
||||
|
||||
Gtk.EventBox candidate_ebox = new Gtk.EventBox();
|
||||
candidate_ebox.set_no_show_all(true);
|
||||
candidate_ebox.button_press_event.connect((w, e) => {
|
||||
candidate_clicked(index, e.button, e.state);
|
||||
return true;
|
||||
});
|
||||
candidate_ebox.add(candidate);
|
||||
candidates_vbox.pack_start(candidate_ebox, false, false, 2);
|
||||
m_widgets += candidate_ebox;
|
||||
}
|
||||
} else {
|
||||
Gtk.HBox hbox = new Gtk.HBox(false, 0);
|
||||
add(hbox);
|
||||
|
||||
m_labels = {};
|
||||
m_candidates = {};
|
||||
m_widgets = {};
|
||||
for (int i = 0; i < 16; i++) {
|
||||
Gtk.Label label = new Gtk.Label(labels[i]);
|
||||
label.set_alignment(0.0f, 0.5f);
|
||||
label.show();
|
||||
m_labels += label;
|
||||
|
||||
Gtk.Label candidate = new Gtk.Label("test");
|
||||
candidate.set_alignment(0.0f, 0.5f);
|
||||
candidate.show();
|
||||
m_candidates += candidate;
|
||||
|
||||
Gtk.HBox candidate_hbox = new Gtk.HBox(false, 0);
|
||||
candidate_hbox.show();
|
||||
candidate_hbox.pack_start(label, false, false, 2);
|
||||
candidate_hbox.pack_start(candidate, false, false, 2);
|
||||
|
||||
// Make a copy of i to workaround a bug in vala.
|
||||
// https://bugzilla.gnome.org/show_bug.cgi?id=628336
|
||||
int index = i;
|
||||
Gtk.EventBox ebox = new Gtk.EventBox();
|
||||
ebox.set_no_show_all(true);
|
||||
ebox.button_press_event.connect((w, e) => {
|
||||
candidate_clicked(index, e.button, e.state);
|
||||
return true;
|
||||
});
|
||||
ebox.add(candidate_hbox);
|
||||
hbox.pack_start(ebox, false, false, 4);
|
||||
m_widgets += ebox;
|
||||
}
|
||||
hbox.pack_start(new VSeparator(), false, false, 0);
|
||||
hbox.pack_start(prev_button, false, false, 0);
|
||||
hbox.pack_start(next_button, false, false, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,238 @@
|
|||
/* vim:set et sts=4 sw=4:
|
||||
*
|
||||
* ibus - The Input Bus
|
||||
*
|
||||
* Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or(at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using Gtk;
|
||||
using Pango;
|
||||
|
||||
class CandidatePanel : Gtk.HBox{
|
||||
private bool m_vertical = true;
|
||||
private Gtk.Window m_toplevel;
|
||||
private Gtk.VBox m_vbox;
|
||||
|
||||
private Gtk.Label m_preedit_label;
|
||||
private Gtk.Label m_aux_label;
|
||||
private CandidateArea m_candidate_area;
|
||||
private HSeparator m_hseparator;
|
||||
|
||||
private Gdk.Rectangle m_cursor_location;
|
||||
|
||||
public signal void cursor_up();
|
||||
public signal void cursor_down();
|
||||
public signal void page_up();
|
||||
public signal void page_down();
|
||||
public signal void candidate_clicked(uint index,
|
||||
uint button,
|
||||
uint state);
|
||||
|
||||
public CandidatePanel() {
|
||||
// Call base class constructor
|
||||
GLib.Object(
|
||||
name : "IBusCandidate"
|
||||
);
|
||||
|
||||
m_toplevel = new Gtk.Window(Gtk.WindowType.POPUP);
|
||||
m_toplevel.add_events(Gdk.EventMask.BUTTON_PRESS_MASK);
|
||||
m_toplevel.button_press_event.connect((w, e) => {
|
||||
if (e.button != 1 || (e.state & Gdk.ModifierType.CONTROL_MASK) == 0)
|
||||
return false;
|
||||
set_vertical(!m_vertical);
|
||||
return true;
|
||||
});
|
||||
|
||||
m_vbox = new Gtk.VBox(false, 0);
|
||||
Handle handle = new Handle();
|
||||
pack_start(handle, false, false, 0);
|
||||
pack_start(m_vbox, false, false, 0);
|
||||
|
||||
m_toplevel.add(this);
|
||||
|
||||
create_ui();
|
||||
}
|
||||
|
||||
public void set_vertical(bool vertical) {
|
||||
if (m_vertical == vertical)
|
||||
return;
|
||||
m_vertical = vertical;
|
||||
m_candidate_area.set_vertical(vertical);
|
||||
}
|
||||
|
||||
public void set_cursor_location(int x, int y, int width, int height) {
|
||||
Gdk.Rectangle location = { x, y, width, height };
|
||||
if (m_cursor_location == location)
|
||||
return;
|
||||
m_cursor_location = location;
|
||||
adjust_window_position();
|
||||
}
|
||||
|
||||
public void set_labels(string[] labels) {
|
||||
m_candidate_area.set_labels(labels);
|
||||
}
|
||||
|
||||
public void set_preedit_text(IBus.Text? text, uint cursor) {
|
||||
if (text != null) {
|
||||
m_preedit_label.set_text(text.get_text());
|
||||
m_preedit_label.show();
|
||||
} else {
|
||||
m_preedit_label.set_text("");
|
||||
m_preedit_label.hide();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
public void set_auxiliary_text(IBus.Text? text) {
|
||||
if (text != null) {
|
||||
m_aux_label.set_text(text.get_text());
|
||||
m_aux_label.show();
|
||||
} else {
|
||||
m_aux_label.set_text("");
|
||||
m_aux_label.hide();
|
||||
}
|
||||
update();
|
||||
}
|
||||
|
||||
public void set_lookup_table(IBus.LookupTable? table) {
|
||||
IBus.Text[] candidates = {};
|
||||
uint cursor_in_page = 0;
|
||||
bool show_cursor = true;
|
||||
|
||||
if (table != null) {
|
||||
uint page_size = table.get_page_size();
|
||||
uint ncandidates = table.get_number_of_candidates();
|
||||
uint cursor = table.get_cursor_pos();
|
||||
cursor_in_page = table.get_cursor_in_page();
|
||||
show_cursor = table.is_cursor_visible();
|
||||
|
||||
uint page_start_pos = cursor / page_size * page_size;
|
||||
uint page_end_pos = uint.min(page_start_pos + page_size, ncandidates);
|
||||
for (uint i = page_start_pos; i < page_end_pos; i++)
|
||||
candidates += table.get_candidate(i);
|
||||
}
|
||||
m_candidate_area.set_candidates(candidates, cursor_in_page, show_cursor);
|
||||
if (candidates.length != 0)
|
||||
m_candidate_area.show_all();
|
||||
else
|
||||
m_candidate_area.hide();
|
||||
|
||||
update();
|
||||
}
|
||||
|
||||
private void update() {
|
||||
if (m_candidate_area.get_visible() ||
|
||||
m_preedit_label.get_visible() ||
|
||||
m_aux_label.get_visible())
|
||||
m_toplevel.show();
|
||||
else
|
||||
m_toplevel.hide();
|
||||
|
||||
if (m_aux_label.get_visible() &&
|
||||
(m_candidate_area.get_visible() || m_preedit_label.get_visible()))
|
||||
m_hseparator.show();
|
||||
else
|
||||
m_hseparator.hide();
|
||||
}
|
||||
|
||||
public override void get_preferred_width(out int minimum_width, out int natural_width) {
|
||||
base.get_preferred_width(out minimum_width, out natural_width);
|
||||
m_toplevel.resize(1, 1);
|
||||
}
|
||||
|
||||
public override void get_preferred_height(out int minimum_width, out int natural_width) {
|
||||
base.get_preferred_height(out minimum_width, out natural_width);
|
||||
m_toplevel.resize(1, 1);
|
||||
}
|
||||
|
||||
private void create_ui() {
|
||||
m_preedit_label = new Gtk.Label(null);
|
||||
m_preedit_label.set_size_request(20, -1);
|
||||
m_preedit_label.set_alignment(0.0f, 0.5f);
|
||||
m_preedit_label.set_padding(8, 0);
|
||||
m_preedit_label.set_no_show_all(true);
|
||||
|
||||
m_aux_label = new Gtk.Label(null);
|
||||
m_aux_label.set_size_request(20, -1);
|
||||
m_aux_label.set_alignment(0.0f, 0.5f);
|
||||
m_aux_label.set_padding(8, 0);
|
||||
m_aux_label.set_no_show_all(true);
|
||||
|
||||
m_candidate_area = new CandidateArea(m_vertical);
|
||||
m_candidate_area.candidate_clicked.connect((w, i, b, s) => candidate_clicked(i, b, s));
|
||||
m_candidate_area.page_up.connect((c) => page_up());
|
||||
m_candidate_area.page_down.connect((c) => page_down());
|
||||
m_candidate_area.cursor_up.connect((c) => cursor_up());
|
||||
m_candidate_area.cursor_down.connect((c) => cursor_down());
|
||||
m_candidate_area.show();
|
||||
|
||||
m_hseparator = new HSeparator();
|
||||
|
||||
pack_all_widgets();
|
||||
}
|
||||
|
||||
private void pack_all_widgets() {
|
||||
m_vbox.pack_start(m_preedit_label, false, false, 4);
|
||||
m_vbox.pack_start(m_aux_label, false, false, 4);
|
||||
m_vbox.pack_start(m_hseparator, false, false, 0);
|
||||
m_vbox.pack_start(m_candidate_area, false, false, 0);
|
||||
}
|
||||
|
||||
public new void show() {
|
||||
m_toplevel.show_all();
|
||||
}
|
||||
|
||||
public new void hide() {
|
||||
m_toplevel.hide();
|
||||
}
|
||||
|
||||
private void move(int x, int y) {
|
||||
m_toplevel.move(x, y);
|
||||
}
|
||||
|
||||
private void adjust_window_position() {
|
||||
Gdk.Point cursor_right_bottom = {
|
||||
m_cursor_location.x + m_cursor_location.width,
|
||||
m_cursor_location.y + m_cursor_location.height
|
||||
};
|
||||
|
||||
Gtk.Allocation allocation;
|
||||
m_toplevel.get_allocation(out allocation);
|
||||
Gdk.Point window_right_bottom = {
|
||||
cursor_right_bottom.x + allocation.width,
|
||||
cursor_right_bottom.y + allocation.height
|
||||
};
|
||||
|
||||
Gdk.Window root = Gdk.get_default_root_window();
|
||||
int root_width = root.get_width();
|
||||
int root_height = root.get_height();
|
||||
|
||||
int x, y;
|
||||
if (window_right_bottom.x > root_width)
|
||||
x = root_width - allocation.width;
|
||||
else
|
||||
x = cursor_right_bottom.x;
|
||||
|
||||
if (window_right_bottom.y > root_height)
|
||||
y = m_cursor_location.y - allocation.height;
|
||||
else
|
||||
y = cursor_right_bottom.y;
|
||||
|
||||
move(x, y);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
/* vim:set et sts=4 sw=4:
|
||||
*
|
||||
* ibus - The Input Bus
|
||||
*
|
||||
* Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or(at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using Cairo;
|
||||
using Gdk;
|
||||
using Gtk;
|
||||
|
||||
class Handle : Gtk.EventBox {
|
||||
private bool m_move_begined;
|
||||
private Gdk.Rectangle m_workarea;
|
||||
private Gdk.Point m_press_pos;
|
||||
|
||||
public signal void move_begin();
|
||||
public signal void move_end();
|
||||
|
||||
public Handle() {
|
||||
set_size_request(6, -1);
|
||||
Gdk.EventMask mask = Gdk.EventMask.EXPOSURE_MASK |
|
||||
Gdk.EventMask.BUTTON_PRESS_MASK |
|
||||
Gdk.EventMask.BUTTON_RELEASE_MASK |
|
||||
Gdk.EventMask.BUTTON1_MOTION_MASK;
|
||||
set_events(mask);
|
||||
m_move_begined = false;
|
||||
}
|
||||
|
||||
public override void realize() {
|
||||
base.realize();
|
||||
// get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.FLEUR));
|
||||
}
|
||||
|
||||
public override bool button_press_event(Gdk.EventButton event) {
|
||||
if (event.button != 1)
|
||||
return false;
|
||||
m_workarea = {0, 0, int.MAX, int.MAX};
|
||||
do {
|
||||
Gdk.Window root = Gdk.get_default_root_window();
|
||||
Gdk.Atom property = Gdk.Atom.intern("_NET_CURRENT_DESKTOP", false);
|
||||
Gdk.Atom type = Gdk.Atom.intern("CARDINAL", false);
|
||||
Gdk.Atom actual_type;
|
||||
int format;
|
||||
uchar[] data;
|
||||
bool result;
|
||||
result = Gdk.property_get(root,
|
||||
property,
|
||||
type,
|
||||
0, long.MAX,
|
||||
0,
|
||||
out actual_type,
|
||||
out format,
|
||||
out data);
|
||||
if (!result || actual_type != type || format != 32 || data.length != 4)
|
||||
break;
|
||||
int index = data[0] |
|
||||
data[1] << 8 |
|
||||
data[2] << 16 |
|
||||
data[3] << 24;
|
||||
property = Gdk.Atom.intern("_NET_WORKAREA", false);
|
||||
type = Gdk.Atom.intern("CARDINAL", false);
|
||||
result = Gdk.property_get(root,
|
||||
property,
|
||||
type,
|
||||
0, long.MAX,
|
||||
0,
|
||||
out actual_type,
|
||||
out format,
|
||||
out data);
|
||||
if (!result || actual_type != type || format != 32 || data.length < (index + 1) * 16)
|
||||
break;
|
||||
int i = index * 4 * 4;
|
||||
m_workarea.x = data[i] |
|
||||
data[i + 1] << 8 |
|
||||
data[i + 2] << 16 |
|
||||
data[i + 3] << 24;
|
||||
i += 4;
|
||||
m_workarea.y = data[i] |
|
||||
data[i + 1] << 8 |
|
||||
data[i + 2] << 16 |
|
||||
data[i + 3] << 24;
|
||||
i += 4;
|
||||
m_workarea.width = data[i] |
|
||||
data[i + 1] << 8 |
|
||||
data[i + 2] << 16 |
|
||||
data[i + 3] << 24;
|
||||
i += 4;
|
||||
m_workarea.height = data[i] |
|
||||
data[i + 1] << 8 |
|
||||
data[i + 2] << 16 |
|
||||
data[i + 3] << 24;
|
||||
} while (false);
|
||||
m_move_begined = true;
|
||||
int x, y;
|
||||
Gtk.Window toplevel = (Gtk.Window)get_toplevel();
|
||||
toplevel.get_position(out x, out y);
|
||||
m_press_pos = { (int)event.x_root - x, (int)event.y_root - y };
|
||||
move_begin();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool button_release_event(Gdk.EventButton event) {
|
||||
if (event.button != 1)
|
||||
return false;
|
||||
m_move_begined = false;
|
||||
m_press_pos = { 0, 0 };
|
||||
get_window().set_cursor(new Gdk.Cursor(Gdk.CursorType.LEFT_PTR));
|
||||
move_end();
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool motion_notify_event(Gdk.EventMotion event) {
|
||||
if (!m_move_begined)
|
||||
return false;
|
||||
Gtk.Window toplevel = (Gtk.Window)get_toplevel();
|
||||
int x = (int)(event.x_root - m_press_pos.x);
|
||||
int y = (int)(event.y_root - m_press_pos.y);
|
||||
|
||||
if (x < m_workarea.x && x > m_workarea.x - 16)
|
||||
x = m_workarea.x;
|
||||
if (y < m_workarea.y && y > m_workarea.y - 16)
|
||||
y = m_workarea.y;
|
||||
int w, h;
|
||||
toplevel.get_size(out w, out h);
|
||||
if (x + w > m_workarea.x + m_workarea.width &&
|
||||
x + w < m_workarea.x + m_workarea.width + 16)
|
||||
x = m_workarea.x + m_workarea.width - w;
|
||||
if (y + h > m_workarea.y + m_workarea.height &&
|
||||
y + h < m_workarea.y + m_workarea.height + 16)
|
||||
y = m_workarea.y + m_workarea.height - w;
|
||||
toplevel.move(x, y);
|
||||
return true;
|
||||
}
|
||||
|
||||
public override bool draw(Cairo.Context cr) {
|
||||
if (Gtk.cairo_should_draw_window(cr, get_window())) {
|
||||
Gtk.StyleContext context = get_style_context();
|
||||
Gtk.Allocation allocation;
|
||||
get_allocation(out allocation);
|
||||
Gtk.render_handle(context, cr,
|
||||
allocation.x, allocation.y + (allocation.height - 40) / 2, allocation.width, 40.0);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/* vim:set et sts=4 sw=4:
|
||||
*
|
||||
* ibus - The Input Bus
|
||||
*
|
||||
* Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or(at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using Gdk;
|
||||
using GLib;
|
||||
using Gtk;
|
||||
|
||||
class IconWidget: Gtk.Image {
|
||||
public IconWidget(string icon, int size) {
|
||||
Gdk.Pixbuf pixbuf = null;
|
||||
try {
|
||||
if (icon[0] == '/') {
|
||||
pixbuf = new Gdk.Pixbuf.from_file(icon);
|
||||
} else {
|
||||
var theme = Gtk.IconTheme.get_default();
|
||||
pixbuf = theme.load_icon(icon, size, 0);
|
||||
}
|
||||
} catch (GLib.Error e) {
|
||||
try {
|
||||
var theme = Gtk.IconTheme.get_default();
|
||||
pixbuf = theme.load_icon(Gtk.Stock.MISSING_IMAGE, size, 0);
|
||||
} catch (GLib.Error e) {}
|
||||
}
|
||||
|
||||
if (pixbuf == null)
|
||||
return;
|
||||
float width = (float)pixbuf.get_width();
|
||||
float height = (float)pixbuf.get_height();
|
||||
float scale = size / (width > height ? width : height);
|
||||
width *= scale;
|
||||
height *= scale;
|
||||
|
||||
pixbuf = pixbuf.scale_simple((int)width, (int)height, Gdk.InterpType.BILINEAR);
|
||||
set_from_pixbuf(pixbuf);
|
||||
show();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,186 @@
|
|||
/*
|
||||
valac --pkg gtk+-2.0 --pkg x11 --pkg gdk-x11-2.0 --pkg gee-1.0 keybinding-manager.vala
|
||||
*/
|
||||
|
||||
/**
|
||||
* This class is in charge to grab keybindings on the X11 display
|
||||
* and filter X11-events and passing on such events to the registed
|
||||
* handler methods.
|
||||
*
|
||||
* @author Oliver Sauder <os@esite.ch>
|
||||
*/
|
||||
|
||||
using Gdk;
|
||||
using GLib;
|
||||
using Gtk;
|
||||
using X;
|
||||
|
||||
class KeybindingManager : GLib.Object
|
||||
{
|
||||
/**
|
||||
* list of binded keybindings
|
||||
*/
|
||||
private GLib.List<Keybinding> bindings = new GLib.List<Keybinding>();
|
||||
|
||||
/**
|
||||
* locked modifiers used to grab all keys whatever lock key
|
||||
* is pressed.
|
||||
*/
|
||||
private static uint[] lock_modifiers = {
|
||||
0,
|
||||
Gdk.ModifierType.MOD2_MASK, // NUM_LOCK
|
||||
Gdk.ModifierType.LOCK_MASK, // CAPS_LOCK
|
||||
Gdk.ModifierType.MOD5_MASK, // SCROLL_LOCK
|
||||
Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.LOCK_MASK,
|
||||
Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.MOD5_MASK,
|
||||
Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK,
|
||||
Gdk.ModifierType.MOD2_MASK|Gdk.ModifierType.LOCK_MASK|Gdk.ModifierType.MOD5_MASK
|
||||
};
|
||||
|
||||
/**
|
||||
* Helper class to store keybinding
|
||||
*/
|
||||
private class Keybinding
|
||||
{
|
||||
public Keybinding(string accelerator, int keycode,
|
||||
Gdk.ModifierType modifiers, KeybindingHandlerFunc handler)
|
||||
{
|
||||
this.accelerator = accelerator;
|
||||
this.keycode = keycode;
|
||||
this.modifiers = modifiers;
|
||||
this.handler = handler;
|
||||
}
|
||||
|
||||
public string accelerator { get; set; }
|
||||
public int keycode { get; set; }
|
||||
public Gdk.ModifierType modifiers { get; set; }
|
||||
public unowned KeybindingHandlerFunc handler { get; set; }
|
||||
}
|
||||
|
||||
/**
|
||||
* Keybinding func needed to bind key to handler
|
||||
*
|
||||
* @param event passing on gdk event
|
||||
*/
|
||||
public delegate void KeybindingHandlerFunc(Gdk.Event event);
|
||||
|
||||
public KeybindingManager()
|
||||
{
|
||||
// init filter to retrieve X.Events
|
||||
Gdk.Window rootwin = Gdk.get_default_root_window();
|
||||
if(rootwin != null) {
|
||||
rootwin.add_filter(event_filter);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Bind accelerator to given handler
|
||||
*
|
||||
* @param accelerator accelerator parsable by Gtk.accelerator_parse
|
||||
* @param handler handler called when given accelerator is pressed
|
||||
*/
|
||||
public void bind(string accelerator, KeybindingHandlerFunc handler)
|
||||
{
|
||||
debug("Binding key " + accelerator);
|
||||
|
||||
// convert accelerator
|
||||
uint keysym;
|
||||
Gdk.ModifierType modifiers;
|
||||
Gtk.accelerator_parse(accelerator, out keysym, out modifiers);
|
||||
|
||||
unowned X.Display display = Gdk.x11_get_default_xdisplay();
|
||||
|
||||
int keycode = display.keysym_to_keycode(keysym);
|
||||
|
||||
if(keycode != 0) {
|
||||
// trap XErrors to avoid closing of application
|
||||
// even when grabing of key fails
|
||||
Gdk.error_trap_push();
|
||||
|
||||
// grab key finally
|
||||
// also grab all keys which are combined with a lock key such NumLock
|
||||
foreach(uint lock_modifier in lock_modifiers) {
|
||||
display.grab_key(keycode, modifiers|lock_modifier, Gdk.x11_get_default_root_xwindow(), false,
|
||||
X.GrabMode.Async, X.GrabMode.Async);
|
||||
}
|
||||
|
||||
// wait until all X request have been processed
|
||||
Gdk.flush();
|
||||
|
||||
// store binding
|
||||
Keybinding binding = new Keybinding(accelerator, keycode, modifiers, handler);
|
||||
bindings.append(binding);
|
||||
|
||||
debug("Successfully binded key " + accelerator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unbind given accelerator.
|
||||
*
|
||||
* @param accelerator accelerator parsable by Gtk.accelerator_parse
|
||||
*/
|
||||
public void unbind(string accelerator)
|
||||
{
|
||||
debug("Unbinding key " + accelerator);
|
||||
|
||||
unowned X.Display display = Gdk.x11_get_default_xdisplay();
|
||||
|
||||
// unbind all keys with given accelerator
|
||||
GLib.List<Keybinding> remove_bindings = new GLib.List<Keybinding>();
|
||||
foreach(Keybinding binding in bindings) {
|
||||
if(str_equal(accelerator, binding.accelerator)) {
|
||||
foreach(uint lock_modifier in lock_modifiers) {
|
||||
display.ungrab_key(binding.keycode, binding.modifiers | lock_modifier, Gdk.x11_get_default_root_xwindow());
|
||||
}
|
||||
remove_bindings.append(binding);
|
||||
}
|
||||
}
|
||||
|
||||
// remove unbinded keys
|
||||
foreach(Keybinding binding in remove_bindings)
|
||||
bindings.remove(binding);
|
||||
}
|
||||
|
||||
/**
|
||||
* Event filter method needed to fetch X.Events
|
||||
*/
|
||||
public Gdk.FilterReturn event_filter(Gdk.XEvent gdk_xevent, Gdk.Event gdk_event)
|
||||
{
|
||||
Gdk.FilterReturn filter_return = Gdk.FilterReturn.CONTINUE;
|
||||
|
||||
void* pointer = &gdk_xevent;
|
||||
X.Event* xevent = (X.Event*) pointer;
|
||||
|
||||
if(xevent->type == X.EventType.KeyPress) {
|
||||
foreach(Keybinding binding in bindings) {
|
||||
// remove NumLock, CapsLock and ScrollLock from key state
|
||||
uint event_mods = xevent.xkey.state & ~ (lock_modifiers[7]);
|
||||
if(xevent->xkey.keycode == binding.keycode && event_mods == binding.modifiers) {
|
||||
// call all handlers with pressed key and modifiers
|
||||
binding.handler(gdk_event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return filter_return;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
public static int main (string[] args)
|
||||
{
|
||||
Gtk.init (ref args);
|
||||
|
||||
KeybindingManager manager = new KeybindingManager();
|
||||
manager.bind("<Ctrl><Alt>V", test);
|
||||
|
||||
Gtk.main ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
private static void test()
|
||||
{
|
||||
debug("hotkey pressed");
|
||||
}
|
||||
*/
|
|
@ -0,0 +1,168 @@
|
|||
/* vim:set et sts=4 sw=4:
|
||||
*
|
||||
* ibus - The Input Bus
|
||||
*
|
||||
* Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or(at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using IBus;
|
||||
using GLib;
|
||||
using Gtk;
|
||||
|
||||
class Panel : IBus.PanelService {
|
||||
private IBus.Bus m_bus;
|
||||
private IBus.Config m_config;
|
||||
// private IBus.PanelService m_service;
|
||||
private Gtk.StatusIcon m_status_icon;
|
||||
private Gtk.Menu m_ime_menu;
|
||||
private IBus.EngineDesc[] m_engines;
|
||||
private CandidatePanel m_candidate_panel;
|
||||
private KeybindingManager m_keybinding_manager;
|
||||
|
||||
public Panel(IBus.Bus bus) {
|
||||
assert(bus.is_connected());
|
||||
// Chain up base class constructor
|
||||
GLib.Object(connection : bus.get_connection(),
|
||||
object_path : "/org/freedesktop/IBus/Panel");
|
||||
|
||||
m_bus = bus;
|
||||
|
||||
m_config = bus.get_config();
|
||||
|
||||
// init ui
|
||||
m_status_icon = new Gtk.StatusIcon();
|
||||
m_status_icon.set_name("ibus-ui-gtk");
|
||||
m_status_icon.set_title("IBus Panel");
|
||||
m_status_icon.popup_menu.connect(status_icon_popup_menu);
|
||||
m_status_icon.activate.connect(status_icon_activate);
|
||||
m_status_icon.set_from_icon_name("ibus-keyboard");
|
||||
|
||||
m_candidate_panel = new CandidatePanel();
|
||||
|
||||
m_candidate_panel.hide();
|
||||
m_candidate_panel.show();
|
||||
|
||||
update_engines();
|
||||
|
||||
m_keybinding_manager = new KeybindingManager();
|
||||
m_keybinding_manager.bind("<Control>space", (d) => {
|
||||
// Switch to next engine
|
||||
IBus.EngineDesc engine = m_bus.get_global_engine();
|
||||
int i;
|
||||
for (i = 0; i < m_engines.length && engine != null; i++) {
|
||||
if (m_engines[i].get_name() == engine.get_name())
|
||||
break;
|
||||
}
|
||||
i ++;
|
||||
if (i >= m_engines.length) i = 0;
|
||||
if (i >= m_engines.length)
|
||||
return;
|
||||
m_bus.set_global_engine(m_engines[i].get_name());
|
||||
});
|
||||
}
|
||||
|
||||
private void update_engines() {
|
||||
Variant variant = m_config.get_value("general", "preload_engines");
|
||||
if (variant != null)
|
||||
m_engines = m_bus.get_engines_by_names(variant.get_strv());
|
||||
else
|
||||
m_engines = m_bus.get_engines_by_names({"xkb:us:eng", "pinyin"});
|
||||
m_ime_menu = null;
|
||||
}
|
||||
|
||||
private void status_icon_popup_menu(Gtk.StatusIcon status_icon,
|
||||
uint button,
|
||||
uint activate_time) {
|
||||
debug("popup-menu %u %u", button, activate_time);
|
||||
}
|
||||
|
||||
private void status_icon_activate(Gtk.StatusIcon status_icon) {
|
||||
if (m_ime_menu == null) {
|
||||
int width, height;
|
||||
Gtk.icon_size_lookup(Gtk.IconSize.MENU, out width, out height);
|
||||
m_ime_menu = new Gtk.Menu();
|
||||
foreach (var engine in m_engines) {
|
||||
var lang = engine.get_language();
|
||||
var name = engine.get_name();
|
||||
var item = new Gtk.ImageMenuItem.with_label(lang + " - " + name);
|
||||
if (engine.get_icon() != "") {
|
||||
var icon = new IconWidget(engine.get_icon(), width);
|
||||
item.set_image(icon);
|
||||
}
|
||||
// Make a copy of engine to workaround a bug in vala.
|
||||
// https://bugzilla.gnome.org/show_bug.cgi?id=628336
|
||||
var e = engine;
|
||||
item.activate.connect((i) => {
|
||||
m_bus.set_global_engine(e.get_name());
|
||||
});
|
||||
m_ime_menu.add(item);
|
||||
}
|
||||
m_ime_menu.show_all();
|
||||
m_ime_menu.set_take_focus(false);
|
||||
}
|
||||
m_ime_menu.popup(null,
|
||||
null,
|
||||
m_status_icon.position_menu,
|
||||
0,
|
||||
Gtk.get_current_event_time());
|
||||
}
|
||||
|
||||
public override void set_cursor_location(int x, int y, int width, int height) {
|
||||
m_candidate_panel.set_cursor_location(x, y, width, height);
|
||||
}
|
||||
|
||||
public override void focus_in(string input_context_path) {
|
||||
debug("focus_in ic=%s", input_context_path);
|
||||
}
|
||||
|
||||
public override void focus_out(string input_context_path) {
|
||||
debug("focus_out ic=%s", input_context_path);
|
||||
}
|
||||
|
||||
public override void update_preedit_text(IBus.Text text,
|
||||
uint cursor_pos,
|
||||
bool visible) {
|
||||
if (visible)
|
||||
m_candidate_panel.set_preedit_text(text, cursor_pos);
|
||||
else
|
||||
m_candidate_panel.set_preedit_text(null, 0);
|
||||
}
|
||||
|
||||
public override void hide_preedit_text() {
|
||||
m_candidate_panel.set_preedit_text(null, 0);
|
||||
}
|
||||
|
||||
public override void update_auxiliary_text(IBus.Text text,
|
||||
bool visible) {
|
||||
m_candidate_panel.set_auxiliary_text(visible ? text : null);
|
||||
}
|
||||
|
||||
public override void hide_auxiliary_text() {
|
||||
m_candidate_panel.set_auxiliary_text(null);
|
||||
}
|
||||
|
||||
public override void update_lookup_table(IBus.LookupTable table,
|
||||
bool visible) {
|
||||
m_candidate_panel.set_lookup_table(visible ? table : null);
|
||||
}
|
||||
|
||||
public override void hide_lookup_table() {
|
||||
m_candidate_panel.set_lookup_table(null);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
/* vim:set et sts=4 sw=4:
|
||||
*
|
||||
* ibus - The Input Bus
|
||||
*
|
||||
* Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or(at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using IBus;
|
||||
using Pango;
|
||||
|
||||
Pango.AttrList get_pango_attr_list_from_ibus_text(IBus.Text text) {
|
||||
Pango.AttrList pango_attrs = new Pango.AttrList();
|
||||
unowned IBus.AttrList attrs = text.get_attributes();
|
||||
if (attrs == null)
|
||||
return pango_attrs;
|
||||
|
||||
unowned string str = text.get_text();
|
||||
long nchars = str.char_count();
|
||||
long[] offsets = new long[nchars + 1];
|
||||
for (int i = 0; i <= nchars; i++)
|
||||
offsets[i] = str.index_of_nth_char(i);
|
||||
|
||||
IBus.Attribute attr;
|
||||
int i = 0;
|
||||
while(true) {
|
||||
attr = attrs.get(i++);
|
||||
if (attr == null)
|
||||
break;
|
||||
long start_index = attr.start_index;
|
||||
if (start_index <= 0) start_index = 0;
|
||||
start_index = start_index <= nchars ? offsets[start_index] : offsets[-1];
|
||||
|
||||
long end_index = attr.end_index;
|
||||
if (end_index <= 0) end_index = 0;
|
||||
end_index = end_index <= nchars ? offsets[end_index] : offsets[-1];
|
||||
|
||||
Pango.Attribute pango_attr = null;
|
||||
switch(attr.type) {
|
||||
case IBus.AttrType.FOREGROUND:
|
||||
{
|
||||
uint16 r = (uint16)(attr.value & 0x00ff0000) >> 8;
|
||||
uint16 g = (uint16)(attr.value & 0x0000ff00);
|
||||
uint16 b = (uint16)(attr.value & 0x000000ff) << 8;
|
||||
pango_attr = Pango.attr_foreground_new(r, g, b);
|
||||
break;
|
||||
}
|
||||
case IBus.AttrType.BACKGROUND:
|
||||
{
|
||||
uint16 r = (uint16)(attr.value & 0x00ff0000) >> 8;
|
||||
uint16 g = (uint16)(attr.value & 0x0000ff00);
|
||||
uint16 b = (uint16)(attr.value & 0x000000ff) << 8;
|
||||
pango_attr = Pango.attr_background_new(r, g, b);
|
||||
break;
|
||||
}
|
||||
case IBus.AttrType.UNDERLINE:
|
||||
{
|
||||
pango_attr = Pango.attr_underline_new((Pango.Underline)attr.value);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
pango_attr.start_index = (uint)start_index;
|
||||
pango_attr.end_index = (uint)end_index;
|
||||
// Transfer the ownership to pango_attrs
|
||||
pango_attrs.insert((owned)pango_attr);
|
||||
}
|
||||
return pango_attrs;
|
||||
}
|
|
@ -0,0 +1,39 @@
|
|||
/* vim:set et sts=4 sw=4:
|
||||
*
|
||||
* ibus - The Input Bus
|
||||
*
|
||||
* Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or(at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this program; if not, write to the
|
||||
* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
|
||||
* Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
using Gtk;
|
||||
|
||||
class HSeparator : Gtk.HSeparator {
|
||||
public HSeparator() {
|
||||
GLib.Object(
|
||||
margin : 2
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class VSeparator : Gtk.VSeparator {
|
||||
public VSeparator() {
|
||||
GLib.Object(
|
||||
margin : 2
|
||||
);
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче