Merge lp:~attente/unity-settings-daemon/fcitx-transition into lp:unity-settings-daemon
- fcitx-transition
- Merge into trunk
Status: | Merged |
---|---|
Approved by: | Sebastien Bacher |
Approved revision: | 4064 |
Merged at revision: | 4069 |
Proposed branch: | lp:~attente/unity-settings-daemon/fcitx-transition |
Merge into: | lp:unity-settings-daemon |
Diff against target: |
1362 lines (+998/-66) 8 files modified
.bzrignore (+1/-0) configure.ac (+22/-2) debian/control (+4/-1) debian/rules (+1/-1) plugins/keyboard/Makefile.am (+7/-0) plugins/keyboard/gsd-keyboard-manager.c (+633/-50) plugins/keyboard/input-method-engines.gperf (+203/-0) plugins/media-keys/gsd-media-keys-manager.c (+127/-12) |
To merge this branch: | bzr merge lp:~attente/unity-settings-daemon/fcitx-transition |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sebastien Bacher | Approve | ||
PS Jenkins bot (community) | continuous-integration | Approve | |
Review via email: mp+230289@code.launchpad.net |
Commit message
Basic Fcitx support.
Description of the change
Basic Fcitx support.
PS Jenkins bot (ps-jenkins) wrote : | # |
- 4049. By William Hua
-
Revert.
- 4050. By William Hua
-
Use fcitx-gclient API instead.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4050
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Sebastien Bacher (seb128) wrote : | # |
Thanks, looks mostly fine, some comments:
- we shouldn't recommend both ibus and fcitx from the settings daemon, we should rather seed fcitx if we want it installed by default
- we need to have the fcitx MIR approved because we can land the changes, since it adds a build-depends on packages which are currently in universe
- looks fine to land otherwise
setting needs fixing for the recommend, then it's good to go, once the fcitx MIR is ready
- 4051. By William Hua
-
Remove fcitx from recommends.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4051
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4052. By William Hua
-
Sync Fcitx engine list to input sources.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4052
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4053. By William Hua
-
Activate Fcitx when disabled.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4053
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4054. By William Hua
-
Translate keyboard layout names properly to Fcitx.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4054
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4055. By William Hua
-
Update current index when Fcitx engine changes.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4055
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4056. By William Hua
-
Sync fcitx engines to dconf.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4056
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4057. By William Hua
-
Fix migration; WIP: finish get_fcitx_
engine_ for_ibus_ engine ().
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4057
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4058. By William Hua
-
Finish get_fcitx_
engine_ for_ibus_ engine ().
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Continuous integration, rev:4058
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
FAILURE: http://
Click here to trigger a rebuild:
http://
- 4059. By William Hua
-
Add gperf as build dependency.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4059
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4060. By William Hua
-
Set initial IM when Fcitx appears.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4060
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4061. By William Hua
-
Use Fcitx current IM instead of current source when available.
- 4062. By William Hua
-
Migrate per-window setting to Fcitx.
- 4063. By William Hua
-
Remember to zero struct.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4063
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
- 4064. By William Hua
-
Merge trunk.
William Hua (attente) wrote : | # |
Hi, could we please reconsider this for approval now that Fcitx is approved for main? I don't remember why I added fcitx-data as a Recommends, but if it's wrong, I'll remove it.
PS Jenkins bot (ps-jenkins) wrote : | # |
PASSED: Continuous integration, rev:4064
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild:
http://
Sebastien Bacher (seb128) wrote : | # |
Thanks, seems like we don't have anyone available to do a detailed review, so based on a read of the changes and testing in a ppa let's approve that, if there are issues we can sort them out with another landing
Preview Diff
1 | === modified file '.bzrignore' |
2 | --- .bzrignore 2013-12-04 23:55:26 +0000 |
3 | +++ .bzrignore 2015-02-12 15:57:03 +0000 |
4 | @@ -48,6 +48,7 @@ |
5 | plugins/datetime/gsd-datetime-mechanism-glue.h |
6 | plugins/datetime/org.gnome.SettingsDaemon.DateTimeMechanism.service |
7 | plugins/datetime/org.gnome.settingsdaemon.datetimemechanism.policy |
8 | +plugins/keyboard/input-method-engines.c |
9 | plugins/media-keys/gsd-marshal.c |
10 | plugins/media-keys/gsd-marshal.h |
11 | plugins/media-keys/gsd-media-keys-manager-glue.h |
12 | |
13 | === modified file 'configure.ac' |
14 | --- configure.ac 2014-10-07 23:50:00 +0000 |
15 | +++ configure.ac 2015-02-12 15:57:03 +0000 |
16 | @@ -204,7 +204,26 @@ |
17 | fi |
18 | AM_CONDITIONAL(HAVE_IBUS, test "x$enable_ibus" == "xyes") |
19 | |
20 | -PKG_CHECK_MODULES(KEYBOARD, accountsservice xkbfile xkeyboard-config $IBUS_MODULE gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION) |
21 | +AC_ARG_ENABLE(fcitx, |
22 | + AS_HELP_STRING([--disable-fcitx], |
23 | + [Disable Fcitx support]), |
24 | + enable_fcitx=$enableval, |
25 | + enable_fcitx=yes) |
26 | + |
27 | +if test "x$enable_fcitx" = "xyes" ; then |
28 | + FCITX_MODULE="fcitx-config fcitx-gclient" |
29 | + AC_DEFINE(HAVE_FCITX, 1, [Defined if Fcitx support is enabled]) |
30 | + |
31 | + AC_CHECK_PROG(HAVE_GPERF, gperf, yes) |
32 | + if test "x$HAVE_GPERF" != "xyes" ; then |
33 | + AC_MSG_ERROR([gperf needed for Fcitx support]) |
34 | + fi |
35 | +else |
36 | + FCITX_MODULE= |
37 | +fi |
38 | +AM_CONDITIONAL(HAVE_FCITX, test "x$enable_fcitx" == "xyes") |
39 | + |
40 | +PKG_CHECK_MODULES(KEYBOARD, accountsservice xkbfile xkeyboard-config $IBUS_MODULE $FCITX_MODULE gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED_VERSION) |
41 | |
42 | XKB_BASE=$($PKG_CONFIG --variable xkb_base xkeyboard-config) |
43 | AC_SUBST(XKB_BASE) |
44 | @@ -218,7 +237,7 @@ |
45 | dnl - media-keys plugin stuff |
46 | dnl --------------------------------------------------------------------------- |
47 | |
48 | -PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra-gtk3 libnotify alsa]) |
49 | +PKG_CHECK_MODULES(MEDIA_KEYS, [gio-unix-2.0 libpulse >= $PA_REQUIRED_VERSION $GUDEV_PKG libpulse-mainloop-glib >= $PA_REQUIRED_VERSION libcanberra-gtk3 libnotify alsa $FCITX_MODULE]) |
50 | PKG_CHECK_MODULES(GVC, [gobject-2.0 libpulse >= $PA_REQUIRED_VERSION libpulse-mainloop-glib >= $PA_REQUIRED_VERSION]) |
51 | AM_CONDITIONAL(HAVE_INTROSPECTION, false) |
52 | |
53 | @@ -564,6 +583,7 @@ |
54 | Session tracking: ${SESSION_TRACKING} |
55 | LCMS DICT support: ${have_new_lcms} |
56 | IBus support: ${enable_ibus} |
57 | + Fcitx support: ${enable_fcitx} |
58 | Libnotify support: ${have_libnotify} |
59 | PackageKit support: ${have_packagekit} |
60 | Smartcard support: ${have_smartcard_support} |
61 | |
62 | === modified file 'debian/control' |
63 | --- debian/control 2014-11-27 10:32:03 +0000 |
64 | +++ debian/control 2015-02-12 15:57:03 +0000 |
65 | @@ -41,6 +41,8 @@ |
66 | libxklavier-dev, |
67 | libsystemd-login-dev (>= 183), |
68 | libibus-1.0-dev (>= 1.5.0), |
69 | + fcitx-libs-dev, |
70 | + gperf, |
71 | libgl1-mesa-dev, |
72 | libxkbfile-dev, |
73 | xkb-data, |
74 | @@ -56,7 +58,8 @@ |
75 | nautilus-data (>= 2.91.3-1), |
76 | gnome-settings-daemon-schemas (>= 3.8), |
77 | gsettings-ubuntu-schemas (>= 0.0.1+14.04.20140224), |
78 | -Recommends: ibus (>= 1.5.0), |
79 | +Recommends: fcitx-data, |
80 | + ibus (>= 1.5.0), |
81 | pulseaudio, |
82 | systemd-services |
83 | Pre-Depends: ${misc:Pre-Depends} |
84 | |
85 | === modified file 'debian/rules' |
86 | --- debian/rules 2014-10-07 23:50:00 +0000 |
87 | +++ debian/rules 2015-02-12 15:57:03 +0000 |
88 | @@ -8,7 +8,7 @@ |
89 | |
90 | DEB_DH_MAKESHLIBS_ARGS_ALL += -X/usr/lib/unity-settings-daemon-1.0 |
91 | DEB_CONFIGURE_SCRIPT := ./autogen.sh |
92 | -DEB_CONFIGURE_EXTRA_FLAGS = --enable-systemd --disable-packagekit --enable-ibus |
93 | +DEB_CONFIGURE_EXTRA_FLAGS = --enable-systemd --disable-packagekit --enable-ibus --enable-fcitx |
94 | |
95 | build/unity-settings-daemon:: |
96 | gcc -o gnome-settings-daemon/gnome-update-wallpaper-cache debian/gnome-update-wallpaper-cache.c `pkg-config --cflags --libs glib-2.0 gdk-3.0 gdk-x11-3.0 gio-2.0 gnome-desktop-3.0` |
97 | |
98 | === modified file 'plugins/keyboard/Makefile.am' |
99 | --- plugins/keyboard/Makefile.am 2014-09-29 11:08:12 +0000 |
100 | +++ plugins/keyboard/Makefile.am 2015-02-12 15:57:03 +0000 |
101 | @@ -15,6 +15,13 @@ |
102 | kbd-capslock-off.png kbd-numlock-off.png kbd-scrolllock-off.png \ |
103 | kbd-capslock-on.png kbd-numlock-on.png kbd-scrolllock-on.png |
104 | |
105 | +if HAVE_FCITX |
106 | +BUILT_SOURCES = input-method-engines.c |
107 | +endif |
108 | + |
109 | +input-method-engines.c: $(srcdir)/input-method-engines.gperf |
110 | + $(AM_V_GEN) gperf --output-file=input-method-engines.c $< |
111 | + |
112 | libkeyboard_la_SOURCES = \ |
113 | gsd-keyboard-plugin.c \ |
114 | gsd-keyboard-manager.h \ |
115 | |
116 | === modified file 'plugins/keyboard/gsd-keyboard-manager.c' |
117 | --- plugins/keyboard/gsd-keyboard-manager.c 2014-09-29 11:08:12 +0000 |
118 | +++ plugins/keyboard/gsd-keyboard-manager.c 2015-02-12 15:57:03 +0000 |
119 | @@ -48,6 +48,11 @@ |
120 | #include <ibus.h> |
121 | #endif |
122 | |
123 | +#ifdef HAVE_FCITX |
124 | +#include <fcitx-config/fcitx-config.h> |
125 | +#include <fcitx-gclient/fcitxinputmethod.h> |
126 | +#endif |
127 | + |
128 | #include <act/act.h> |
129 | |
130 | #include "gnome-settings-session.h" |
131 | @@ -57,6 +62,10 @@ |
132 | #include "gsd-enums.h" |
133 | #include "gsd-xkb-utils.h" |
134 | |
135 | +#ifdef HAVE_FCITX |
136 | +#include "input-method-engines.c" |
137 | +#endif |
138 | + |
139 | #define GSD_KEYBOARD_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_KEYBOARD_MANAGER, GsdKeyboardManagerPrivate)) |
140 | |
141 | #define GSD_KEYBOARD_DIR "org.gnome.settings-daemon.peripherals.keyboard" |
142 | @@ -76,9 +85,11 @@ |
143 | |
144 | #define GNOME_DESKTOP_INTERFACE_DIR "org.gnome.desktop.interface" |
145 | |
146 | +#define ENV_GTK_IM_MODULE "GTK_IM_MODULE" |
147 | #define KEY_GTK_IM_MODULE "gtk-im-module" |
148 | #define GTK_IM_MODULE_SIMPLE "gtk-im-context-simple" |
149 | #define GTK_IM_MODULE_IBUS "ibus" |
150 | +#define GTK_IM_MODULE_FCITX "fcitx" |
151 | |
152 | #define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources" |
153 | |
154 | @@ -86,8 +97,11 @@ |
155 | #define KEY_INPUT_SOURCES "sources" |
156 | #define KEY_KEYBOARD_OPTIONS "xkb-options" |
157 | |
158 | -#define INPUT_SOURCE_TYPE_XKB "xkb" |
159 | -#define INPUT_SOURCE_TYPE_IBUS "ibus" |
160 | +#define INPUT_SOURCE_TYPE_XKB "xkb" |
161 | +#define INPUT_SOURCE_TYPE_IBUS "ibus" |
162 | +#define INPUT_SOURCE_TYPE_FCITX "fcitx" |
163 | + |
164 | +#define FCITX_XKB_PREFIX "fcitx-keyboard-" |
165 | |
166 | #define DEFAULT_LANGUAGE "en_US" |
167 | #define DEFAULT_LAYOUT "us" |
168 | @@ -108,6 +122,13 @@ |
169 | IBusBus *ibus; |
170 | GHashTable *ibus_engines; |
171 | GCancellable *ibus_cancellable; |
172 | + gboolean is_ibus_active; |
173 | +#endif |
174 | +#ifdef HAVE_FCITX |
175 | + FcitxInputMethod *fcitx; |
176 | + GCancellable *fcitx_cancellable; |
177 | + gulong fcitx_signal_id; |
178 | + gboolean is_fcitx_active; |
179 | #endif |
180 | gint xkb_event_base; |
181 | GsdNumLockState old_state; |
182 | @@ -1079,6 +1100,186 @@ |
183 | } |
184 | } |
185 | |
186 | +#ifdef HAVE_FCITX |
187 | +static gchar * |
188 | +get_xkb_name (const gchar *name) |
189 | +{ |
190 | + gchar *xkb_name; |
191 | + gchar *separator; |
192 | + |
193 | + if (g_str_has_prefix (name, FCITX_XKB_PREFIX)) |
194 | + name += strlen (FCITX_XKB_PREFIX); |
195 | + |
196 | + xkb_name = g_strdup (name); |
197 | + separator = strchr (xkb_name, '-'); |
198 | + |
199 | + if (separator) |
200 | + *separator = '+'; |
201 | + |
202 | + return xkb_name; |
203 | +} |
204 | + |
205 | +static gchar * |
206 | +get_fcitx_name (const gchar *name) |
207 | +{ |
208 | + gchar *fcitx_name = g_strdup (name); |
209 | + gchar *separator = strchr (fcitx_name, '+'); |
210 | + |
211 | + if (separator) |
212 | + *separator = '-'; |
213 | + |
214 | + return fcitx_name; |
215 | +} |
216 | + |
217 | +static gboolean |
218 | +input_source_is_fcitx_engine (const gchar *type, |
219 | + const gchar *name, |
220 | + const gchar *engine) |
221 | +{ |
222 | + if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) { |
223 | + if (g_str_has_prefix (engine, FCITX_XKB_PREFIX)) { |
224 | + gboolean equal; |
225 | + gchar *fcitx_name = get_fcitx_name (name); |
226 | + equal = g_str_equal (fcitx_name, engine + strlen (FCITX_XKB_PREFIX)); |
227 | + g_free (fcitx_name); |
228 | + return equal; |
229 | + } |
230 | + } else if (g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { |
231 | + return g_str_equal (name, engine); |
232 | + } |
233 | + |
234 | + return FALSE; |
235 | +} |
236 | + |
237 | +static void |
238 | +fcitx_engine_changed (GsdKeyboardManager *manager, |
239 | + GParamSpec *pspec, |
240 | + FcitxInputMethod *fcitx) |
241 | +{ |
242 | + GSettings *settings = manager->priv->input_sources_settings; |
243 | + gchar *engine = fcitx_input_method_get_current_im (manager->priv->fcitx); |
244 | + |
245 | + if (engine) { |
246 | + GVariant *sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); |
247 | + guint current = g_settings_get_uint (settings, KEY_CURRENT_INPUT_SOURCE); |
248 | + gboolean update = TRUE; |
249 | + |
250 | + if (current >= 0 && current < g_variant_n_children (sources)) { |
251 | + const gchar *type; |
252 | + const gchar *name; |
253 | + |
254 | + g_variant_get_child (sources, current, "(&s&s)", &type, &name); |
255 | + update = !input_source_is_fcitx_engine (type, name, engine); |
256 | + } |
257 | + |
258 | + if (update) { |
259 | + gsize i; |
260 | + |
261 | + for (i = 0; i < g_variant_n_children (sources); i++) { |
262 | + const gchar *type; |
263 | + const gchar *name; |
264 | + |
265 | + if (i == current) |
266 | + continue; |
267 | + |
268 | + g_variant_get_child (sources, i, "(&s&s)", &type, &name); |
269 | + |
270 | + if (input_source_is_fcitx_engine (type, name, engine)) { |
271 | + g_settings_set_uint (settings, KEY_CURRENT_INPUT_SOURCE, i); |
272 | + break; |
273 | + } |
274 | + } |
275 | + } |
276 | + |
277 | + g_variant_unref (sources); |
278 | + g_free (engine); |
279 | + } |
280 | +} |
281 | + |
282 | +static gboolean |
283 | +should_update_input_sources (GVariant *sources, |
284 | + GPtrArray *engines) |
285 | +{ |
286 | + GVariantIter iter; |
287 | + const gchar *type; |
288 | + const gchar *name; |
289 | + guint i = 0; |
290 | + |
291 | + g_variant_iter_init (&iter, sources); |
292 | + while (g_variant_iter_next (&iter, "(&s&s)", &type, &name)) { |
293 | + if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB) || |
294 | + g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { |
295 | + FcitxIMItem *engine; |
296 | + |
297 | + /* get the next enabled fcitx engine */ |
298 | + for (; i < engines->len; i++) { |
299 | + engine = g_ptr_array_index (engines, i); |
300 | + |
301 | + if (engine->enable) |
302 | + break; |
303 | + } |
304 | + |
305 | + /* there should be an enabled engine and it should match, otherwise we need to update */ |
306 | + if (i++ >= engines->len || !input_source_is_fcitx_engine (type, name, engine->unique_name)) |
307 | + return TRUE; |
308 | + } |
309 | + } |
310 | + |
311 | + /* if there are more enabled engines, we need to update */ |
312 | + for (; i < engines->len; i++) { |
313 | + FcitxIMItem *engine = g_ptr_array_index (engines, i); |
314 | + |
315 | + if (engine->enable) |
316 | + return TRUE; |
317 | + } |
318 | + |
319 | + return FALSE; |
320 | +} |
321 | + |
322 | +static void |
323 | +update_input_sources_from_fcitx_engines (GsdKeyboardManager *manager, |
324 | + FcitxInputMethod *fcitx) |
325 | +{ |
326 | + GPtrArray *engines = fcitx_input_method_get_imlist (manager->priv->fcitx); |
327 | + |
328 | + if (engines) { |
329 | + GVariant *sources = g_settings_get_value (manager->priv->input_sources_settings, KEY_INPUT_SOURCES); |
330 | + |
331 | + if (should_update_input_sources (sources, engines)) { |
332 | + GVariantBuilder builder; |
333 | + gboolean update = FALSE; |
334 | + guint i; |
335 | + |
336 | + g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(ss)")); |
337 | + |
338 | + for (i = 0; i < engines->len; i++) { |
339 | + FcitxIMItem *engine = g_ptr_array_index (engines, i); |
340 | + |
341 | + if (engine->enable) { |
342 | + if (g_str_has_prefix (engine->unique_name, FCITX_XKB_PREFIX)) { |
343 | + gchar *name = get_xkb_name (engine->unique_name); |
344 | + g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_XKB, name); |
345 | + g_free (name); |
346 | + } else { |
347 | + g_variant_builder_add (&builder, "(ss)", INPUT_SOURCE_TYPE_FCITX, engine->unique_name); |
348 | + } |
349 | + |
350 | + update = TRUE; |
351 | + } |
352 | + } |
353 | + |
354 | + if (update) |
355 | + g_settings_set_value (manager->priv->input_sources_settings, KEY_INPUT_SOURCES, g_variant_builder_end (&builder)); |
356 | + else |
357 | + g_variant_builder_clear (&builder); |
358 | + } |
359 | + |
360 | + g_variant_unref (sources); |
361 | + g_ptr_array_unref (engines); |
362 | + } |
363 | +} |
364 | +#endif |
365 | + |
366 | static gboolean |
367 | apply_input_source (GsdKeyboardManager *manager, |
368 | guint current) |
369 | @@ -1103,7 +1304,9 @@ |
370 | priv->active_input_source = current; |
371 | |
372 | #ifdef HAVE_IBUS |
373 | - maybe_start_ibus (manager); |
374 | + if (priv->is_ibus_active) { |
375 | + maybe_start_ibus (manager); |
376 | + } |
377 | #endif |
378 | |
379 | g_variant_get_child (sources, current, "(&s&s)", &type, &id); |
380 | @@ -1119,44 +1322,86 @@ |
381 | g_warning ("Couldn't find XKB input source '%s'", id); |
382 | goto exit; |
383 | } |
384 | + |
385 | +#ifdef HAVE_FCITX |
386 | + if (priv->is_fcitx_active && priv->fcitx) { |
387 | + gchar *name = g_strdup_printf (FCITX_XKB_PREFIX "%s", id); |
388 | + gchar *fcitx_name = get_fcitx_name (name); |
389 | + fcitx_input_method_activate (priv->fcitx); |
390 | + fcitx_input_method_set_current_im (priv->fcitx, fcitx_name); |
391 | + g_free (fcitx_name); |
392 | + g_free (name); |
393 | + } |
394 | +#endif |
395 | + |
396 | #ifdef HAVE_IBUS |
397 | - set_gtk_im_module (manager, sources); |
398 | - set_ibus_xkb_engine (manager); |
399 | + if (priv->is_ibus_active) { |
400 | + set_gtk_im_module (manager, sources); |
401 | + set_ibus_xkb_engine (manager); |
402 | + } |
403 | #endif |
404 | } else if (g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) { |
405 | #ifdef HAVE_IBUS |
406 | - IBusEngineDesc *engine_desc = NULL; |
407 | - |
408 | - if (priv->ibus_engines) |
409 | - engine_desc = g_hash_table_lookup (priv->ibus_engines, id); |
410 | - else |
411 | - goto exit; /* we'll be called again when ibus is up and running */ |
412 | - |
413 | - if (engine_desc) { |
414 | - const gchar *ibus_layout; |
415 | - ibus_layout = ibus_engine_desc_get_layout (engine_desc); |
416 | - |
417 | - if (ibus_layout) { |
418 | - layout = layout_from_ibus_layout (ibus_layout); |
419 | - variant = variant_from_ibus_layout (ibus_layout); |
420 | - options = options_from_ibus_layout (ibus_layout); |
421 | + if (priv->is_ibus_active) { |
422 | + IBusEngineDesc *engine_desc = NULL; |
423 | + |
424 | + if (priv->ibus_engines) |
425 | + engine_desc = g_hash_table_lookup (priv->ibus_engines, id); |
426 | + else |
427 | + goto exit; /* we'll be called again when ibus is up and running */ |
428 | + |
429 | + if (engine_desc) { |
430 | + const gchar *ibus_layout; |
431 | + ibus_layout = ibus_engine_desc_get_layout (engine_desc); |
432 | + |
433 | + if (ibus_layout) { |
434 | + layout = layout_from_ibus_layout (ibus_layout); |
435 | + variant = variant_from_ibus_layout (ibus_layout); |
436 | + options = options_from_ibus_layout (ibus_layout); |
437 | + } |
438 | + } else { |
439 | + g_warning ("Couldn't find IBus input source '%s'", id); |
440 | + goto exit; |
441 | } |
442 | + |
443 | + /* NULL here is a shortcut for "I already know I |
444 | + need the IBus module". */ |
445 | + set_gtk_im_module (manager, NULL); |
446 | + set_ibus_engine (manager, id); |
447 | } else { |
448 | - g_warning ("Couldn't find IBus input source '%s'", id); |
449 | - goto exit; |
450 | + g_warning ("IBus input source type specified but IBus is not active"); |
451 | } |
452 | - |
453 | - /* NULL here is a shortcut for "I already know I |
454 | - need the IBus module". */ |
455 | - set_gtk_im_module (manager, NULL); |
456 | - set_ibus_engine (manager, id); |
457 | #else |
458 | g_warning ("IBus input source type specified but IBus support was not compiled"); |
459 | #endif |
460 | + } else if (g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { |
461 | +#ifdef HAVE_FCITX |
462 | + if (priv->is_fcitx_active) { |
463 | + if (priv->fcitx) { |
464 | + gchar *name = g_strdup (id); |
465 | + fcitx_input_method_activate (priv->fcitx); |
466 | + fcitx_input_method_set_current_im (priv->fcitx, name); |
467 | + g_free (name); |
468 | + } else { |
469 | + g_warning ("Fcitx input method framework unavailable"); |
470 | + } |
471 | + } else { |
472 | + g_warning ("Fcitx input source type specified but Fcitx is not active"); |
473 | + } |
474 | +#else |
475 | + g_warning ("Fcitx input source type specified but Fcitx support was not compiled"); |
476 | +#endif |
477 | } else { |
478 | g_warning ("Unknown input source type '%s'", type); |
479 | } |
480 | |
481 | +#ifdef HAVE_FCITX |
482 | + if (priv->is_fcitx_active && priv->fcitx && !priv->fcitx_signal_id) { |
483 | + priv->fcitx_signal_id = g_signal_connect_swapped (manager->priv->fcitx, "notify::current-im", G_CALLBACK (fcitx_engine_changed), manager); |
484 | + g_signal_connect_swapped (manager->priv->fcitx, "imlist-changed", G_CALLBACK (update_input_sources_from_fcitx_engines), manager); |
485 | + } |
486 | +#endif |
487 | + |
488 | exit: |
489 | apply_xkb_settings (manager, layout, variant, |
490 | prepare_xkb_options (manager, n_sources, options)); |
491 | @@ -1168,6 +1413,229 @@ |
492 | return TRUE; |
493 | } |
494 | |
495 | +#ifdef HAVE_FCITX |
496 | +static const gchar * |
497 | +get_fcitx_engine_for_ibus_engine (const gchar *ibus_engine) |
498 | +{ |
499 | + const struct Engine *engine; |
500 | + |
501 | + if (!ibus_engine) |
502 | + return NULL; |
503 | + |
504 | + engine = get_engine_for_ibus_engine (ibus_engine, strlen (ibus_engine)); |
505 | + |
506 | + return engine ? engine->fcitx_engine : NULL; |
507 | +} |
508 | + |
509 | +static void |
510 | +enable_fcitx_engines (GsdKeyboardManager *manager, |
511 | + gboolean migrate) |
512 | +{ |
513 | + GsdKeyboardManagerPrivate *priv = manager->priv; |
514 | + GPtrArray *engines; |
515 | + GVariant *sources; |
516 | + GVariantIter iter; |
517 | + const gchar *type; |
518 | + const gchar *name; |
519 | + gboolean changed; |
520 | + guint i; |
521 | + guint j; |
522 | + |
523 | + engines = fcitx_input_method_get_imlist (priv->fcitx); |
524 | + |
525 | + if (!engines) { |
526 | + g_warning ("Cannot update Fcitx engine list"); |
527 | + return; |
528 | + } |
529 | + |
530 | + sources = g_settings_get_value (priv->input_sources_settings, KEY_INPUT_SOURCES); |
531 | + changed = FALSE; |
532 | + i = 0; |
533 | + |
534 | + g_variant_iter_init (&iter, sources); |
535 | + while (g_variant_iter_next (&iter, "(&s&s)", &type, &name)) { |
536 | + if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) { |
537 | + gchar *fcitx_name = get_fcitx_name (name); |
538 | + |
539 | + for (j = i; j < engines->len; j++) { |
540 | + FcitxIMItem *engine = g_ptr_array_index (engines, j); |
541 | + |
542 | + if (g_str_has_prefix (engine->unique_name, FCITX_XKB_PREFIX) && |
543 | + g_str_equal (engine->unique_name + strlen (FCITX_XKB_PREFIX), fcitx_name)) { |
544 | + if (!engine->enable) { |
545 | + engine->enable = TRUE; |
546 | + changed = TRUE; |
547 | + } |
548 | + |
549 | + break; |
550 | + } |
551 | + } |
552 | + |
553 | + g_free (fcitx_name); |
554 | + |
555 | + /* j is either the index of the engine "fcitx-keyboard-<name>" |
556 | + * or engines->len, meaning it wasn't found. */ |
557 | + } else if (migrate && g_str_equal (type, INPUT_SOURCE_TYPE_IBUS)) { |
558 | + const gchar *fcitx_name = get_fcitx_engine_for_ibus_engine (name); |
559 | + |
560 | + if (!fcitx_name) |
561 | + continue; |
562 | + |
563 | + for (j = i; j < engines->len; j++) { |
564 | + FcitxIMItem *engine = g_ptr_array_index (engines, j); |
565 | + |
566 | + if (g_str_equal (engine->unique_name, fcitx_name)) { |
567 | + if (!engine->enable) { |
568 | + engine->enable = TRUE; |
569 | + changed = TRUE; |
570 | + } |
571 | + |
572 | + break; |
573 | + } |
574 | + } |
575 | + |
576 | + /* j is either the index of the engine "<name>" |
577 | + * or engines->len, meaning it wasn't found. */ |
578 | + } else if (g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { |
579 | + for (j = i; j < engines->len; j++) { |
580 | + FcitxIMItem *engine = g_ptr_array_index (engines, j); |
581 | + |
582 | + if (g_str_equal (engine->unique_name, name)) { |
583 | + if (!engine->enable) { |
584 | + engine->enable = TRUE; |
585 | + changed = TRUE; |
586 | + } |
587 | + |
588 | + break; |
589 | + } |
590 | + } |
591 | + |
592 | + /* j is either the index of the engine "<name>" |
593 | + * or engines->len, meaning it wasn't found. */ |
594 | + } else { |
595 | + continue; |
596 | + } |
597 | + |
598 | + if (j < engines->len) { |
599 | + if (j != i) { |
600 | + gpointer ptr = engines->pdata[i]; |
601 | + engines->pdata[i] = engines->pdata[j]; |
602 | + engines->pdata[j] = ptr; |
603 | + changed = TRUE; |
604 | + } |
605 | + |
606 | + i++; |
607 | + } else { |
608 | + g_warning ("Fcitx engine not found for %s", name); |
609 | + } |
610 | + } |
611 | + |
612 | + /* we should have i enabled fcitx engines: disable everything else. */ |
613 | + |
614 | + for (; i < engines->len; i++) { |
615 | + FcitxIMItem *engine = g_ptr_array_index (engines, i); |
616 | + |
617 | + if (engine->enable) { |
618 | + engine->enable = FALSE; |
619 | + changed = TRUE; |
620 | + } |
621 | + } |
622 | + |
623 | + if (changed) { |
624 | + fcitx_input_method_set_imlist (priv->fcitx, engines); |
625 | + } |
626 | + |
627 | + g_variant_unref (sources); |
628 | + g_ptr_array_unref (engines); |
629 | +} |
630 | + |
631 | +struct _FcitxShareStateConfig |
632 | +{ |
633 | + FcitxGenericConfig config; |
634 | + gint share_state; |
635 | +}; |
636 | + |
637 | +typedef struct _FcitxShareStateConfig FcitxShareStateConfig; |
638 | + |
639 | +static CONFIG_BINDING_BEGIN (FcitxShareStateConfig) |
640 | +CONFIG_BINDING_REGISTER ("Program", "ShareStateAmongWindow", share_state) |
641 | +CONFIG_BINDING_END () |
642 | + |
643 | +static CONFIG_DESC_DEFINE (get_fcitx_config_desc, "config.desc") |
644 | + |
645 | +static void |
646 | +update_share_state_from_per_window (GsdKeyboardManager *manager) |
647 | +{ |
648 | + /* Set Fcitx' share state setting based on the GSettings per-window option. */ |
649 | + GSettings *settings = g_settings_new ("org.gnome.libgnomekbd.desktop"); |
650 | + gboolean per_window = g_settings_get_boolean (settings, "group-per-window"); |
651 | + |
652 | + FcitxShareStateConfig config = { { NULL } }; |
653 | + |
654 | + /* Load the user's Fcitx configuration. */ |
655 | + FILE *file = FcitxXDGGetFileUserWithPrefix (NULL, "config", "r", NULL); |
656 | + FcitxConfigFile *config_file = FcitxConfigParseConfigFileFp (file, get_fcitx_config_desc ()); |
657 | + FcitxShareStateConfigConfigBind (&config, config_file, get_fcitx_config_desc ()); |
658 | + |
659 | + if (file) |
660 | + fclose (file); |
661 | + |
662 | + config.share_state = per_window ? 0 : 1; |
663 | + |
664 | + /* Save the user's Fcitx configuration. */ |
665 | + file = FcitxXDGGetFileUserWithPrefix (NULL, "config", "w", NULL); |
666 | + FcitxConfigSaveConfigFileFp (file, &config.config, get_fcitx_config_desc ()); |
667 | + |
668 | + if (file) |
669 | + fclose (file); |
670 | + |
671 | + fcitx_input_method_reload_config (manager->priv->fcitx); |
672 | + |
673 | + g_object_unref (settings); |
674 | +} |
675 | + |
676 | +static void |
677 | +migrate_fcitx_engines (GsdKeyboardManager *manager) |
678 | +{ |
679 | + GPtrArray *engines = fcitx_input_method_get_imlist (manager->priv->fcitx); |
680 | + |
681 | + if (engines) { |
682 | + gboolean migrate = FALSE; |
683 | + gboolean second = FALSE; |
684 | + guint i; |
685 | + |
686 | + /* Migrate if there are at least two enabled fcitx engines or |
687 | + * there is one fcitx engine which is not a keyboard layout. |
688 | + * These are our criteria for determining which direction to |
689 | + * sync fcitx engines with input sources. */ |
690 | + |
691 | + for (i = 0; i < engines->len; i++) { |
692 | + FcitxIMItem *engine = g_ptr_array_index (engines, i); |
693 | + |
694 | + if (engine->enable) { |
695 | + if (second || !g_str_has_prefix (engine->unique_name, FCITX_XKB_PREFIX)) { |
696 | + migrate = TRUE; |
697 | + break; |
698 | + } |
699 | + |
700 | + second = TRUE; |
701 | + } |
702 | + } |
703 | + |
704 | + if (migrate) { |
705 | + /* Migrate Fcitx to GSettings. */ |
706 | + update_input_sources_from_fcitx_engines (manager, manager->priv->fcitx); |
707 | + } else { |
708 | + /* Migrate GSettings to Fcitx. */ |
709 | + enable_fcitx_engines (manager, TRUE); |
710 | + update_share_state_from_per_window (manager); |
711 | + } |
712 | + |
713 | + g_ptr_array_unref (engines); |
714 | + } |
715 | +} |
716 | +#endif |
717 | + |
718 | static gboolean |
719 | apply_input_sources_settings (GSettings *settings, |
720 | gpointer keys, |
721 | @@ -1181,6 +1649,30 @@ |
722 | ActUserManager *user_manager; |
723 | gboolean user_manager_loaded; |
724 | |
725 | +#ifdef HAVE_FCITX |
726 | + if (priv->is_fcitx_active) { |
727 | + gboolean sources_changed = FALSE; |
728 | + |
729 | + if (keys) { |
730 | + GQuark *quarks = keys; |
731 | + gint i; |
732 | + |
733 | + for (i = 0; i < n_keys; i++) { |
734 | + if (quarks[i] == g_quark_try_string (KEY_INPUT_SOURCES)) { |
735 | + sources_changed = TRUE; |
736 | + break; |
737 | + } |
738 | + } |
739 | + } else { |
740 | + sources_changed = TRUE; |
741 | + } |
742 | + |
743 | + if (sources_changed) { |
744 | + enable_fcitx_engines (manager, FALSE); |
745 | + } |
746 | + } |
747 | +#endif |
748 | + |
749 | sources = g_settings_get_value (priv->input_sources_settings, KEY_INPUT_SOURCES); |
750 | n_sources = g_variant_n_children (sources); |
751 | |
752 | @@ -1546,11 +2038,10 @@ |
753 | g_object_unref (libgnomekbd_settings); |
754 | } |
755 | |
756 | -static void |
757 | -maybe_convert_old_settings (GSettings *settings) |
758 | +static gboolean |
759 | +should_migrate (const gchar *id) |
760 | { |
761 | - GVariant *sources; |
762 | - gchar **options; |
763 | + gboolean migrate = FALSE; |
764 | gchar *stamp_dir_path = NULL; |
765 | gchar *stamp_file_path = NULL; |
766 | GError *error = NULL; |
767 | @@ -1561,23 +2052,11 @@ |
768 | goto out; |
769 | } |
770 | |
771 | - stamp_file_path = g_build_filename (stamp_dir_path, "input-sources-converted", NULL); |
772 | + stamp_file_path = g_build_filename (stamp_dir_path, id, NULL); |
773 | if (g_file_test (stamp_file_path, G_FILE_TEST_EXISTS)) |
774 | goto out; |
775 | |
776 | - sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); |
777 | - if (g_variant_n_children (sources) < 1) { |
778 | - convert_libgnomekbd_layouts (settings); |
779 | -#ifdef HAVE_IBUS |
780 | - convert_ibus (settings); |
781 | -#endif |
782 | - } |
783 | - g_variant_unref (sources); |
784 | - |
785 | - options = g_settings_get_strv (settings, KEY_KEYBOARD_OPTIONS); |
786 | - if (g_strv_length (options) < 1) |
787 | - convert_libgnomekbd_options (settings); |
788 | - g_strfreev (options); |
789 | + migrate = TRUE; |
790 | |
791 | if (!g_file_set_contents (stamp_file_path, "", 0, &error)) { |
792 | g_warning ("%s", error->message); |
793 | @@ -1586,6 +2065,30 @@ |
794 | out: |
795 | g_free (stamp_file_path); |
796 | g_free (stamp_dir_path); |
797 | + return migrate; |
798 | +} |
799 | + |
800 | +static void |
801 | +maybe_convert_old_settings (GSettings *settings) |
802 | +{ |
803 | + if (should_migrate ("input-sources-converted")) { |
804 | + GVariant *sources; |
805 | + gchar **options; |
806 | + |
807 | + sources = g_settings_get_value (settings, KEY_INPUT_SOURCES); |
808 | + if (g_variant_n_children (sources) < 1) { |
809 | + convert_libgnomekbd_layouts (settings); |
810 | +#ifdef HAVE_IBUS |
811 | + convert_ibus (settings); |
812 | +#endif |
813 | + } |
814 | + g_variant_unref (sources); |
815 | + |
816 | + options = g_settings_get_strv (settings, KEY_KEYBOARD_OPTIONS); |
817 | + if (g_strv_length (options) < 1) |
818 | + convert_libgnomekbd_options (settings); |
819 | + g_strfreev (options); |
820 | + } |
821 | } |
822 | |
823 | static void |
824 | @@ -1708,10 +2211,12 @@ |
825 | if (is_set_input_source || is_activate_input_source) { |
826 | if (priv->invocation) { |
827 | #ifdef HAVE_IBUS |
828 | - /* This can only happen if there's an |
829 | - * ibus_bus_set_global_engine_async() call |
830 | - * going on. */ |
831 | - g_cancellable_cancel (priv->ibus_cancellable); |
832 | + if (priv->is_ibus_active) { |
833 | + /* This can only happen if there's an |
834 | + * ibus_bus_set_global_engine_async() call |
835 | + * going on. */ |
836 | + g_cancellable_cancel (priv->ibus_cancellable); |
837 | + } |
838 | #endif |
839 | g_clear_pointer (&priv->invocation, set_input_source_return); |
840 | priv->pending_ops = 0; |
841 | @@ -1840,13 +2345,46 @@ |
842 | register_manager_dbus (manager); |
843 | } |
844 | |
845 | +#ifdef HAVE_FCITX |
846 | +static void |
847 | +fcitx_appeared (GDBusConnection *connection, |
848 | + const gchar *name, |
849 | + const gchar *name_owner, |
850 | + gpointer user_data) |
851 | +{ |
852 | + GsdKeyboardManager *manager = user_data; |
853 | + apply_input_sources_settings (manager->priv->input_sources_settings, NULL, 0, manager); |
854 | +} |
855 | + |
856 | +static void |
857 | +fcitx_vanished (GDBusConnection *connection, |
858 | + const gchar *name, |
859 | + gpointer user_data) |
860 | +{ |
861 | + GsdKeyboardManager *manager = user_data; |
862 | + g_signal_handlers_disconnect_by_data (manager->priv->fcitx, manager); |
863 | + manager->priv->fcitx_signal_id = 0; |
864 | +} |
865 | +#endif |
866 | + |
867 | static gboolean |
868 | start_keyboard_idle_cb (GsdKeyboardManager *manager) |
869 | { |
870 | + const gchar *module; |
871 | + GError *error = NULL; |
872 | + |
873 | gnome_settings_profile_start (NULL); |
874 | |
875 | g_debug ("Starting keyboard manager"); |
876 | |
877 | + module = g_getenv (ENV_GTK_IM_MODULE); |
878 | +#ifdef HAVE_IBUS |
879 | + manager->priv->is_ibus_active = g_strcmp0 (module, GTK_IM_MODULE_IBUS) == 0; |
880 | +#endif |
881 | +#ifdef HAVE_FCITX |
882 | + manager->priv->is_fcitx_active = g_strcmp0 (module, GTK_IM_MODULE_FCITX) == 0; |
883 | +#endif |
884 | + |
885 | manager->priv->settings = g_settings_new (GSD_KEYBOARD_DIR); |
886 | |
887 | xkb_init (manager); |
888 | @@ -1857,6 +2395,38 @@ |
889 | manager->priv->interface_settings = g_settings_new (GNOME_DESKTOP_INTERFACE_DIR); |
890 | manager->priv->xkb_info = gnome_xkb_info_new (); |
891 | |
892 | +#ifdef HAVE_FCITX |
893 | + if (manager->priv->is_fcitx_active) { |
894 | + manager->priv->fcitx_cancellable = g_cancellable_new (); |
895 | + manager->priv->fcitx = fcitx_input_method_new (G_BUS_TYPE_SESSION, |
896 | + G_DBUS_PROXY_FLAGS_GET_INVALIDATED_PROPERTIES, |
897 | + 0, |
898 | + manager->priv->fcitx_cancellable, |
899 | + &error); |
900 | + g_clear_object (&manager->priv->fcitx_cancellable); |
901 | + |
902 | + if (manager->priv->fcitx) { |
903 | + manager->priv->fcitx_signal_id = 0; |
904 | + |
905 | + g_bus_watch_name (G_BUS_TYPE_SESSION, |
906 | + "org.fcitx.Fcitx", |
907 | + G_BUS_NAME_WATCHER_FLAGS_NONE, |
908 | + fcitx_appeared, |
909 | + fcitx_vanished, |
910 | + manager, |
911 | + NULL); |
912 | + |
913 | + if (should_migrate ("fcitx-engines-migrated")) |
914 | + migrate_fcitx_engines (manager); |
915 | + else |
916 | + enable_fcitx_engines (manager, FALSE); |
917 | + } else { |
918 | + g_warning ("Fcitx input method framework unavailable: %s", error->message); |
919 | + g_error_free (error); |
920 | + } |
921 | + } |
922 | +#endif |
923 | + |
924 | manager->priv->cancellable = g_cancellable_new (); |
925 | |
926 | g_dbus_proxy_new_for_bus (G_BUS_TYPE_SYSTEM, |
927 | @@ -1933,8 +2503,21 @@ |
928 | g_clear_object (&p->xkb_info); |
929 | g_clear_object (&p->localed); |
930 | |
931 | +#ifdef HAVE_FCITX |
932 | + if (p->is_fcitx_active) { |
933 | + if (p->fcitx_cancellable) { |
934 | + g_cancellable_cancel (p->fcitx_cancellable); |
935 | + } |
936 | + |
937 | + g_clear_object (&p->fcitx_cancellable); |
938 | + g_clear_object (&p->fcitx); |
939 | + } |
940 | +#endif |
941 | + |
942 | #ifdef HAVE_IBUS |
943 | - clear_ibus (manager); |
944 | + if (p->is_ibus_active) { |
945 | + clear_ibus (manager); |
946 | + } |
947 | #endif |
948 | |
949 | if (p->device_manager != NULL) { |
950 | |
951 | === added file 'plugins/keyboard/input-method-engines.gperf' |
952 | --- plugins/keyboard/input-method-engines.gperf 1970-01-01 00:00:00 +0000 |
953 | +++ plugins/keyboard/input-method-engines.gperf 2015-02-12 15:57:03 +0000 |
954 | @@ -0,0 +1,203 @@ |
955 | +%pic |
956 | +%struct-type |
957 | +%readonly-tables |
958 | +%define slot-name ibus_engine |
959 | +%define hash-function-name ibus_engine_hash |
960 | +%define lookup-function-name get_engine_for_ibus_engine |
961 | +struct Engine { int ibus_engine; const char *fcitx_engine; }; |
962 | +%% |
963 | +Unikey, "unikey" |
964 | +anthy, "anthy" |
965 | +array, "array30" |
966 | +array30, "array30" |
967 | +array30-big, "array30-big" |
968 | +bopomofo, "zhuyin-libpinyin" |
969 | +cangjie, "cangjie3" |
970 | +cangjie-big, "cangjie-big" |
971 | +cangjie3, "cangjie3" |
972 | +cangjie5, "cangjie5" |
973 | +cantonese, "cantonese" |
974 | +cantonhk, "cantonhk" |
975 | +chewing, "chewing" |
976 | +cns11643, "cns11643" |
977 | +compose, "compose" |
978 | +easy-big, "easy-big" |
979 | +emoji-table, "emoji" |
980 | +erbi, "erbi" |
981 | +erbi-qs, "erbi" |
982 | +googlepinyin, "googlepinyin" |
983 | +hangul, "hangul" |
984 | +# input-pad, NULL |
985 | +ipa-x-sampa, "ipa-x-sampa" |
986 | +jyutping, "jyutping" |
987 | +latex, "latex" |
988 | +libbopomofo, "zhuyin-libpinyin" |
989 | +libpinyin, "pinyin-libpinyin" |
990 | +libthai, "thai" |
991 | +m17n:am:sera, "m17n_am_sera" |
992 | +m17n:ar:kbd, "arabic" |
993 | +m17n:as:inscript, "m17n_as_inscript" |
994 | +m17n:as:itrans, "m17n_as_itrans" |
995 | +m17n:as:phonetic, "m17n_as_phonetic" |
996 | +m17n:ath:phonetic, "m17n_ath_phonetic" |
997 | +m17n:be:kbd, "fcitx-keyboard-by" |
998 | +m17n:bla:phonetic, "m17n_bla_phonetic" |
999 | +m17n:bn:disha, "m17n_bn_disha" |
1000 | +m17n:bn:inscript, "m17n_bn_inscript" |
1001 | +m17n:bn:itrans, "m17n_bn_itrans" |
1002 | +m17n:bn:probhat, "m17n_bn_probhat" |
1003 | +m17n:bn:unijoy, "m17n_bn_unijoy" |
1004 | +m17n:bo:ewts, "m17n_bo_ewts" |
1005 | +m17n:bo:tcrc, "m17n_bo_tcrc" |
1006 | +m17n:bo:wylie, "m17n_bo_wylie" |
1007 | +# m17n:cmc:kbd, NULL |
1008 | +m17n:cr:western, "m17n_cr_western" |
1009 | +m17n:cs:kbd, "fcitx-keyboard-cz-qwerty_bksl" |
1010 | +m17n:da:post, "m17n_da_post" |
1011 | +m17n:dv:phonetic, "m17n_dv_phonetic" |
1012 | +m17n:el:kbd, "fcitx-keyboard-gr-simple" |
1013 | +m17n:eo:h-fundamente, "m17n_eo_h-fundamente" |
1014 | +m17n:eo:h-sistemo, "m17n_eo_h-sistemo" |
1015 | +m17n:eo:plena, "m17n_eo_plena" |
1016 | +m17n:eo:q-sistemo, "m17n_eo_q-sistemo" |
1017 | +m17n:eo:vi-sistemo, "m17n_eo_vi-sistemo" |
1018 | +m17n:eo:x-sistemo, "m17n_eo_x-sistemo" |
1019 | +m17n:fa:isiri, "m17n_fa_isiri" |
1020 | +m17n:fr:azerty, "m17n_fr_azerty" |
1021 | +m17n:grc:mizuochi, "m17n_grc_mizuochi" |
1022 | +m17n:gu:inscript, "m17n_gu_inscript" |
1023 | +m17n:gu:itrans, "m17n_gu_itrans" |
1024 | +m17n:gu:phonetic, "m17n_gu_phonetic" |
1025 | +m17n:he:kbd, "fcitx-keyboard-il" |
1026 | +m17n:hi:inscript, "m17n_hi_inscript" |
1027 | +m17n:hi:itrans, "m17n_hi_itrans" |
1028 | +m17n:hi:phonetic, "m17n_hi_phonetic" |
1029 | +m17n:hi:remington, "m17n_hi_remington" |
1030 | +m17n:hi:typewriter, "m17n_hi_typewriter" |
1031 | +m17n:hi:vedmata, "m17n_hi_vedmata" |
1032 | +m17n:hr:kbd, "fcitx-keyboard-hr" |
1033 | +m17n:hy:kbd, "fcitx-keyboard-am-eastern-alt" |
1034 | +m17n:ii:phonetic, "m17n_ii_phonetic" |
1035 | +m17n:iu:phonetic, "m17n_iu_phonetic" |
1036 | +m17n:ja:tcode, "m17n_ja_tcode" |
1037 | +m17n:ja:trycode, "m17n_ja_trycode" |
1038 | +m17n:ka:kbd, "fcitx-keyboard-ge" |
1039 | +m17n:kk:arabic, "m17n_kk_arabic" |
1040 | +m17n:kk:kbd, "fcitx-keyboard-kz" |
1041 | +m17n:km:yannis, "m17n_km_yannis" |
1042 | +m17n:kn:inscript, "m17n_kn_inscript" |
1043 | +m17n:kn:itrans, "m17n_kn_itrans" |
1044 | +m17n:kn:kgp, "m17n_kn_kgp" |
1045 | +m17n:kn:typewriter, "m17n_kn_typewriter" |
1046 | +# m17n:ko:han2, NULL |
1047 | +# m17n:ko:romaja, NULL |
1048 | +m17n:ks:inscript, "m17n_ks_inscript" |
1049 | +m17n:ks:kbd, "m17n_ks_kbd" |
1050 | +m17n:lo:kbd, "fcitx-keyboard-la-stea" |
1051 | +m17n:lo:lrt, "m17n_lo_lrt" |
1052 | +m17n:mai:inscript, "m17n_mai_inscript" |
1053 | +m17n:ml:inscript, "m17n_ml_inscript" |
1054 | +m17n:ml:itrans, "m17n_ml_itrans" |
1055 | +m17n:ml:mozhi, "m17n_ml_mozhi" |
1056 | +m17n:ml:remington, "m17n_ml_remington" |
1057 | +m17n:ml:swanalekha, "m17n_ml_swanalekha" |
1058 | +m17n:mr:inscript, "m17n_mr_inscript" |
1059 | +m17n:mr:itrans, "m17n_mr_itrans" |
1060 | +m17n:mr:phonetic, "m17n_mr_phonetic" |
1061 | +m17n:my:kbd, "fcitx-keyboard-mm" |
1062 | +m17n:ne:rom, "m17n_ne_rom" |
1063 | +m17n:ne:trad, "m17n_ne_trad" |
1064 | +m17n:nsk:phonetic, "m17n_nsk_phonetic" |
1065 | +m17n:oj:phonetic, "m17n_oj_phonetic" |
1066 | +m17n:or:inscript, "m17n_or_inscript" |
1067 | +m17n:or:itrans, "m17n_or_itrans" |
1068 | +m17n:or:phonetic, "m17n_or_phonetic" |
1069 | +m17n:pa:anmollipi, "m17n_pa_anmollipi" |
1070 | +m17n:pa:inscript, "m17n_pa_inscript" |
1071 | +m17n:pa:itrans, "m17n_pa_itrans" |
1072 | +m17n:pa:jhelum, "m17n_pa_jhelum" |
1073 | +m17n:pa:phonetic, "m17n_pa_phonetic" |
1074 | +m17n:ps:phonetic, "m17n_ps_phonetic" |
1075 | +m17n:ru:kbd, "fcitx-keyboard-ru" |
1076 | +m17n:ru:phonetic, "m17n_ru_phonetic" |
1077 | +m17n:ru:translit, "m17n_ru_translit" |
1078 | +m17n:ru:yawerty, "m17n_ru_yawerty" |
1079 | +m17n:sa:IAST, "m17n_sa_IAST" |
1080 | +m17n:sa:harvard-kyoto, "m17n_sa_harvard-kyoto" |
1081 | +m17n:sa:itrans, "m17n_sa_itrans" |
1082 | +m17n:sd:inscript, "m17n_sd_inscript" |
1083 | +m17n:si:phonetic-dynamic, "m17n_si_phonetic-dynamic" |
1084 | +m17n:si:samanala, "m17n_si_samanala" |
1085 | +m17n:si:singlish, "m17n_si_singlish" |
1086 | +m17n:si:sumihiri, "m17n_si_sumihiri" |
1087 | +m17n:si:transliteration, "m17n_si_transliteration" |
1088 | +m17n:si:wijesekera, "m17n_si_wijesekera" |
1089 | +m17n:sk:kbd, "fcitx-keyboard-sk" |
1090 | +m17n:sr:kbd, "fcitx-keyboard-rs" |
1091 | +m17n:sv:post, "m17n_sv_post" |
1092 | +m17n:t:latn-post, "m17n_t_latn-post" |
1093 | +m17n:t:latn-pre, "m17n_t_latn-pre" |
1094 | +m17n:t:math-latex, "m17n_t_math-latex" |
1095 | +m17n:t:rfc1345, "m17n_t_rfc1345" |
1096 | +m17n:t:syrc-phonetic, "m17n_t_syrc-phonetic" |
1097 | +m17n:t:unicode, "m17n_t_unicode" |
1098 | +m17n:ta:inscript, "m17n_ta_inscript" |
1099 | +m17n:ta:itrans, "m17n_ta_itrans" |
1100 | +m17n:ta:lk-renganathan, "m17n_ta_lk-renganathan" |
1101 | +m17n:ta:phonetic, "m17n_ta_phonetic" |
1102 | +m17n:ta:tamil99, "m17n_ta_tamil99" |
1103 | +m17n:ta:typewriter, "m17n_ta_typewriter" |
1104 | +m17n:ta:vutam, "m17n_ta_vutam" |
1105 | +m17n:tai:sonla-kbd, "m17n_tai_sonla-kbd" |
1106 | +m17n:te:apple, "m17n_te_apple" |
1107 | +m17n:te:inscript, "m17n_te_inscript" |
1108 | +m17n:te:itrans, "m17n_te_itrans" |
1109 | +m17n:te:pothana, "m17n_te_pothana" |
1110 | +m17n:te:rts, "m17n_te_rts" |
1111 | +m17n:te:sarala, "m17n_te_sarala" |
1112 | +m17n:th:kesmanee, "m17n_th_kesmanee" |
1113 | +m17n:th:pattachote, "m17n_th_pattachote" |
1114 | +m17n:th:tis820, "m17n_th_tis820" |
1115 | +m17n:ua:kbd, "fcitx-keyboard-ua" |
1116 | +m17n:ug:kbd, "fcitx-keyboard-cn-ug" |
1117 | +m17n:ur:phonetic, "m17n_ur_phonetic" |
1118 | +m17n:uz:kbd, "fcitx-keyboard-uz" |
1119 | +m17n:vi:han, "m17n_vi_han" |
1120 | +m17n:vi:nomtelex, "m17n_vi_nomtelex" |
1121 | +m17n:vi:nomvni, "m17n_vi_nomvni" |
1122 | +m17n:vi:tcvn, "m17n_vi_tcvn" |
1123 | +m17n:vi:telex, "m17n_vi_telex" |
1124 | +m17n:vi:viqr, "m17n_vi_viqr" |
1125 | +m17n:vi:vni, "m17n_vi_vni" |
1126 | +m17n:yi:yivo, "m17n_yi_yivo" |
1127 | +m17n:zh:bopomofo, "m17n_zh_bopomofo" |
1128 | +m17n:zh:cangjie, "cangjie3" |
1129 | +m17n:zh:pinyin, "m17n_zh_pinyin" |
1130 | +m17n:zh:pinyin-vi, "m17n_zh_pinyin-vi" |
1131 | +# m17n:zh:py, NULL |
1132 | +m17n:zh:quick, "quick3" |
1133 | +# m17n:zh:tonepy, NULL |
1134 | +mozc-jp, "mozc" |
1135 | +pinyin, "pinyin" |
1136 | +quick, "quick3" |
1137 | +quick-classic, "quick-classic" |
1138 | +quick3, "quick3" |
1139 | +quick5, "quick5" |
1140 | +rime, "rime" |
1141 | +rustrad, "rustrad" |
1142 | +scj6, "scj6" |
1143 | +skk, "skk" |
1144 | +stroke5, "stroke5" |
1145 | +sunpinyin, "sunpinyin" |
1146 | +# tegaki, NULL |
1147 | +thai, "thai" |
1148 | +translit, "translit" |
1149 | +translit-ua, "translit-ua" |
1150 | +viqr, "viqr" |
1151 | +wu, "wu" |
1152 | +wubi-haifeng86, "wubi" |
1153 | +wubi-jidian86, "wubi" |
1154 | +# xkbc, NULL |
1155 | +yawerty, "yawerty" |
1156 | +# yong, NULL |
1157 | +%% |
1158 | |
1159 | === modified file 'plugins/media-keys/gsd-media-keys-manager.c' |
1160 | --- plugins/media-keys/gsd-media-keys-manager.c 2014-12-03 02:42:39 +0000 |
1161 | +++ plugins/media-keys/gsd-media-keys-manager.c 2015-02-12 15:57:03 +0000 |
1162 | @@ -67,6 +67,10 @@ |
1163 | |
1164 | #include <libnotify/notify.h> |
1165 | |
1166 | +#ifdef HAVE_FCITX |
1167 | +#include <fcitx-gclient/fcitxinputmethod.h> |
1168 | +#endif |
1169 | + |
1170 | #define GSD_MEDIA_KEYS_DBUS_PATH GSD_DBUS_PATH "/MediaKeys" |
1171 | #define GSD_MEDIA_KEYS_DBUS_NAME GSD_DBUS_NAME ".MediaKeys" |
1172 | |
1173 | @@ -116,10 +120,20 @@ |
1174 | |
1175 | #define VOLUME_STEP 6 /* percents for one volume button press */ |
1176 | |
1177 | +#define ENV_GTK_IM_MODULE "GTK_IM_MODULE" |
1178 | +#define GTK_IM_MODULE_IBUS "ibus" |
1179 | +#define GTK_IM_MODULE_FCITX "fcitx" |
1180 | + |
1181 | #define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources" |
1182 | #define KEY_CURRENT_INPUT_SOURCE "current" |
1183 | #define KEY_INPUT_SOURCES "sources" |
1184 | |
1185 | +#define INPUT_SOURCE_TYPE_XKB "xkb" |
1186 | +#define INPUT_SOURCE_TYPE_IBUS "ibus" |
1187 | +#define INPUT_SOURCE_TYPE_FCITX "fcitx" |
1188 | + |
1189 | +#define FCITX_XKB_PREFIX "fcitx-keyboard-" |
1190 | + |
1191 | #define SYSTEMD_DBUS_NAME "org.freedesktop.login1" |
1192 | #define SYSTEMD_DBUS_PATH "/org/freedesktop/login1" |
1193 | #define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager" |
1194 | @@ -218,6 +232,13 @@ |
1195 | guint panel_name_owner_id; |
1196 | guint have_legacy_keygrabber; |
1197 | |
1198 | +#ifdef HAVE_FCITX |
1199 | + FcitxInputMethod *fcitx; |
1200 | +#endif |
1201 | + |
1202 | + gboolean is_ibus_active; |
1203 | + gboolean is_fcitx_active; |
1204 | + |
1205 | /* What did you plug in dialog */ |
1206 | pa_backend *wdypi_pa_backend; |
1207 | }; |
1208 | @@ -2131,16 +2152,53 @@ |
1209 | |
1210 | } |
1211 | |
1212 | +#ifdef HAVE_FCITX |
1213 | +static gchar * |
1214 | +get_fcitx_name (const gchar *name) |
1215 | +{ |
1216 | + gchar *fcitx_name = g_strdup (name); |
1217 | + gchar *separator = strchr (fcitx_name, '+'); |
1218 | + |
1219 | + if (separator) |
1220 | + *separator = '-'; |
1221 | + |
1222 | + return fcitx_name; |
1223 | +} |
1224 | + |
1225 | +static gboolean |
1226 | +input_source_is_fcitx_engine (const gchar *type, |
1227 | + const gchar *name, |
1228 | + const gchar *engine) |
1229 | +{ |
1230 | + if (g_str_equal (type, INPUT_SOURCE_TYPE_XKB)) { |
1231 | + if (g_str_has_prefix (engine, FCITX_XKB_PREFIX)) { |
1232 | + gboolean equal; |
1233 | + gchar *fcitx_name = get_fcitx_name (name); |
1234 | + equal = g_str_equal (fcitx_name, engine + strlen (FCITX_XKB_PREFIX)); |
1235 | + g_free (fcitx_name); |
1236 | + return equal; |
1237 | + } |
1238 | + } else if (g_str_equal (type, INPUT_SOURCE_TYPE_FCITX)) { |
1239 | + return g_str_equal (name, engine); |
1240 | + } |
1241 | + |
1242 | + return FALSE; |
1243 | +} |
1244 | +#endif |
1245 | + |
1246 | static void |
1247 | do_switch_input_source_action (GsdMediaKeysManager *manager, |
1248 | MediaKeyType type) |
1249 | { |
1250 | + GsdMediaKeysManagerPrivate *priv = manager->priv; |
1251 | GSettings *settings; |
1252 | GVariant *sources; |
1253 | + const gchar *source_type; |
1254 | + guint first; |
1255 | gint i, n; |
1256 | |
1257 | if (g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "ubuntu") != 0) |
1258 | - if (!manager->priv->have_legacy_keygrabber) |
1259 | + if (!priv->have_legacy_keygrabber) |
1260 | return; |
1261 | |
1262 | settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR); |
1263 | @@ -2150,19 +2208,52 @@ |
1264 | if (n < 2) |
1265 | goto out; |
1266 | |
1267 | - i = g_settings_get_uint (settings, KEY_CURRENT_INPUT_SOURCE); |
1268 | - |
1269 | - if (type == SWITCH_INPUT_SOURCE_KEY) |
1270 | - i += 1; |
1271 | - else |
1272 | - i -= 1; |
1273 | + i = -1; |
1274 | + |
1275 | +#ifdef HAVE_FCITX |
1276 | + if (priv->is_fcitx_active && priv->fcitx) { |
1277 | + gchar *engine = fcitx_input_method_get_current_im (priv->fcitx); |
1278 | + |
1279 | + if (engine) { |
1280 | + GVariantIter iter; |
1281 | + const gchar *source_name; |
1282 | + |
1283 | + g_variant_iter_init (&iter, sources); |
1284 | + for (i = 0; g_variant_iter_next (&iter, "(&s&s)", &source_type, &source_name); i++) { |
1285 | + if (input_source_is_fcitx_engine (source_type, source_name, engine)) { |
1286 | + break; |
1287 | + } |
1288 | + } |
1289 | + |
1290 | + if (i >= g_variant_n_children (sources)) |
1291 | + i = -1; |
1292 | + |
1293 | + g_free (engine); |
1294 | + } |
1295 | + } |
1296 | +#endif |
1297 | |
1298 | if (i < 0) |
1299 | - i = n - 1; |
1300 | - else if (i >= n) |
1301 | - i = 0; |
1302 | - |
1303 | - g_settings_set_uint (settings, KEY_CURRENT_INPUT_SOURCE, i); |
1304 | + i = g_settings_get_uint (settings, KEY_CURRENT_INPUT_SOURCE); |
1305 | + |
1306 | + first = i; |
1307 | + |
1308 | + if (type == SWITCH_INPUT_SOURCE_KEY) { |
1309 | + do { |
1310 | + i = (i + 1) % n; |
1311 | + g_variant_get_child (sources, i, "(&s&s)", &source_type, NULL); |
1312 | + } while (i != first && ((g_str_equal (source_type, INPUT_SOURCE_TYPE_IBUS) && !priv->is_ibus_active) || |
1313 | + (g_str_equal (source_type, INPUT_SOURCE_TYPE_FCITX) && !priv->is_fcitx_active))); |
1314 | + } else { |
1315 | + do { |
1316 | + i = (i + n - 1) % n; |
1317 | + g_variant_get_child (sources, i, "(&s&s)", &source_type, NULL); |
1318 | + } while (i != first && ((g_str_equal (source_type, INPUT_SOURCE_TYPE_IBUS) && !priv->is_ibus_active) || |
1319 | + (g_str_equal (source_type, INPUT_SOURCE_TYPE_FCITX) && !priv->is_fcitx_active))); |
1320 | + } |
1321 | + |
1322 | + if (i != first) |
1323 | + g_settings_set_uint (settings, KEY_CURRENT_INPUT_SOURCE, i); |
1324 | |
1325 | out: |
1326 | g_variant_unref (sources); |
1327 | @@ -2931,11 +3022,35 @@ |
1328 | static gboolean |
1329 | start_media_keys_idle_cb (GsdMediaKeysManager *manager) |
1330 | { |
1331 | + const gchar *module; |
1332 | char *theme_name; |
1333 | |
1334 | g_debug ("Starting media_keys manager"); |
1335 | gnome_settings_profile_start (NULL); |
1336 | |
1337 | + module = g_getenv (ENV_GTK_IM_MODULE); |
1338 | +#ifdef HAVE_IBUS |
1339 | + manager->priv->is_ibus_active = g_strcmp0 (module, GTK_IM_MODULE_IBUS) == 0; |
1340 | +#endif |
1341 | +#ifdef HAVE_FCITX |
1342 | + manager->priv->is_fcitx_active = g_strcmp0 (module, GTK_IM_MODULE_FCITX) == 0; |
1343 | + |
1344 | + if (manager->priv->is_fcitx_active) { |
1345 | + GError *error = NULL; |
1346 | + |
1347 | + manager->priv->fcitx = fcitx_input_method_new (G_BUS_TYPE_SESSION, |
1348 | + G_DBUS_PROXY_FLAGS_NONE, |
1349 | + 0, |
1350 | + NULL, |
1351 | + &error); |
1352 | + |
1353 | + if (!manager->priv->fcitx) { |
1354 | + g_warning ("Fcitx connection unavailable: %s", error->message); |
1355 | + g_error_free (error); |
1356 | + } |
1357 | + } |
1358 | +#endif |
1359 | + |
1360 | manager->priv->keys = g_ptr_array_new_with_free_func ((GDestroyNotify) media_key_free); |
1361 | |
1362 | initialize_volume_handler (manager); |
PASSED: Continuous integration, rev:4048 jenkins. qa.ubuntu. com/job/ unity-settings- daemon- ci/34/ jenkins. qa.ubuntu. com/job/ unity-settings- daemon- utopic- amd64-ci/ 8 jenkins. qa.ubuntu. com/job/ unity-settings- daemon- utopic- armhf-ci/ 8 jenkins. qa.ubuntu. com/job/ unity-settings- daemon- utopic- i386-ci/ 8
http://
Executed test runs:
SUCCESS: http://
SUCCESS: http://
SUCCESS: http://
Click here to trigger a rebuild: s-jenkins. ubuntu- ci:8080/ job/unity- settings- daemon- ci/34/rebuild
http://