Remove enable status of input context and hotkey logic in ibus-daemon

This commit is contained in:
Peng Huang 2011-08-16 07:26:42 -04:00
Родитель 60587bf804
Коммит 53d33ec4e6
31 изменённых файлов: 1547 добавлений и 1423 удалений

Просмотреть файл

@ -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

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -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)

84
ui/gtk3/Makefile.am Normal file
Просмотреть файл

@ -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

109
ui/gtk3/application.vala Normal file
Просмотреть файл

@ -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();
}
}

252
ui/gtk3/candidatearea.vala Normal file
Просмотреть файл

@ -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);
}
}
}

238
ui/gtk3/candidatepanel.vala Normal file
Просмотреть файл

@ -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);
}
}

161
ui/gtk3/handle.vala Normal file
Просмотреть файл

@ -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;
}
}

56
ui/gtk3/iconwidget.vala Normal file
Просмотреть файл

@ -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");
}
*/

168
ui/gtk3/panel.vala Normal file
Просмотреть файл

@ -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);
}
}

84
ui/gtk3/pango.vala Normal file
Просмотреть файл

@ -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;
}

39
ui/gtk3/separator.vala Normal file
Просмотреть файл

@ -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
);
}
}