aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--configure.ac4
-rw-r--r--data/Makefile.am3
-rw-r--r--debian/control1
-rw-r--r--deps/Fcitx-1.0.metadata7
-rw-r--r--deps/README47
-rw-r--r--deps/fcitx.vapi97
-rw-r--r--lib/Makefile.am6
-rw-r--r--lib/indicator-menu.vala7
-rw-r--r--lib/main.vala45
-rw-r--r--lib/source.vala136
-rw-r--r--tests/indicator-keyboard-test.in1
11 files changed, 290 insertions, 64 deletions
diff --git a/configure.ac b/configure.ac
index 5c09f8fc..dc90e15d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -70,6 +70,10 @@ PKG_CHECK_MODULES([IBUS], [ibus-1.0])
AC_SUBST([IBUS_CFLAGS])
AC_SUBST([IBUS_LIBS])
+PKG_CHECK_MODULES([FCITX_GCLIENT], [fcitx-gclient])
+AC_SUBST([FCITX_GCLIENT_CFLAGS])
+AC_SUBST([FCITX_GCLIENT_LIBS])
+
PKG_CHECK_MODULES([ACCOUNTSSERVICE], [accountsservice])
AC_SUBST([ACCOUNTSSERVICE_CFLAGS])
AC_SUBST([ACCOUNTSSERVICE_LIBS])
diff --git a/data/Makefile.am b/data/Makefile.am
index 06ed4662..bcb22cde 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -9,8 +9,7 @@ noinst_PROGRAMS = indicator-keyboard-icon-generator
AM_CFLAGS = -w -DGNOME_DESKTOP_USE_UNSTABLE_API
AM_LDFLAGS = -lm
-AM_VALAFLAGS = --enable-experimental-non-null \
- --metadatadir $(top_srcdir)/deps \
+AM_VALAFLAGS = --metadatadir $(top_srcdir)/deps \
--vapidir $(top_srcdir)/deps
indicator_keyboard_icon_generator_SOURCES = main.vala \
diff --git a/debian/control b/debian/control
index 585af9c5..a359f3d9 100644
--- a/debian/control
+++ b/debian/control
@@ -7,6 +7,7 @@ Build-Depends: debhelper (>= 9.0.0),
dh-autoreconf,
dh-translations,
dbus,
+ fcitx-libs-dev (>= 1:4.2.8.3),
libaccountsservice-dev,
libgee-dev,
libgirepository1.0-dev,
diff --git a/deps/Fcitx-1.0.metadata b/deps/Fcitx-1.0.metadata
new file mode 100644
index 00000000..81c20f3c
--- /dev/null
+++ b/deps/Fcitx-1.0.metadata
@@ -0,0 +1,7 @@
+Client cheader_filename="fcitx-gclient/fcitxclient.h"
+Connection cheader_filename="fcitx-gclient/fcitxconnection.h"
+IMItem cheader_filename="fcitx-gclient/fcitxinputmethod.h"
+InputMethod cheader_filename="fcitx-gclient/fcitxinputmethod.h"
+Kbd cheader_filename="fcitx-gclient/fcitxkbd.h"
+LayoutItem cheader_filename="fcitx-gclient/fcitxkbd.h"
+PreeditItem cheader_filename="fcitx-gclient/fcitxclient.h"
diff --git a/deps/README b/deps/README
new file mode 100644
index 00000000..c3666140
--- /dev/null
+++ b/deps/README
@@ -0,0 +1,47 @@
+To generate fontconfig.vapi:
+
+vapigen --library fontconfig /path/to/fontconfig-2.0.gir
+
+To generate freetype2.vapi:
+
+vapigen --library freetype2 /path/to/freetype2-2.0.gir
+
+To generate pangoft2.vapi:
+
+vapigen --library pangoft2 /path/to/PangoFT2-1.0.gir
+
+To generate gnome-desktop-3.0.vapi:
+
+vapigen --pkg gio-2.0 --pkg gtk+-3.0 --library gnome-desktop-3.0 /path/to/GnomeDesktop-3.0.gir
+
+To generate gnome-desktop-3.0.vapi docs:
+
+valadoc --vapidir /path/to/vapi/dir --pkg gdk-3.0 -o gnome-desktop-3.0 gnome-desktop-3.0.vapi
+
+To generate libxklavier.vapi:
+
+vapigen --metadatadir . --pkg x11 --library libxklavier /path/to/Xkl-1.0.gir
+
+To generate libxklavier.vapi docs:
+
+valadoc --vapidir /path/to/vapi/dir --pkg x11 -o libxklavier libxklavier.vapi
+
+To generate libgnomekbd.vapi:
+
+vapigen --metadatadir . --pkg gtk+-3.0 --library libgnomekbd /path/to/Gkbd-3.0.gir
+
+To generate libgnomekbd.vapi docs:
+
+valadoc --metadatadir . --vapidir /path/to/vapi/dir --pkg gtk+-3.0 --pkg Xkl-1.0 -o libgnomekbd libgnomekbd.vapi
+
+To generate ibus-1.0.vapi docs:
+
+valadoc --vapidir /path/to/vapi/dir -o ibus-1.0 /path/to/ibus-1.0.vapi
+
+To generate fcitx.vapi:
+
+vapigen --metadatadir . --pkg gio-2.0 --library fcitx /path/to/Fcitx-1.0.gir
+
+To generate libbamf3.vapi:
+
+vapigen --library libbamf3 /path/to/Bamf-3.gir
diff --git a/deps/fcitx.vapi b/deps/fcitx.vapi
new file mode 100644
index 00000000..fbf5e925
--- /dev/null
+++ b/deps/fcitx.vapi
@@ -0,0 +1,97 @@
+/* fcitx.vapi generated by vapigen, do not modify. */
+
+[CCode (cprefix = "Fcitx", gir_namespace = "Fcitx", gir_version = "1.0", lower_case_cprefix = "fcitx_")]
+namespace Fcitx {
+ [CCode (cheader_filename = "fcitx-gclient/fcitxclient.h", type_id = "fcitx_client_get_type ()")]
+ public class Client : GLib.Object {
+ [CCode (has_construct_function = false)]
+ public Client ();
+ public void close_ic ();
+ public void enable_ic ();
+ public void focus_in ();
+ public void focus_out ();
+ public bool is_valid ();
+ [Deprecated]
+ public async int process_key (uint32 keyval, uint32 keycode, uint32 state, int type, uint32 t);
+ public async int process_key_async (uint32 keyval, uint32 keycode, uint32 state, int type, uint32 t, int timeout_msec, GLib.Cancellable? cancellable);
+ public int process_key_sync (uint32 keyval, uint32 keycode, uint32 state, int type, uint32 t);
+ public void reset ();
+ public void set_capacity (uint flags);
+ public void set_cursor_rect (int x, int y, int w, int h);
+ [Deprecated]
+ public void set_cusor_rect (int x, int y, int w, int h);
+ public void set_surrounding_text (string? text, uint cursor, uint anchor);
+ public signal void close_im ();
+ public signal void commit_string (string string);
+ public signal void connected ();
+ public signal void delete_surrounding_text (int cursor, uint len);
+ public signal void disconnected ();
+ public signal void enable_im ();
+ public signal void forward_key (uint keyval, int state, int type);
+ public signal void update_client_side_ui (string auxup, string auxdown, string preedit, string candidateword, string imname, int cursor_pos);
+ public signal void update_formatted_preedit (GLib.GenericArray<Fcitx.PreeditItem> preedit, int cursor);
+ }
+ [CCode (cheader_filename = "fcitx-gclient/fcitxconnection.h", type_id = "fcitx_connection_get_type ()")]
+ public class Connection : GLib.Object {
+ [CCode (has_construct_function = false)]
+ public Connection ();
+ public unowned GLib.DBusConnection get_g_dbus_connection ();
+ public bool is_valid ();
+ public signal void connected ();
+ public signal void disconnected ();
+ }
+ [CCode (cheader_filename = "fcitx-gclient/fcitxinputmethod.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "fcitx_im_item_get_type ()")]
+ [Compact]
+ public class IMItem {
+ public bool enable;
+ public weak string langcode;
+ public weak string name;
+ public weak string unique_name;
+ [CCode (has_construct_function = false)]
+ public IMItem (string name, string unique_name, string langcode, bool enable);
+ }
+ [CCode (cheader_filename = "fcitx-gclient/fcitxinputmethod.h", type_id = "fcitx_input_method_get_type ()")]
+ public class InputMethod : GLib.DBusProxy, GLib.AsyncInitable, GLib.DBusInterface, GLib.Initable {
+ [CCode (has_construct_function = false)]
+ public InputMethod (GLib.BusType bus_type, GLib.DBusProxyFlags flags, int display_number, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public void activate ();
+ public void configure ();
+ public void configure_addon (string addon);
+ public void configure_im (string imname);
+ public void exit ();
+ public string get_current_im ();
+ public int get_current_state ();
+ public string get_current_ui ();
+ public string get_im_addon (string imname);
+ public GLib.GenericArray<Fcitx.IMItem> get_imlist_nofree ();
+ public void inactivate ();
+ public void reload_config ();
+ public void restart ();
+ public void set_current_im (string imname);
+ public void set_imlist (GLib.GenericArray<Fcitx.IMItem> array);
+ public void toggle ();
+ public signal void imlist_changed ();
+ }
+ [CCode (cheader_filename = "fcitx-gclient/fcitxkbd.h", type_id = "fcitx_kbd_get_type ()")]
+ public class Kbd : GLib.DBusProxy, GLib.AsyncInitable, GLib.DBusInterface, GLib.Initable {
+ [CCode (has_construct_function = false)]
+ public Kbd (GLib.BusType bus_type, GLib.DBusProxyFlags flags, int display_number, GLib.Cancellable? cancellable = null) throws GLib.Error;
+ public void get_layout_for_im (string imname, out string layout, out string variant);
+ public GLib.GenericArray<Fcitx.LayoutItem> get_layouts_nofree ();
+ public void set_default_layout (string layout, string variant);
+ public void set_layout_for_im (string imname, string layout, string variant);
+ }
+ [CCode (cheader_filename = "fcitx-gclient/fcitxkbd.h", copy_function = "g_boxed_copy", free_function = "g_boxed_free", type_id = "fcitx_layout_item_get_type ()")]
+ [Compact]
+ public class LayoutItem {
+ public weak string langcode;
+ public weak string layout;
+ public weak string name;
+ public weak string variant;
+ }
+ [CCode (cheader_filename = "fcitx-gclient/fcitxclient.h", has_type_id = false)]
+ public struct PreeditItem {
+ public weak global::string string;
+ public int32 type;
+ }
+}
diff --git a/lib/Makefile.am b/lib/Makefile.am
index c57725c1..6543ccd4 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -2,8 +2,7 @@ pkglibexec_PROGRAMS = indicator-keyboard-service
AM_CFLAGS = -w -DGNOME_DESKTOP_USE_UNSTABLE_API
AM_LDFLAGS = -lm
-AM_VALAFLAGS = --enable-experimental-non-null \
- --metadatadir $(top_srcdir)/deps \
+AM_VALAFLAGS = --metadatadir $(top_srcdir)/deps \
--vapidir $(top_srcdir)/deps
indicator_keyboard_service_SOURCES = main.vala \
@@ -26,6 +25,7 @@ indicator_keyboard_service_VALAFLAGS = $(AM_VALAFLAGS) \
--pkg Xkl-1.0 \
--pkg Gkbd-3.0 \
--pkg ibus-1.0 \
+ --pkg fcitx \
--pkg accountsservice \
--pkg liblightdm-gobject-1
indicator_keyboard_service_CFLAGS = $(AM_CFLAGS) \
@@ -36,6 +36,7 @@ indicator_keyboard_service_CFLAGS = $(AM_CFLAGS) \
$(LIBXKLAVIER_CFLAGS) \
$(LIBGNOMEKBD_CFLAGS) \
$(IBUS_CFLAGS) \
+ $(FCITX_GCLIENT_CFLAGS) \
$(ACCOUNTSSERVICE_CFLAGS) \
$(LIGHTDM_CFLAGS) \
$(COVERAGE_CFLAGS)
@@ -47,6 +48,7 @@ indicator_keyboard_service_LDFLAGS = $(AM_LDFLAGS) \
$(LIBXKLAVIER_LIBS) \
$(LIBGNOMEKBD_LIBS) \
$(IBUS_LIBS) \
+ $(FCITX_GCLIENT_LIBS) \
$(ACCOUNTSSERVICE_LIBS) \
$(LIGHTDM_LIBS) \
$(COVERAGE_LDFLAGS)
diff --git a/lib/indicator-menu.vala b/lib/indicator-menu.vala
index 8e5661e2..115adc5f 100644
--- a/lib/indicator-menu.vala
+++ b/lib/indicator-menu.vala
@@ -22,7 +22,8 @@ public class Indicator.Keyboard.IndicatorMenu : MenuModel {
NONE = 0x0,
DCONF = 0x1,
IBUS = 0x2,
- SETTINGS = 0x4
+ FCITX = 0x4,
+ SETTINGS = 0x8
}
private Options options;
@@ -76,7 +77,9 @@ public class Indicator.Keyboard.IndicatorMenu : MenuModel {
sources_section.remove_all ();
for (var i = 0; i < sources.length; i++) {
- if (!sources[i].is_ibus || (options & Options.IBUS) != Options.NONE) {
+ if (sources[i].is_xkb ||
+ (sources[i].is_ibus && (options & Options.IBUS) != Options.NONE) ||
+ (sources[i].is_fcitx && (options & Options.FCITX) != Options.NONE)) {
string action;
if ((options & Options.DCONF) != Options.NONE) {
diff --git a/lib/main.vala b/lib/main.vala
index 1cb3896c..d2ea8c79 100644
--- a/lib/main.vala
+++ b/lib/main.vala
@@ -146,6 +146,18 @@ public class Indicator.Keyboard.Service : Object {
}
[DBus (visible = false)]
+ private static bool is_ibus_active () {
+ var module = Environment.get_variable ("GTK_IM_MODULE");
+ return module != null && (!) module == "ibus";
+ }
+
+ [DBus (visible = false)]
+ private static bool is_fcitx_active () {
+ var module = Environment.get_variable ("GTK_IM_MODULE");
+ return module != null && (!) module == "fcitx";
+ }
+
+ [DBus (visible = false)]
private IBus.Bus get_ibus () {
if (ibus == null) {
IBus.init ();
@@ -788,30 +800,30 @@ public class Indicator.Keyboard.Service : Object {
private void handle_scroll_wheel_when_locked (Variant? parameter) {
if (parameter != null) {
var sources = get_sources ();
- var non_ibus_length = 0;
+ var xkb_length = 0;
- /* Figure out how many non-IBus sources we have. */
+ /* Figure out how many Xkb sources we have. */
foreach (var source in sources) {
- if (!source.is_ibus) {
- non_ibus_length++;
+ if (source.is_xkb) {
+ xkb_length++;
}
}
- if (non_ibus_length > 1) {
+ if (xkb_length > 1) {
var active_action = get_active_action ();
var active = active_action.get_state ().get_uint32 ();
- var offset = -((!) parameter).get_int32 () % non_ibus_length;
+ var offset = -((!) parameter).get_int32 () % xkb_length;
- /* Make offset positive modulo non_ibus_length. */
+ /* Make offset positive modulo xkb_length. */
if (offset < 0) {
- offset += non_ibus_length;
+ offset += xkb_length;
}
- /* We need to cycle through non-IBus sources only. */
+ /* We need to cycle through Xkb sources only. */
while (offset > 0) {
do {
active = (active + 1) % sources.length;
- } while (sources[active].is_ibus);
+ } while (!sources[active].is_xkb);
offset--;
}
@@ -882,9 +894,16 @@ public class Indicator.Keyboard.Service : Object {
public IndicatorMenu get_desktop_menu () {
if (desktop_menu == null) {
var options = IndicatorMenu.Options.DCONF
- | IndicatorMenu.Options.IBUS
| IndicatorMenu.Options.SETTINGS;
+ if (is_ibus_active ()) {
+ options |= IndicatorMenu.Options.IBUS;
+ }
+
+ if (is_fcitx_active ()) {
+ options |= IndicatorMenu.Options.FCITX;
+ }
+
desktop_menu = new IndicatorMenu (get_action_group (), options);
((!) desktop_menu).set_sources (get_sources ());
((!) desktop_menu).activate.connect ((property, state) => {
@@ -1040,9 +1059,9 @@ public class Indicator.Keyboard.Service : Object {
if (sources.length > 0) {
var current = source_settings.get_uint ("current");
- if (current < sources.length && sources[current].is_ibus) {
+ if (current < sources.length && !sources[current].is_xkb) {
for (var i = 0; i < sources.length; i++) {
- if (!sources[i].is_ibus) {
+ if (sources[i].is_xkb) {
get_active_action ().change_state (new Variant.uint32 (i));
break;
}
diff --git a/lib/source.vala b/lib/source.vala
index 5fe7157d..2777f521 100644
--- a/lib/source.vala
+++ b/lib/source.vala
@@ -19,10 +19,12 @@
public class Indicator.Keyboard.Source : Object {
private static Gnome.XkbInfo? xkb_info;
- private static IBus.Bus? bus;
+ private static IBus.Bus? ibus_bus;
+ private static Fcitx.InputMethod? fcitx_proxy;
private string? xkb;
private string? ibus;
+ private string? fcitx;
private string? _name;
private string? _short_name;
@@ -77,6 +79,10 @@ public class Indicator.Keyboard.Source : Object {
get { return ibus != null; }
}
+ public bool is_fcitx {
+ get { return fcitx != null; }
+ }
+
public Source (Variant variant, bool use_gtk = false) {
Object (use_gtk: use_gtk);
@@ -90,6 +96,8 @@ public class Indicator.Keyboard.Source : Object {
xkb = name;
} else if (type == "ibus") {
ibus = name;
+ } else if (type == "fcitx") {
+ fcitx = name;
}
} else if (variant.is_of_type (new VariantType ("a{ss}"))) {
VariantIter iter;
@@ -103,6 +111,8 @@ public class Indicator.Keyboard.Source : Object {
xkb = value;
} else if (key == "ibus") {
ibus = value;
+ } else if (key == "fcitx") {
+ fcitx = value;
}
}
}
@@ -116,13 +126,21 @@ public class Indicator.Keyboard.Source : Object {
return (!) xkb_info;
}
- private static IBus.Bus get_bus () {
- if (bus == null) {
+ private static IBus.Bus get_ibus_bus () {
+ if (ibus_bus == null) {
IBus.init ();
- bus = new IBus.Bus ();
+ ibus_bus = new IBus.Bus ();
}
- return (!) bus;
+ return (!) ibus_bus;
+ }
+
+ private static Fcitx.InputMethod get_fcitx_proxy () throws Error {
+ if (fcitx_proxy == null) {
+ fcitx_proxy = new Fcitx.InputMethod (GLib.BusType.SESSION, GLib.DBusProxyFlags.NONE, 0);
+ }
+
+ return (!) fcitx_proxy;
}
private IBus.EngineDesc? get_engine () {
@@ -132,7 +150,7 @@ public class Indicator.Keyboard.Source : Object {
var names = new string[2];
names[0] = (!) ibus;
- var engines = get_bus ().get_engines_by_names (names);
+ var engines = get_ibus_bus ().get_engines_by_names (names);
if (engines.length > 0) {
engine = engines[0];
@@ -145,31 +163,7 @@ public class Indicator.Keyboard.Source : Object {
protected virtual string? _get_name () {
string? name = null;
- var engine = get_engine ();
-
- if (engine != null) {
- string? language = ((!) engine).get_language ();
- string? display_name = ((!) engine).get_longname ();
- var has_language = language != null && ((!) language).get_char () != '\0';
- var has_display_name = display_name != null && ((!) display_name).get_char () != '\0';
-
- if (has_language) {
- language = Xkl.get_language_name ((!) language);
- has_language = language != null && ((!) language).get_char () != '\0';
- }
-
- if (has_language && has_display_name) {
- name = @"$((!) language) ($((!) display_name))";
- } else if (has_language) {
- name = language;
- } else if (has_display_name) {
- name = display_name;
- }
- }
-
- var has_name = name != null && ((!) name).get_char () != '\0';
-
- if (!has_name && xkb != null) {
+ if (xkb != null) {
string? display_name = null;
string? layout = null;
@@ -194,14 +188,53 @@ public class Indicator.Keyboard.Source : Object {
name = country;
}
}
- }
- if (name == null || ((!) name).get_char () == '\0') {
- if (ibus != null) {
- name = ibus;
- } else if (xkb != null) {
+ if (name == null || ((!) name).get_char () == '\0') {
name = xkb;
}
+ } else if (ibus != null) {
+ var engine = get_engine ();
+
+ if (engine != null) {
+ string? language = ((!) engine).get_language ();
+ string? display_name = ((!) engine).get_longname ();
+ var has_language = language != null && ((!) language).get_char () != '\0';
+ var has_display_name = display_name != null && ((!) display_name).get_char () != '\0';
+
+ if (has_language) {
+ language = Xkl.get_language_name ((!) language);
+ has_language = language != null && ((!) language).get_char () != '\0';
+ }
+
+ if (has_language && has_display_name) {
+ name = @"$((!) language) ($((!) display_name))";
+ } else if (has_language) {
+ name = language;
+ } else if (has_display_name) {
+ name = display_name;
+ }
+ }
+
+ if (name == null || ((!) name).get_char () == '\0') {
+ name = ibus;
+ }
+ } else if (fcitx != null) {
+ try {
+ var input_methods = get_fcitx_proxy ().get_imlist_nofree ();
+
+ for (var i = 0; i < input_methods.length; i++) {
+ if (input_methods.get (i).unique_name == (!) fcitx) {
+ name = input_methods.get (i).name;
+ break;
+ }
+ }
+ } catch (Error error) {
+ warning ("error: %s", error.message);
+ }
+
+ if (name == null || ((!) name).get_char () == '\0') {
+ name = fcitx;
+ }
}
return name;
@@ -212,23 +245,36 @@ public class Indicator.Keyboard.Source : Object {
if (xkb != null) {
get_xkb_info ().get_layout_info ((!) xkb, null, out short_name, null, null);
- }
- var has_short_name = short_name != null && ((!) short_name).get_char () != '\0';
-
- if (!has_short_name) {
+ if (short_name == null || ((!) short_name).get_char () == '\0') {
+ short_name = xkb;
+ }
+ } else if (ibus != null) {
var engine = get_engine ();
if (engine != null) {
short_name = ((!) engine).get_name ();
}
- }
- if (short_name == null || ((!) short_name).get_char () == '\0') {
- if (ibus != null) {
+ if (short_name == null || ((!) short_name).get_char () == '\0') {
short_name = ibus;
- } else if (xkb != null) {
- short_name = xkb;
+ }
+ } else if (fcitx != null) {
+ try {
+ var input_methods = get_fcitx_proxy ().get_imlist_nofree ();
+
+ for (var i = 0; i < input_methods.length; i++) {
+ if (input_methods.get (i).unique_name == (!) fcitx) {
+ short_name = input_methods.get (i).langcode;
+ break;
+ }
+ }
+ } catch (Error error) {
+ warning ("error: %s", error.message);
+ }
+
+ if (short_name == null || ((!) short_name).get_char () == '\0') {
+ short_name = fcitx;
}
}
diff --git a/tests/indicator-keyboard-test.in b/tests/indicator-keyboard-test.in
index 621133dd..3d43d8ab 100644
--- a/tests/indicator-keyboard-test.in
+++ b/tests/indicator-keyboard-test.in
@@ -4,6 +4,7 @@ export PATH="@abs_top_builddir@/tests/execute:$PATH"
export DCONF_PROFILE="@abs_top_builddir@/tests/profiles/indicator-keyboard-test"
export GSETTINGS_SCHEMA_DIR="@abs_top_builddir@/data"
export XDG_RUNTIME_DIR="@abs_top_builddir@/tests"
+export GTK_IM_MODULE="ibus"
if xvfb-run -a ./indicator-keyboard-tests
then