1 From 15a9eb2a8f9a278b5e357d7dd7ffebedd05d0c5e Mon Sep 17 00:00:00 2001
2 From: fujiwarat <takao.fujiwara1@gmail.com>
3 Date: Tue, 9 Oct 2012 17:21:01 +0900
4 Subject: [PATCH] Add ibus-xkb and libgnomekbd.
7 bindings/vala/Gkbd-3.0.metadata | 1 +
8 bindings/vala/Makefile.am | 23 ++
9 bindings/vala/Xkl-1.0.metadata | 3 +
10 client/x11/gdk-private.c | 3 +-
11 configure.ac | 60 +++++
12 data/ibus.schemas.in | 94 +++++++
13 engine/Makefile.am | 6 +
14 engine/ibus-xkb/Makefile.am | 64 +++++
15 engine/ibus-xkb/ibus-xkb-main.c | 111 ++++++++
16 engine/ibus-xkb/xkblib.c | 327 ++++++++++++++++++++++++
17 engine/ibus-xkb/xkblib.h | 41 +++
18 engine/main.vala | 86 +++++++
19 engine/simple.xml.in.in | 531 +--------------------------------------
22 setup/main.py | 38 ++-
25 src/ibusxkbxml.c | 466 ++++++++++++++++++++++++++++++++++
26 src/ibusxkbxml.h | 187 ++++++++++++++
27 ui/gtk3/Makefile.am | 39 +++
28 ui/gtk3/gkbdlayout.vala.false | 63 +++++
29 ui/gtk3/gkbdlayout.vala.true | 108 ++++++++
30 ui/gtk3/keybindingmanager.vala | 14 +-
31 ui/gtk3/panel.vala | 365 +++++++++++++++++++++++----
32 ui/gtk3/switcher.vala | 49 ++--
33 ui/gtk3/xkblayout.vala | 464 ++++++++++++++++++++++++++++++++++
34 27 files changed, 2562 insertions(+), 603 deletions(-)
35 create mode 100644 bindings/vala/Gkbd-3.0.metadata
36 create mode 100644 bindings/vala/Xkl-1.0.metadata
37 create mode 100644 engine/ibus-xkb/Makefile.am
38 create mode 100644 engine/ibus-xkb/ibus-xkb-main.c
39 create mode 100644 engine/ibus-xkb/xkblib.c
40 create mode 100644 engine/ibus-xkb/xkblib.h
41 create mode 100644 src/ibusxkbxml.c
42 create mode 100644 src/ibusxkbxml.h
43 create mode 100644 ui/gtk3/gkbdlayout.vala.false
44 create mode 100644 ui/gtk3/gkbdlayout.vala.true
45 create mode 100644 ui/gtk3/xkblayout.vala
47 diff --git a/bindings/vala/Gkbd-3.0.metadata b/bindings/vala/Gkbd-3.0.metadata
49 index 0000000..661e6fd
51 +++ b/bindings/vala/Gkbd-3.0.metadata
53 +Configuration cheader_filename="libgnomekbd/gkbd-configuration.h"
54 diff --git a/bindings/vala/Makefile.am b/bindings/vala/Makefile.am
55 index abcc543..307a161 100644
56 --- a/bindings/vala/Makefile.am
57 +++ b/bindings/vala/Makefile.am
58 @@ -27,12 +27,22 @@ dist_vapi_DATA = \
61 # Don't rebuild vapi every time gir is updated.
62 +if ENABLE_LIBGNOMEKBD
64 $(srcdir)/IBus-1.0.metadata \
65 $(srcdir)/IBus-1.0-custom.vala \
67 + $(builddir)/gkbd.vapi \
68 $(top_srcdir)/src/IBus-@IBUS_API_VERSION@.gir \
72 + $(srcdir)/IBus-1.0.metadata \
73 + $(srcdir)/IBus-1.0-custom.vala \
75 + $(top_srcdir)/src/IBus-@IBUS_API_VERSION@.gir \
79 ibus-@IBUS_API_VERSION@.vapi: $(vapi_deps)
80 $(AM_V_GEN) $(VAPIGEN) --library ibus-@IBUS_API_VERSION@ \
81 @@ -41,13 +51,26 @@ ibus-@IBUS_API_VERSION@.vapi: $(vapi_deps)
82 $(top_srcdir)/src/IBus-@IBUS_API_VERSION@.gir \
83 $(srcdir)/IBus-1.0-custom.vala
85 +if ENABLE_LIBGNOMEKBD
86 +$(builddir)/gkbd.vapi:
87 + $(AM_V_GEN) $(VAPIGEN) --library gkbd \
88 + --metadatadir $(srcdir) \
89 + --pkg gtk+-3.0 --pkg glib-2.0 --pkg gmodule-2.0 \
90 + /usr/share/gir-1.0/Gkbd-3.0.gir
97 IBus-1.0-custom.vala \
103 +CLEANFILES = gkbd.vapi
105 MAINTAINERCLEANFILES = ibus-@IBUS_API_VERSION@.vapi
107 -include $(top_srcdir)/git.mk
108 diff --git a/bindings/vala/Xkl-1.0.metadata b/bindings/vala/Xkl-1.0.metadata
110 index 0000000..4961d0c
112 +++ b/bindings/vala/Xkl-1.0.metadata
114 +Xkl cheader_filename="libxklavier/xklavier.h"
116 + .filter_events.evt ref type="X.Event"
117 diff --git a/client/x11/gdk-private.c b/client/x11/gdk-private.c
118 index 009a5b0..20689c3 100644
119 --- a/client/x11/gdk-private.c
120 +++ b/client/x11/gdk-private.c
122 #include <gdk/gdkx.h>
123 #include <gdk/gdkkeysyms.h>
125 -#ifdef HAVE_X11_XKBLIB_H
128 # include <X11/XKBlib.h>
131 diff --git a/configure.ac b/configure.ac
132 index cc7d0e0..df0d4a7 100644
135 @@ -252,6 +252,63 @@ else
136 enable_xim="no (disabled, use --enable-xim to enable)"
139 +# --enable-xkb option.
141 + AS_HELP_STRING([--enable-xkb],
143 + [enable_xkb=$enableval],
146 +AM_CONDITIONAL([ENABLE_XKB], [test x"$enable_xkb" = x"yes"])
147 +if test x"$enable_xkb" = x"yes"; then
148 + PKG_CHECK_MODULES(X11, [
151 + PKG_CHECK_MODULES(XKB,
153 + [XKB_LIBS="-lxkbfile"]
155 + AC_DEFINE(HAVE_XKB, 1, [define to 1 if you have xkbfile])
158 + enable_xkb="no (disabled, use --enable-xkb to enable)"
159 + HAVE_IBUS_XKB=false
161 +AC_SUBST(HAVE_IBUS_XKB)
163 +# --enable-libgnomekbd option.
164 +AC_ARG_ENABLE(libgnomekbd,
165 + AS_HELP_STRING([--enable-libgnomekbd],
166 + [Use libgnomekbd to handle the keymaps]),
167 + [enable_libgnomekbd=$enableval],
168 + [enable_libgnomekbd=no]
170 +AM_CONDITIONAL([ENABLE_LIBGNOMEKBD], [test x"$enable_libgnomekbd" = x"yes"])
171 +if test x"$enable_libgnomekbd" = x"yes"; then
172 + # check for libgnomekbd
173 + PKG_CHECK_MODULES(LIBGNOMEKBDUI, [
176 + PKG_CHECK_MODULES(ATK, [
179 + HAVE_IBUS_GKBD=true
181 + enable_libgnomekbd="no (disabled, use --enable-libgnomekbd to enable)"
182 + HAVE_IBUS_GKBD=false
184 +AC_SUBST(HAVE_IBUS_GKBD)
186 +# Define XKB rules file
187 +AC_ARG_WITH(xkb-rules-xml,
188 + AS_HELP_STRING([--with-xkb-rules-xml[=$DIR/evdev.xml]],
189 + [Set evdev.xml file path (default: /usr/share/X11/xkb/rules/evdev.xml)]),
190 + XKB_RULES_XML_FILE=$with_xkb_rules_xml,
191 + XKB_RULES_XML_FILE="/usr/share/X11/xkb/rules/evdev.xml"
193 +AC_DEFINE_UNQUOTED(XKB_RULES_XML_FILE, "$XKB_RULES_XML_FILE",
194 + [Define file path of evdev.xml])
196 # GObject introspection
197 GOBJECT_INTROSPECTION_CHECK([0.6.8])
199 @@ -517,6 +574,7 @@ src/ibusversion.h
203 +engine/ibus-xkb/Makefile
207 @@ -577,5 +635,7 @@ Build options:
208 Panel icon "$IBUS_ICON_KEYBOARD"
209 Enable surrounding-text $enable_surrounding_text
210 Run test cases $enable_tests
211 + Build XKB $enable_xkb
212 + Build libgnomebkd $enable_libgnomekbd
215 diff --git a/data/ibus.schemas.in b/data/ibus.schemas.in
216 index 53ba05c..07169ae 100644
217 --- a/data/ibus.schemas.in
218 +++ b/data/ibus.schemas.in
223 + <key>/schemas/desktop/ibus/general/use_xmodmap</key>
224 + <applyto>/desktop/ibus/general/use_xmodmap</applyto>
225 + <owner>ibus</owner>
227 + <default>true</default>
229 + <short>Use xmodmap</short>
230 + <long>Run xmodmap if .xmodmap/.Xmodmap exists.</long>
234 + <key>/schemas/desktop/ibus/general/xkb_latin_layouts</key>
235 + <applyto>/desktop/ibus/general/xkb_latin_layouts</applyto>
236 + <owner>ibus</owner>
238 + <list_type>string</list_type>
239 + <default>[ara,bg,cz,dev,gr,gur,in,jp(kana),mal,mkd,ru,ua]</default>
241 + <short>Latin layout which have no ASCII</short>
242 + <long>us layout is appended to the latin layouts. variant is not needed.</long>
246 + <key>/schemas/desktop/ibus/general/load_xkb_layouts</key>
247 + <applyto>/desktop/ibus/general/load_xkb_layouts</applyto>
248 + <owner>ibus</owner>
250 + <list_type>string</list_type>
251 + <default>[us,us(chr),us(dvorak),ad,al,am,ara,az,ba,bd,be,bg,br,bt,by,
252 +de,dk,ca,ch,cn(tib),cz,ee,epo,es,et,fi,fo,fr,
253 +gb,ge,ge(dsb),ge(ru),ge(os),gh,gh(akan),gh(ewe),gh(fula),gh(ga),gh(hausa),
254 +gn,gr,hu,hr,ie,ie(CloGaelach),il,
256 +in(tel),in(bolnagri),iq,iq(ku),ir,ir(ku),is,it,jp,
257 +kg,kh,kz,la,latam,lk,lk(tam_unicode),lt,lv,ma,ma(tifinagh),mal,mao,
258 +me,mk,mm,mt,mv,ng,ng(hausa),ng,ng(igbo),ng(yoruba),nl,no,no(smi),np,
259 +pk,pl,pl(csb),pt,ro,rs,ru,ru(cv),ru(kom),ru(sah),ru(tt),ru(xal),
260 +se,si,sk,sy,sy(ku),th,tj,tr,ua,uz,vn
263 + <short>XKB layout list which is shown on ibus-setup</short>
264 + <long>XKB layout list which is shown on ibus-setup.
265 + The format is "layout" or "layout(variant)".</long>
269 <key>/schemas/desktop/ibus/general/hotkey/trigger</key>
270 <applyto>/desktop/ibus/general/hotkey/trigger</applyto>
273 <default>[Control+space,Zenkaku_Hankaku,Alt+Kanji,Alt+grave,Hangul,Alt+Release+Alt_R]</default>
275 <short>Trigger shortcut keys</short>
276 + <long>The shortcut keys for turning input method on or off</long>
280 + <key>/schemas/desktop/ibus/general/hotkey/trigger_accel</key>
281 + <applyto>/desktop/ibus/general/hotkey/trigger_accel</applyto>
282 + <owner>ibus</owner>
284 + <list_type>string</list_type>
285 + <default>[<Control>space]</default>
287 + <short>Trigger shortcut keys for gtk_accelerator_parse</short>
288 + <long>The shortcut keys for turning input method on or off</long>
292 + <key>/schemas/desktop/ibus/general/hotkey/trigger_accel_backward</key>
293 + <applyto>/desktop/ibus/general/hotkey/trigger_accel_backward</applyto>
294 + <owner>ibus</owner>
296 + <list_type>string</list_type>
297 + <default>[<Control><Shift>space]</default>
299 + <short>Trigger reverse shortcut keys for gtk_accelerator_parse</short>
300 + <long>The reverse shortcut keys for turning input method on or off</long>
304 + <key>/schemas/desktop/ibus/general/hotkey/trigger_ja</key>
305 + <applyto>/desktop/ibus/general/hotkey/trigger_ja</applyto>
306 + <owner>ibus</owner>
308 + <list_type>string</list_type>
309 + <default>[Zenkaku_Hankaku]</default>
311 + <short>Trigger shortcut keys for ja gtk_accelerator_parse</short>
312 + <long>The shortcut keys for turning input method on or off</long>
316 + <key>/schemas/desktop/ibus/general/hotkey/trigger_ko</key>
317 + <applyto>/desktop/ibus/general/hotkey/trigger_ko</applyto>
318 + <owner>ibus</owner>
320 + <list_type>string</list_type>
321 + <default>[Hangul, Alt_R]</default>
323 + <short>Trigger shortcut keys for ko gtk_accelerator_parse</short>
324 <long>The shortcut keys for turning input method on or off</long>
327 diff --git a/engine/Makefile.am b/engine/Makefile.am
328 index b3b46be..7a806fc 100644
329 --- a/engine/Makefile.am
330 +++ b/engine/Makefile.am
333 libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la
342 -I$(top_srcdir)/src \
343 -I$(top_builddir)/src \
344 diff --git a/engine/ibus-xkb/Makefile.am b/engine/ibus-xkb/Makefile.am
346 index 0000000..65ede37
348 +++ b/engine/ibus-xkb/Makefile.am
350 +# vim:set noet ts=4:
352 +# ibus - The Input Bus
354 +# Copyright (c) 2012 Takao Fujiwara <takao.fujiwara1@gmail.com>
355 +# Copyright (c) 2012 Red Hat, Inc.
357 +# This library is free software; you can redistribute it and/or
358 +# modify it under the terms of the GNU Lesser General Public
359 +# License as published by the Free Software Foundation; either
360 +# version 2 of the License, or (at your option) any later version.
362 +# This library is distributed in the hope that it will be useful,
363 +# but WITHOUT ANY WARRANTY; without even the implied warranty of
364 +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
365 +# GNU Lesser General Public License for more details.
367 +# You should have received a copy of the GNU Lesser General Public
368 +# License along with this program; if not, write to the
369 +# Free Software Foundation, Inc., 59 Temple Place, Suite 330,
370 +# Boston, MA 02111-1307 USA
372 +libibus = $(top_builddir)/src/libibus-@IBUS_API_VERSION@.la
375 + -I$(top_srcdir)/src \
376 + -I$(top_builddir)/src \
381 + -DG_LOG_DOMAIN=\"IBUS\" \
382 + -DIBUS_DISABLE_DEPRECATED \
383 + -Wno-unused-variable \
384 + -Wno-unused-but-set-variable \
385 + -Wno-unused-function \
391 +libexec_PROGRAMS = ibus-xkb
393 +ibus_xkb_SOURCES = \
411 + $(MAKE) -C $(top_builddir)/src
413 +-include $(top_srcdir)/git.mk
414 diff --git a/engine/ibus-xkb/ibus-xkb-main.c b/engine/ibus-xkb/ibus-xkb-main.c
416 index 0000000..2529e4d
418 +++ b/engine/ibus-xkb/ibus-xkb-main.c
420 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
421 +/* vim:set et sts=4: */
422 +/* bus - The Input Bus
423 + * Copyright (C) 2012 Takao Fujiwara <takao.fujiwara1@gmail.com>
424 + * Copyright (C) 2012 Peng Huang <shawn.p.huang@gmail.com>
425 + * Copyright (C) 2012 Red Hat, Inc.
427 + * This library is free software; you can redistribute it and/or
428 + * modify it under the terms of the GNU Lesser General Public
429 + * License as published by the Free Software Foundation; either
430 + * version 2 of the License, or (at your option) any later version.
432 + * This library is distributed in the hope that it will be useful,
433 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
434 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
435 + * Lesser General Public License for more details.
437 + * You should have received a copy of the GNU Lesser General Public
438 + * License along with this library; if not, write to the
439 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
440 + * Boston, MA 02111-1307, USA.
442 +#ifdef HAVE_CONFIG_H
447 +#include <glib/gprintf.h>
448 +#include <glib/gi18n.h>
449 +#include <X11/Xlib.h>
457 +static gboolean get_layout = FALSE;
458 +static gboolean get_group = FALSE;
459 +static gchar *layout = NULL;
460 +static gchar *variant = NULL;
461 +static gchar *option = NULL;
462 +static int group = 0;
464 +static const GOptionEntry entries[] =
466 + { "get", 'g', 0, G_OPTION_ARG_NONE, &get_layout, N_("Get current xkb layout"), NULL },
467 + { "layout", 'l', 0, G_OPTION_ARG_STRING, &layout, N_("Set xkb LAYOUT"), N_("LAYOUT") },
468 + { "variant", 'v', 0, G_OPTION_ARG_STRING, &variant, N_("Set xkb VARIANT"), N_("VARIANT") },
469 + { "option", 'o', 0, G_OPTION_ARG_STRING, &option, N_("Set xkb OPTION"), N_("OPTION") },
470 + { "get-group", 'G', 0, G_OPTION_ARG_NONE, &get_group, N_("Get current xkb state"), NULL },
475 +main (int argc, char *argv[])
477 + GOptionContext *context;
478 + GError *error = NULL;
482 + setlocale (LC_ALL, "");
484 + bindtextdomain (GETTEXT_PACKAGE, GLIB_LOCALE_DIR);
485 + bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
488 + context = g_option_context_new ("- ibus daemon");
490 + g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
491 + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE);
493 + if (!g_option_context_parse (context, &argc, &argv, &error)) {
494 + g_printerr ("Option parsing failed: %s\n", error->message);
498 + xdisplay = XOpenDisplay (NULL);
499 + if (xdisplay == NULL) {
500 + g_warning ("Could not open display");
503 + ibus_xkb_init (xdisplay);
506 + ibus_xkb_set_layout (layout, variant, option);
509 + layout = ibus_xkb_get_current_layout ();
510 + variant = ibus_xkb_get_current_variant ();
511 + option = ibus_xkb_get_current_option ();
512 + g_printf ("layout: %s\n"
515 + layout ? layout : "",
516 + variant ? variant : "",
517 + option ? option : "");
523 + group = ibus_xkb_get_current_group ();
524 + g_printf ("group: %d\n", group);
531 diff --git a/engine/ibus-xkb/xkblib.c b/engine/ibus-xkb/xkblib.c
533 index 0000000..bb25455
535 +++ b/engine/ibus-xkb/xkblib.c
537 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
538 +/* vim:set et sts=4: */
539 +/* bus - The Input Bus
540 + * Copyright (C) 2012 Takao Fujiwara <takao.fujiwara1@gmail.com>
541 + * Copyright (C) 2012 Peng Huang <shawn.p.huang@gmail.com>
542 + * Copyright (C) 2012 Red Hat, Inc.
544 + * This library is free software; you can redistribute it and/or
545 + * modify it under the terms of the GNU Lesser General Public
546 + * License as published by the Free Software Foundation; either
547 + * version 2 of the License, or (at your option) any later version.
549 + * This library is distributed in the hope that it will be useful,
550 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
551 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
552 + * Lesser General Public License for more details.
554 + * You should have received a copy of the GNU Lesser General Public
555 + * License along with this library; if not, write to the
556 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
557 + * Boston, MA 02111-1307, USA.
559 +#ifdef HAVE_CONFIG_H
564 +#include <X11/Xlib.h>
565 +#include <X11/Xatom.h>
566 +#include <X11/XKBlib.h>
567 +#include <stdio.h> /* for XKBrules.h */
568 +#include <X11/extensions/XKBrules.h>
569 +#include <X11/extensions/XKBstr.h>
574 +#ifndef XKB_RULES_XML_FILE
575 +#define XKB_RULES_XML_FILE "/usr/share/X11/xkb/rules/evdev.xml"
578 +static gchar **default_layouts;
579 +static gchar **default_variants;
580 +static gchar **default_options;
581 +static int default_layout_group;
584 +get_xdisplay (Display *xdisplay)
586 + static Display *saved_xdisplay = NULL;
587 + if (xdisplay != NULL) {
588 + saved_xdisplay = xdisplay;
590 + return saved_xdisplay;
594 +init_xkb_default_layouts (Display *xdisplay)
597 + Atom xkb_rules_name, type;
599 + unsigned long l, nitems, bytes_after;
600 + unsigned char *prop = NULL;
602 + xkb_rules_name = XInternAtom (xdisplay, "_XKB_RULES_NAMES", TRUE);
603 + if (xkb_rules_name == None) {
604 + g_warning ("Could not get XKB rules atom");
607 + if (XGetWindowProperty (xdisplay,
608 + XDefaultRootWindow (xdisplay),
610 + 0, 1024, FALSE, XA_STRING,
611 + &type, &format, &nitems, &bytes_after, &prop) != Success) {
612 + g_warning ("Could not get X property");
616 + g_warning ("Could not get group layout from X property");
619 + for (l = 0; l < 2; l++) {
620 + prop += strlen ((const char *) prop) + 1;
622 + if (prop == NULL || *prop == '\0') {
623 + g_warning ("No layouts form X property");
626 + default_layouts = g_strsplit ((gchar *) prop, ",", -1);
627 + prop += strlen ((const char *) prop) + 1;
628 + default_variants = g_strsplit ((gchar *) prop, ",", -1);
629 + prop += strlen ((const char *) prop) + 1;
630 + default_options = g_strsplit ((gchar *) prop, ",", -1);
632 + if (XkbGetState (xdisplay, XkbUseCoreKbd, &state) != Success) {
633 + g_warning ("Could not get state");
636 + default_layout_group = state.group;
640 +set_xkb_rules (Display *xdisplay,
641 + const char *rules_file, const char *model,
642 + const char *all_layouts, const char *all_variants,
643 + const char *all_options)
646 + XkbRF_RulesPtr rules;
647 + XkbRF_VarDefsRec rdefs;
648 + XkbComponentNamesRec rnames;
651 + rules_path = g_strdup ("./rules/evdev");
652 + rules = XkbRF_Load (rules_path, "C", TRUE, TRUE);
653 + if (rules == NULL) {
654 + g_return_val_if_fail (XKB_RULES_XML_FILE != NULL, FALSE);
656 + g_free (rules_path);
657 + if (g_str_has_suffix (XKB_RULES_XML_FILE, ".xml")) {
658 + rules_path = g_strndup (XKB_RULES_XML_FILE,
659 + strlen (XKB_RULES_XML_FILE) - 4);
661 + rules_path = g_strdup (XKB_RULES_XML_FILE);
663 + rules = XkbRF_Load (rules_path, "C", TRUE, TRUE);
665 + g_return_val_if_fail (rules != NULL, FALSE);
667 + memset (&rdefs, 0, sizeof (XkbRF_VarDefsRec));
668 + memset (&rnames, 0, sizeof (XkbComponentNamesRec));
669 + rdefs.model = model ? g_strdup (model) : NULL;
670 + rdefs.layout = all_layouts ? g_strdup (all_layouts) : NULL;
671 + rdefs.variant = all_variants ? g_strdup (all_variants) : NULL;
672 + rdefs.options = all_options ? g_strdup (all_options) : NULL;
673 + XkbRF_GetComponents (rules, &rdefs, &rnames);
674 + xkb = XkbGetKeyboardByName (xdisplay, XkbUseCoreKbd, &rnames,
675 + XkbGBN_AllComponentsMask,
676 + XkbGBN_AllComponentsMask &
677 + (~XkbGBN_GeometryMask), True);
679 + g_warning ("Cannot load new keyboard description.");
682 + XkbRF_SetNamesProp (xdisplay, rules_path, &rdefs);
683 + g_free (rules_path);
684 + g_free (rdefs.model);
685 + g_free (rdefs.layout);
686 + g_free (rdefs.variant);
687 + g_free (rdefs.options);
693 +update_xkb_properties (Display *xdisplay,
694 + const char *rules_file, const char *model,
695 + const char *all_layouts, const char *all_variants,
696 + const char *all_options)
702 + Window root_window;
704 + len = (rules_file ? strlen (rules_file) : 0);
705 + len += (model ? strlen (model) : 0);
706 + len += (all_layouts ? strlen (all_layouts) : 0);
707 + len += (all_variants ? strlen (all_variants) : 0);
708 + len += (all_options ? strlen (all_options) : 0);
713 + len += 5; /* trailing NULs */
715 + rules_atom = XInternAtom (xdisplay, _XKB_RF_NAMES_PROP_ATOM, False);
716 + root_window = XDefaultRootWindow (xdisplay);
717 + pval = next = g_new0 (char, len + 1);
723 + strcpy (next, rules_file);
724 + next += strlen (rules_file);
728 + strcpy (next, model);
729 + next += strlen (model);
733 + strcpy (next, all_layouts);
734 + next += strlen (all_layouts);
737 + if (all_variants) {
738 + strcpy (next, all_variants);
739 + next += strlen (all_variants);
743 + strcpy (next, all_options);
744 + next += strlen (all_options);
747 + if ((next - pval) != len) {
752 + XChangeProperty (xdisplay, root_window,
753 + rules_atom, XA_STRING, 8, PropModeReplace,
754 + (unsigned char *) pval, len);
755 + XSync(xdisplay, False);
761 +ibus_xkb_init (Display *xdisplay)
763 + get_xdisplay (xdisplay);
764 + init_xkb_default_layouts (xdisplay);
768 +ibus_xkb_finit (void)
770 + g_strfreev (default_layouts);
771 + default_layouts = NULL;
772 + g_strfreev (default_variants);
773 + default_variants = NULL;
774 + g_strfreev (default_options);
775 + default_options = NULL;
779 +ibus_xkb_get_current_layout (void)
781 + if (default_layouts == NULL) {
782 + g_warning ("Your system seems not to support XKB.");
786 + return g_strjoinv (",", (gchar **) default_layouts);
790 +ibus_xkb_get_current_variant (void)
792 + if (default_variants == NULL) {
796 + return g_strjoinv (",", (gchar **) default_variants);
800 +ibus_xkb_get_current_option (void)
802 + if (default_options == NULL) {
806 + return g_strjoinv (",", (gchar **) default_options);
810 +ibus_xkb_set_layout (const char *layouts,
811 + const char *variants,
812 + const char *options)
816 + gchar *layouts_line;
818 + if (default_layouts == NULL) {
819 + g_warning ("Your system seems not to support XKB.");
823 + if (layouts == NULL || g_strcmp0 (layouts, "default") == 0) {
824 + layouts_line = g_strjoinv (",", (gchar **) default_layouts);
826 + layouts_line = g_strdup (layouts);
829 + xdisplay = get_xdisplay (NULL);
830 + retval = set_xkb_rules (xdisplay,
832 + layouts_line, variants, options);
833 + update_xkb_properties (xdisplay,
835 + layouts_line, variants, options);
836 + g_free (layouts_line);
842 +ibus_xkb_get_current_group (void)
844 + Display *xdisplay = get_xdisplay (NULL);
847 + if (default_layouts == NULL) {
848 + g_warning ("Your system seems not to support XKB.");
852 + if (xdisplay == NULL) {
853 + g_warning ("ibus-xkb is not initialized.");
857 + if (XkbGetState (xdisplay, XkbUseCoreKbd, &state) != Success) {
858 + g_warning ("Could not get state");
862 + return state.group;
864 diff --git a/engine/ibus-xkb/xkblib.h b/engine/ibus-xkb/xkblib.h
866 index 0000000..36597c3
868 +++ b/engine/ibus-xkb/xkblib.h
870 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
871 +/* vim:set et sts=4: */
872 +/* bus - The Input Bus
873 + * Copyright (C) 2012 Takao Fujiwara <takao.fujiwara1@gmail.com>
874 + * Copyright (C) 2012 Peng Huang <shawn.p.huang@gmail.com>
875 + * Copyright (C) 2012 Red Hat, Inc.
877 + * This library is free software; you can redistribute it and/or
878 + * modify it under the terms of the GNU Lesser General Public
879 + * License as published by the Free Software Foundation; either
880 + * version 2 of the License, or (at your option) any later version.
882 + * This library is distributed in the hope that it will be useful,
883 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
884 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
885 + * Lesser General Public License for more details.
887 + * You should have received a copy of the GNU Lesser General Public
888 + * License along with this library; if not, write to the
889 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
890 + * Boston, MA 02111-1307, USA.
895 +#include <X11/Xlib.h>
899 +void ibus_xkb_init (Display *xdisplay);
900 +void ibus_xkb_finit (void);
901 +gchar *ibus_xkb_get_current_layout (void);
902 +gchar *ibus_xkb_get_current_variant (void);
903 +gchar *ibus_xkb_get_current_option (void);
904 +gboolean ibus_xkb_set_layout (const char *layouts,
905 + const char *variants,
906 + const char *options);
907 +int ibus_xkb_get_current_group (void);
911 diff --git a/engine/main.vala b/engine/main.vala
912 index acfa737..afadca0 100644
913 --- a/engine/main.vala
914 +++ b/engine/main.vala
921 +private void print_xml(string layout,
922 + string layout_desc,
924 + string? variant_desc,
926 + string name = "xkb:%s:%s:%s".printf(layout, variant ?? "", lang);
927 + string keymap = layout;
928 + string desc = layout_desc;
929 + string symbol = lang;
931 + if (variant != null) {
932 + keymap = "%s(%s)".printf(layout, variant);
935 + if (variant_desc != null) {
936 + desc = variant_desc;
939 + desc = desc.replace("<", "<").replace(">", ">");
941 + if (lang.length > 2) {
942 + symbol = lang[0:2];
948 + <language>%s</language>
949 + <license>GPL</license>
950 + <author>Peng Huang <shawn.p.huang@gmail.com></author>
951 + <layout>%s</layout>
952 + <longname>%s</longname>
953 + <description>%s</description>
954 + <icon>ibus-keyboard</icon>
955 + <symbol>%s</symbol>
957 + </engine>".printf(name, lang, keymap, desc, desc, symbol, 99);
961 +private void print_component() {
962 + IBus.XKBConfigRegistry registry = new IBus.XKBConfigRegistry();
963 + GLib.List layouts = registry.layout_list_get_layouts();
964 + GLib.List variants;
966 + string layout_desc;
967 + const string header = "<engines>";
968 + const string footer = "
972 + for (unowned GLib.List<string> l = layouts; l != null; l = l.next) {
973 + variants = registry.layout_list_get_variants(l.data);
974 + langs = registry.layout_lang_get_langs(l.data);
975 + layout_desc = registry.layout_desc_get_desc(l.data);
976 + for (unowned GLib.List<string> lg = langs; lg != null; lg = lg.next) {
977 + print_xml(l.data, layout_desc, null, null, lg.data);
979 + for (unowned GLib.List<string> v = variants; v != null; v = v.next) {
980 + var l_v = "%s(%s)".printf(l.data, v.data);
981 + unowned GLib.List<string> l_v_langs = null;
982 + GLib.List<string> _l_v_langs = registry.layout_lang_get_langs(l_v);
983 + l_v_langs = _l_v_langs;
984 + if (l_v_langs == null) {
987 + for (unowned GLib.List<string> lg = l_v_langs; lg != null; lg = lg.next) {
991 + registry.variant_desc_get_desc(l_v),
999 class DummyEngine : IBus.EngineSimple {
1001 @@ -28,6 +107,13 @@ class DummyEngine : IBus.EngineSimple {
1002 public int main(string[] args) {
1005 + if (args.length >= 2) {
1006 + if (args[1] == "--xml" || args[1] == "-x") {
1007 + print_component();
1012 IBus.Bus bus = new IBus.Bus();
1013 if (!bus.is_connected()) {
1014 warning("ibus-daemon does not exist.");
1015 diff --git a/engine/simple.xml.in.in b/engine/simple.xml.in.in
1016 index 25db578..7de949a 100644
1017 --- a/engine/simple.xml.in.in
1018 +++ b/engine/simple.xml.in.in
1020 <license>GPL</license>
1021 <homepage>http://code.google.com/p/ibus</homepage>
1022 <textdomain>ibus</textdomain>
1025 - <name>xkb:us::eng</name>
1026 - <language>eng</language>
1027 - <license>GPL</license>
1028 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1029 - <layout>us</layout>
1030 - <longname>English (US)</longname>
1031 - <description>English (US)</description>
1032 - <icon>ibus-keyboard</icon>
1036 - <name>xkb:us:intl:eng</name>
1037 - <language>eng</language>
1038 - <license>GPL</license>
1039 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1040 - <layout>us(intl)</layout>
1041 - <longname>English (US, international with dead keys)</longname>
1042 - <description>English (US, international with dead keys)</description>
1043 - <icon>ibus-keyboard</icon>
1047 - <name>xkb:us:colemak:eng</name>
1048 - <language>eng</language>
1049 - <license>GPL</license>
1050 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1051 - <layout>us(colemak)</layout>
1052 - <longname>English (Colemak)</longname>
1053 - <description>English (Colemak)</description>
1054 - <icon>ibus-keyboard</icon>
1058 - <name>xkb:us:dvorak:eng</name>
1059 - <language>eng</language>
1060 - <license>GPL</license>
1061 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1062 - <layout>us(dvorak)</layout>
1063 - <longname>English (Dvorak)</longname>
1064 - <description>English (Dvorak)</description>
1065 - <icon>ibus-keyboard</icon>
1069 - <name>xkb:us:altgr-intl:eng</name>
1070 - <language>eng</language>
1071 - <license>GPL</license>
1072 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1073 - <layout>us(altgr-intl)</layout>
1074 - <longname>English (international AltGr dead keys)</longname>
1075 - <description>English (international AltGr dead keys)</description>
1076 - <icon>ibus-keyboard</icon>
1080 - <name>xkb:us:altgr-intl:eng</name>
1081 - <language>eng</language>
1082 - <license>GPL</license>
1083 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1084 - <layout>us(altgr-intl)</layout>
1085 - <longname>English (international AltGr dead keys)</longname>
1086 - <description>English (international AltGr dead keys)</description>
1087 - <icon>ibus-keyboard</icon>
1091 - <name>xkb:be::ger</name>
1092 - <language>ger</language>
1093 - <license>GPL</license>
1094 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1095 - <layout>be</layout>
1096 - <longname>Belgian</longname>
1097 - <description>Belgian</description>
1098 - <icon>ibus-keyboard</icon>
1102 - <name>xkb:be::nld</name>
1103 - <language>nld</language>
1104 - <license>GPL</license>
1105 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1106 - <layout>be</layout>
1107 - <longname>Belgian</longname>
1108 - <description>Belgian</description>
1109 - <icon>ibus-keyboard</icon>
1113 - <name>xkb:be::fra</name>
1114 - <language>fra</language>
1115 - <license>GPL</license>
1116 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1117 - <layout>be</layout>
1118 - <longname>Belgian</longname>
1119 - <description>Belgian</description>
1120 - <icon>ibus-keyboard</icon>
1124 - <name>xkb:br::por</name>
1125 - <language>por</language>
1126 - <license>GPL</license>
1127 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1128 - <layout>br</layout>
1129 - <longname>Portuguese (Brazil)</longname>
1130 - <description>Portuguese (Brazil)</description>
1131 - <icon>ibus-keyboard</icon>
1135 - <name>xkb:bg::bul</name>
1136 - <language>bul</language>
1137 - <license>GPL</license>
1138 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1139 - <layout>bg</layout>
1140 - <longname>Bulgarian</longname>
1141 - <description>Bulgarian</description>
1142 - <icon>ibus-keyboard</icon>
1146 - <name>xkb:bg:phonetic:bul</name>
1147 - <language>bul</language>
1148 - <license>GPL</license>
1149 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1150 - <layout>bg(phonetic)</layout>
1151 - <longname>Bulgarian (traditional phonetic)</longname>
1152 - <description>Bulgarian (traditional phonetic)</description>
1153 - <icon>ibus-keyboard</icon>
1157 - <name>xkb:ca::fra</name>
1158 - <language>fra</language>
1159 - <license>GPL</license>
1160 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1161 - <layout>ca</layout>
1162 - <longname>French (Canada)</longname>
1163 - <description>French (Canada)</description>
1164 - <icon>ibus-keyboard</icon>
1168 - <name>xkb:ca:eng:eng</name>
1169 - <language>eng</language>
1170 - <license>GPL</license>
1171 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1172 - <layout>ca(eng)</layout>
1173 - <longname>English (Canada)</longname>
1174 - <description>English (Canada)</description>
1175 - <icon>ibus-keyboard</icon>
1179 - <name>xkb:hr::scr</name>
1180 - <language>scr</language>
1181 - <license>GPL</license>
1182 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1183 - <layout>hr</layout>
1184 - <longname>Croatian</longname>
1185 - <description>Croatian</description>
1186 - <icon>ibus-keyboard</icon>
1190 - <name>xkb:cz::cze</name>
1191 - <language>cze</language>
1192 - <license>GPL</license>
1193 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1194 - <layout>cz</layout>
1195 - <longname>Czech</longname>
1196 - <description>Czech</description>
1197 - <icon>ibus-keyboard</icon>
1201 - <name>xkb:dk::dan</name>
1202 - <language>dan</language>
1203 - <license>GPL</license>
1204 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1205 - <layout>dk</layout>
1206 - <longname>Danish</longname>
1207 - <description>Danish</description>
1208 - <icon>ibus-keyboard</icon>
1212 - <name>xkb:ee::est</name>
1213 - <language>est</language>
1214 - <license>GPL</license>
1215 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1216 - <layout>ee</layout>
1217 - <longname>Estonian</longname>
1218 - <description>Estonian</description>
1219 - <icon>ibus-keyboard</icon>
1223 - <name>xkb:fi::fin</name>
1224 - <language>fin</language>
1225 - <license>GPL</license>
1226 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1227 - <layout>fi</layout>
1228 - <longname>Finnish</longname>
1229 - <description>Finnish</description>
1230 - <icon>ibus-keyboard</icon>
1234 - <name>xkb:fr::fra</name>
1235 - <language>fra</language>
1236 - <license>GPL</license>
1237 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1238 - <layout>fr</layout>
1239 - <longname>French</longname>
1240 - <description>French</description>
1241 - <icon>ibus-keyboard</icon>
1245 - <name>xkb:de::ger</name>
1246 - <language>ger</language>
1247 - <license>GPL</license>
1248 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1249 - <layout>de</layout>
1250 - <longname>German</longname>
1251 - <description>German</description>
1252 - <icon>ibus-keyboard</icon>
1256 - <name>xkb:de:neo:ger</name>
1257 - <language>ger</language>
1258 - <license>GPL</license>
1259 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1260 - <layout>de(neo)</layout>
1261 - <longname>German (Neo 2)</longname>
1262 - <description>German (Neo 2)</description>
1263 - <icon>ibus-keyboard</icon>
1267 - <name>xkb:gr::gre</name>
1268 - <language>gre</language>
1269 - <license>GPL</license>
1270 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1271 - <layout>gr</layout>
1272 - <longname>Greek</longname>
1273 - <description>Greek</description>
1274 - <icon>ibus-keyboard</icon>
1278 - <name>xkb:hu::hun</name>
1279 - <language>hun</language>
1280 - <license>GPL</license>
1281 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1282 - <layout>hu</layout>
1283 - <longname>Hungarian</longname>
1284 - <description>Hungarian</description>
1285 - <icon>ibus-keyboard</icon>
1289 - <name>xkb:il::heb</name>
1290 - <language>heb</language>
1291 - <license>GPL</license>
1292 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1293 - <layout>il</layout>
1294 - <longname>Hebrew</longname>
1295 - <description>Hebrew</description>
1296 - <icon>ibus-keyboard</icon>
1300 - <name>xkb:it::ita</name>
1301 - <language>ita</language>
1302 - <license>GPL</license>
1303 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1304 - <layout>it</layout>
1305 - <longname>Italian</longname>
1306 - <description>Italian</description>
1307 - <icon>ibus-keyboard</icon>
1311 - <name>xkb:jp::jpn</name>
1312 - <language>jpn</language>
1313 - <license>GPL</license>
1314 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1315 - <layout>jp</layout>
1316 - <longname>Japanese</longname>
1317 - <description>Japanese</description>
1318 - <icon>ibus-keyboard</icon>
1322 - <name>xkb:latam::spa</name>
1323 - <language>spa</language>
1324 - <license>GPL</license>
1325 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1326 - <layout>latam</layout>
1327 - <longname>Spanish (Latin American)</longname>
1328 - <description>Spanish (Latin American)</description>
1329 - <icon>ibus-keyboard</icon>
1333 - <name>xkb:lt::lit</name>
1334 - <language>lit</language>
1335 - <license>GPL</license>
1336 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1337 - <layout>lt</layout>
1338 - <longname>Lithuanian</longname>
1339 - <description>Lithuanian</description>
1340 - <icon>ibus-keyboard</icon>
1344 - <name>xkb:lv:apostrophe:lav</name>
1345 - <language>lav</language>
1346 - <license>GPL</license>
1347 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1348 - <layout>lv(apostrophe)</layout>
1349 - <longname>Latvian (apostrophe variant)</longname>
1350 - <description>Latvian (apostrophe variant)</description>
1351 - <icon>ibus-keyboard</icon>
1355 - <name>xkb:pl::pol</name>
1356 - <language>pol</language>
1357 - <license>GPL</license>
1358 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1359 - <layout>pl</layout>
1360 - <longname>Polish</longname>
1361 - <description>Polish</description>
1362 - <icon>ibus-keyboard</icon>
1366 - <name>xkb:pt::por</name>
1367 - <language>por</language>
1368 - <license>GPL</license>
1369 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1370 - <layout>pt</layout>
1371 - <longname>Portuguese</longname>
1372 - <description>Portuguese</description>
1373 - <icon>ibus-keyboard</icon>
1377 - <name>xkb:ro::rum</name>
1378 - <language>rum</language>
1379 - <license>GPL</license>
1380 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1381 - <layout>ro</layout>
1382 - <longname>Romanian</longname>
1383 - <description>Romanian</description>
1384 - <icon>ibus-keyboard</icon>
1388 - <name>xkb:ru::rus</name>
1389 - <language>rus</language>
1390 - <license>GPL</license>
1391 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1392 - <layout>ru</layout>
1393 - <longname>Russian</longname>
1394 - <description>Russian</description>
1395 - <icon>ibus-keyboard</icon>
1399 - <name>xkb:ru:phonetic:rus</name>
1400 - <language>rus</language>
1401 - <license>GPL</license>
1402 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1403 - <layout>ru(phonetic)</layout>
1404 - <longname>Russian (phonetic)</longname>
1405 - <description>Russian (phonetic)</description>
1406 - <icon>ibus-keyboard</icon>
1410 - <name>xkb:rs::srp</name>
1411 - <language>srp</language>
1412 - <license>GPL</license>
1413 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1414 - <layout>rs</layout>
1415 - <longname>Serbian</longname>
1416 - <description>Serbian</description>
1417 - <icon>ibus-keyboard</icon>
1421 - <name>xkb:si::slv</name>
1422 - <language>slv</language>
1423 - <license>GPL</license>
1424 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1425 - <layout>si</layout>
1426 - <longname>Slovenian</longname>
1427 - <description>Slovenian</description>
1428 - <icon>ibus-keyboard</icon>
1432 - <name>xkb:sk::slo</name>
1433 - <language>slo</language>
1434 - <license>GPL</license>
1435 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1436 - <layout>sk</layout>
1437 - <longname>Slovak</longname>
1438 - <description>Slovak</description>
1439 - <icon>ibus-keyboard</icon>
1443 - <name>xkb:es::spa</name>
1444 - <language>spa</language>
1445 - <license>GPL</license>
1446 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1447 - <layout>es</layout>
1448 - <longname>Spanish</longname>
1449 - <description>Spanish</description>
1450 - <icon>ibus-keyboard</icon>
1454 - <name>xkb:es:cat:cat</name>
1455 - <language>cat</language>
1456 - <license>GPL</license>
1457 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1458 - <layout>es(cat)</layout>
1459 - <longname>Catalan (Spain, with middle-dot L)</longname>
1460 - <description>Catalan (Spain, with middle-dot L)</description>
1461 - <icon>ibus-keyboard</icon>
1465 - <name>xkb:se::swe</name>
1466 - <language>swe</language>
1467 - <license>GPL</license>
1468 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1469 - <layout>se</layout>
1470 - <longname>Swedish</longname>
1471 - <description>Swedish</description>
1472 - <icon>ibus-keyboard</icon>
1476 - <name>xkb:ch::ger</name>
1477 - <language>ger</language>
1478 - <license>GPL</license>
1479 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1480 - <layout>ch</layout>
1481 - <longname>German (Switzerland)</longname>
1482 - <description>German (Switzerland)</description>
1483 - <icon>ibus-keyboard</icon>
1487 - <name>xkb:ch:fr:fra</name>
1488 - <language>fra</language>
1489 - <license>GPL</license>
1490 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1491 - <layout>ch(fr)</layout>
1492 - <longname>French (Switzerland)</longname>
1493 - <description>French (Switzerland)</description>
1494 - <icon>ibus-keyboard</icon>
1498 - <name>xkb:tr::tur</name>
1499 - <language>tur</language>
1500 - <license>GPL</license>
1501 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1502 - <layout>tr</layout>
1503 - <longname>Turkish</longname>
1504 - <description>Turkish</description>
1505 - <icon>ibus-keyboard</icon>
1509 - <name>xkb:ua::ukr</name>
1510 - <language>ukr</language>
1511 - <license>GPL</license>
1512 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1513 - <layout>ua</layout>
1514 - <longname>Ukrainian</longname>
1515 - <description>Ukrainian</description>
1516 - <icon>ibus-keyboard</icon>
1520 - <name>xkb:gb:extd:eng</name>
1521 - <language>eng</language>
1522 - <license>GPL</license>
1523 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1524 - <layout>gb(extd)</layout>
1525 - <longname>English (UK, extended WinKeys)</longname>
1526 - <description>English (UK, extended WinKeys)</description>
1527 - <icon>ibus-keyboard</icon>
1531 - <name>xkb:gb:dvorak:eng</name>
1532 - <language>eng</language>
1533 - <license>GPL</license>
1534 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1535 - <layout>gb(dvorak)</layout>
1536 - <longname>English (UK, Dvorak)</longname>
1537 - <description>English (UK, Dvorak)</description>
1538 - <icon>ibus-keyboard</icon>
1542 - <name>xkb:kr:kr104:kor</name>
1543 - <language>kor</language>
1544 - <license>GPL</license>
1545 - <author>Peng Huang <shawn.p.huang@gmail.com></author>
1546 - <layout>kr(kr104)</layout>
1547 - <longname>Korean (101/104 key compatible)</longname>
1548 - <description>Korean (101/104 key compatible)</description>
1549 - <icon>ibus-keyboard</icon>
1553 + <engines exec=\"${libexecdir}/ibus-engine-simple --xml\" />
1555 diff --git a/ibus-1.0.pc.in b/ibus-1.0.pc.in
1556 index 9f593ab..66b902a 100644
1557 --- a/ibus-1.0.pc.in
1558 +++ b/ibus-1.0.pc.in
1561 exec_prefix=@exec_prefix@
1563 +libexecdir=@libexecdir@
1564 includedir=@includedir@
1566 pkgdatadir=@datadir@/ibus
1567 +have_ibus_xkb=@HAVE_IBUS_XKB@
1568 +ibus_xkb=${libexecdir}/ibus-xkb
1569 +have_ibus_gkbd=@HAVE_IBUS_GKBD@
1572 Description: IBus Library
1573 diff --git a/ibus.spec.in b/ibus.spec.in
1574 index 58cac38..4b6f869 100644
1580 %define build_python_library 0
1581 +%define build_xkb 0
1583 %define glib_ver %([ -a %{_libdir}/pkgconfig/glib-2.0.pc ] && pkg-config --modversion glib-2.0 | cut -d. -f 1,2 || echo -n "999")
1584 %define gconf2_version 2.12.0
1585 @@ -38,6 +39,10 @@ BuildRequires: GConf2-devel
1586 BuildRequires: pygobject2-devel
1587 BuildRequires: intltool
1588 BuildRequires: iso-codes-devel
1590 +BuildRequires: libxkbfile-devel
1591 +BuildRequires: libgnomekbd-devel
1594 Requires: %{name}-libs = %{version}-%{release}
1595 Requires: %{name}-gtk2 = %{version}-%{release}
1596 @@ -51,6 +56,9 @@ Requires: im-chooser >= %{im_chooser_version}
1597 Requires: GConf2 >= %{gconf2_version}
1598 Requires: notify-python
1601 +Requires: libgnomekbd
1604 Requires(post): desktop-file-utils
1605 Requires(postun): desktop-file-utils
1606 @@ -132,6 +140,10 @@ OPTIONS="$OPTIONS --enable-python-library"
1607 OPTIONS="$OPTIONS --disable-python-library"
1611 +OPTIONS="$OPTIONS --enable-xkb --enable-libgnomekbd"
1616 # make -C po update-gmo
1617 diff --git a/setup/main.py b/setup/main.py
1618 index 8a2391d..2a19c49 100644
1621 @@ -67,6 +67,13 @@ class Setup(object):
1623 super(Setup, self).__init__()
1625 + # In the latest pygobject3 3.3.4 or later, g_variant_dup_strv
1626 + # returns the allocated strv but in the previous release,
1627 + # it returned the tuple of (strv, length)
1628 + self.__tuple_for_variant_strv = False
1629 + if type(GLib.Variant.new_strv([]).dup_strv()) == tuple:
1630 + self.__tuple_for_variant_strv = True
1632 # IBus.Bus() calls ibus_bus_new().
1633 # Gtk.Builder().add_from_file() also calls ibus_bus_new_async()
1634 # via ibus_im_context_new().
1635 @@ -191,14 +198,22 @@ class Setup(object):
1638 self.__engines = self.__bus.list_engines()
1639 + value = self.__config.get_value("general", "load_xkb_layouts")
1642 + load_layouts = self.__variant_dup_strv(value)
1644 + for engine in self.__engines:
1645 + if not engine.get_name().startswith('xkb:'):
1646 + engines.append(engine)
1647 + elif engine.get_layout() in load_layouts:
1648 + engines.append(engine)
1650 self.__combobox = self.__builder.get_object("combobox_engines")
1651 - self.__combobox.set_engines(self.__engines)
1652 + self.__combobox.set_engines(engines)
1655 - for e in self.__engines:
1656 - tmp_dict[e.get_name()] = e
1657 engine_names = values.get("preload_engines", [])
1658 - engines = [tmp_dict[name] for name in engine_names if name in tmp_dict]
1659 + engines = self.__get_engine_descs_from_names(engine_names)
1661 self.__treeview = self.__builder.get_object("treeview_engines")
1662 self.__treeview.set_engines(engines)
1663 @@ -247,6 +262,12 @@ class Setup(object):
1665 self.__init_general()
1667 + def __variant_dup_strv(self, variant):
1668 + if self.__tuple_for_variant_strv:
1669 + return variant.dup_strv()[0]
1671 + return variant.dup_strv()
1673 def __combobox_notify_active_engine_cb(self, combobox, property):
1674 engine = self.__combobox.get_active_engine()
1675 button = self.__builder.get_object("button_engine_add")
1676 @@ -271,6 +292,13 @@ class Setup(object):
1677 args.append(path.basename(setup_path))
1680 + def __get_engine_descs_from_names(self, engine_names):
1682 + for e in self.__engines:
1683 + tmp_dict[e.get_name()] = e
1684 + engines = [tmp_dict[name] for name in engine_names if name in tmp_dict]
1687 def __treeview_notify_cb(self, treeview, prop):
1688 if prop.name not in ("active-engine", "engines"):
1690 diff --git a/src/Makefile.am b/src/Makefile.am
1691 index df4ada3..e249ada 100644
1692 --- a/src/Makefile.am
1693 +++ b/src/Makefile.am
1694 @@ -194,6 +194,11 @@ typelibs_DATA = $(INTROSPECTION_GIRS:.gir=.typelib)
1695 CLEANFILES += $(dist_gir_DATA) $(typelibs_DATA)
1699 +ibus_sources += ibusxkbxml.c
1700 +ibus_headers += ibusxkbxml.h
1704 ibusenumtypes.h: $(ibus_headers) ibusenumtypes.h.template
1705 $(AM_V_GEN) ( top_builddir=`cd $(top_builddir) && pwd`; \
1706 diff --git a/src/ibus.h b/src/ibus.h
1707 index ef811a4..f82a162 100644
1711 #include <ibuskeys.h>
1712 #include <ibusenumtypes.h>
1713 #include <ibushotkey.h>
1714 +#include <ibusxkbxml.h>
1715 #include <ibusxml.h>
1716 #include <ibusenginedesc.h>
1717 #include <ibusobservedpath.h>
1718 diff --git a/src/ibusxkbxml.c b/src/ibusxkbxml.c
1719 new file mode 100644
1720 index 0000000..4792664
1722 +++ b/src/ibusxkbxml.c
1724 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
1725 +/* vim:set et sts=4: */
1726 +/* bus - The Input Bus
1727 + * Copyright (C) 2012 Takao Fujiwara <takao.fujiwara1@gmail.com>
1728 + * Copyright (C) 2012 Peng Huang <shawn.p.huang@gmail.com>
1729 + * Copyright (C) 2012 Red Hat, Inc.
1731 + * This library is free software; you can redistribute it and/or
1732 + * modify it under the terms of the GNU Lesser General Public
1733 + * License as published by the Free Software Foundation; either
1734 + * version 2 of the License, or (at your option) any later version.
1736 + * This library is distributed in the hope that it will be useful,
1737 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1738 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
1739 + * Lesser General Public License for more details.
1741 + * You should have received a copy of the GNU Lesser General Public
1742 + * License along with this library; if not, write to the
1743 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
1744 + * Boston, MA 02111-1307, USA.
1746 +#ifdef HAVE_CONFIG_H
1747 +#include <config.h>
1753 +#include "ibusxkbxml.h"
1755 +#ifndef XKB_RULES_XML_FILE
1756 +#define XKB_RULES_XML_FILE "/usr/share/X11/xkb/rules/evdev.xml"
1759 +#define IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE(o) \
1760 + (G_TYPE_INSTANCE_GET_PRIVATE ((o), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryPrivate))
1762 +typedef struct _IBusXKBConfigRegistryPrivate IBusXKBConfigRegistryPrivate;
1764 +struct _IBusXKBConfigRegistryPrivate {
1765 + GHashTable *layout_list;
1766 + GHashTable *layout_lang;
1767 + GHashTable *layout_desc;
1768 + GHashTable *variant_desc;
1772 +/* functions prototype */
1773 +static void ibus_xkb_config_registry_destroy
1774 + (IBusXKBConfigRegistry *xkb_config);
1776 +G_DEFINE_TYPE (IBusXKBConfigRegistry, ibus_xkb_config_registry, IBUS_TYPE_OBJECT)
1779 +parse_xkb_xml_languagelist_node (IBusXKBConfigRegistryPrivate *priv,
1780 + XMLNode *parent_node,
1781 + const gchar *layout_name)
1783 + XMLNode *node = parent_node;
1784 + XMLNode *sub_node;
1786 + GList *lang_list = NULL;
1788 + g_assert (node != NULL);
1789 + g_assert (layout_name != NULL);
1790 + for (p = node->sub_nodes; p; p = p->next) {
1791 + sub_node = (XMLNode *) p->data;
1792 + if (g_strcmp0 (sub_node->name, "iso639Id") == 0) {
1793 + lang_list = g_list_append (lang_list,
1794 + (gpointer) g_strdup (sub_node->text));
1798 + if (lang_list == NULL) {
1799 + /* some nodes have no lang */
1802 + if (g_hash_table_lookup (priv->layout_lang, layout_name) != NULL) {
1803 + g_warning ("duplicated name %s exists", layout_name);
1806 + g_hash_table_insert (priv->layout_lang,
1807 + (gpointer) g_strdup (layout_name),
1808 + (gpointer) lang_list);
1811 +static const gchar *
1812 +parse_xkb_xml_configitem_node (IBusXKBConfigRegistryPrivate *priv,
1813 + XMLNode *parent_node)
1815 + XMLNode *node = parent_node;
1816 + XMLNode *sub_node;
1818 + gchar *name = NULL;
1819 + gchar *description = NULL;
1821 + g_assert (node != NULL);
1822 + for (p = node->sub_nodes; p; p = p->next) {
1823 + sub_node = (XMLNode *) p->data;
1824 + if (g_strcmp0 (sub_node->name, "name") == 0) {
1825 + name = sub_node->text;
1828 + if (g_strcmp0 (sub_node->name, "description") == 0) {
1829 + description = sub_node->text;
1832 + if (g_strcmp0 (sub_node->name, "languageList") == 0) {
1833 + if (name == NULL) {
1834 + g_warning ("layout name is NULL in node %s", node->name);
1837 + parse_xkb_xml_languagelist_node (priv, sub_node, name);
1841 + if (name == NULL) {
1842 + g_warning ("No name in layout node");
1845 + if (g_hash_table_lookup (priv->layout_desc, name) != NULL) {
1846 + g_warning ("duplicated name %s exists", name);
1849 + g_hash_table_insert (priv->layout_desc,
1850 + (gpointer) g_strdup (name),
1851 + (gpointer) g_strdup (description));
1856 +static const gchar *
1857 +parse_xkb_xml_variant_configitem_node (IBusXKBConfigRegistryPrivate *priv,
1858 + XMLNode *parent_node,
1859 + const gchar *layout_name)
1861 + XMLNode *node = parent_node;
1862 + XMLNode *sub_node;
1864 + gchar *name = NULL;
1865 + gchar *description = NULL;
1866 + gchar *variant_lang_name = NULL;
1868 + g_assert (node != NULL);
1869 + g_assert (layout_name != NULL);
1870 + for (p = node->sub_nodes; p; p = p->next) {
1871 + sub_node = (XMLNode *) p->data;
1872 + if (g_strcmp0 (sub_node->name, "name") == 0) {
1873 + name = sub_node->text;
1876 + if (g_strcmp0 (sub_node->name, "description") == 0) {
1877 + description = sub_node->text;
1880 + if (g_strcmp0 (sub_node->name, "languageList") == 0) {
1881 + if (name == NULL) {
1882 + g_warning ("layout name is NULL in node %s", node->name);
1885 + variant_lang_name = g_strdup_printf ("%s(%s)", layout_name, name);
1886 + parse_xkb_xml_languagelist_node (priv, sub_node, variant_lang_name);
1887 + g_free (variant_lang_name);
1891 + if (name == NULL) {
1892 + g_warning ("No name in layout node");
1895 + if (g_hash_table_lookup (priv->variant_desc, name) != NULL) {
1896 + /* This is an expected case. */
1899 + variant_lang_name = g_strdup_printf ("%s(%s)", layout_name, name);
1900 + g_hash_table_insert (priv->variant_desc,
1901 + (gpointer) variant_lang_name,
1902 + (gpointer) g_strdup (description));
1906 +static const gchar *
1907 +parse_xkb_xml_variant_node (IBusXKBConfigRegistryPrivate *priv,
1908 + XMLNode *parent_node,
1909 + const gchar *layout_name)
1911 + XMLNode *node = parent_node;
1912 + XMLNode *sub_node;
1914 + const gchar *variant_name = NULL;
1916 + g_assert (node != NULL);
1917 + g_assert (layout_name != NULL);
1918 + for (p = node->sub_nodes; p; p = p->next) {
1919 + sub_node = (XMLNode *) p->data;
1920 + if (g_strcmp0 (sub_node->name, "configItem") == 0) {
1921 + variant_name = parse_xkb_xml_variant_configitem_node (priv, sub_node, layout_name);
1925 + return variant_name;
1929 +parse_xkb_xml_variantlist_node (IBusXKBConfigRegistryPrivate *priv,
1930 + XMLNode *parent_node,
1931 + const gchar *layout_name,
1932 + GList *variant_list)
1934 + XMLNode *node = parent_node;
1935 + XMLNode *sub_node;
1937 + const gchar *variant_name = NULL;
1939 + g_assert (node != NULL);
1940 + g_assert (layout_name != NULL);
1941 + for (p = node->sub_nodes; p; p = p->next) {
1942 + sub_node = (XMLNode *) p->data;
1943 + if (g_strcmp0 (sub_node->name, "variant") == 0) {
1944 + variant_name = parse_xkb_xml_variant_node (priv, sub_node, layout_name);
1945 + if (variant_name != NULL) {
1946 + variant_list = g_list_append (variant_list,
1947 + (gpointer) g_strdup (variant_name));
1952 + return variant_list;
1956 +parse_xkb_xml_layout_node (IBusXKBConfigRegistryPrivate *priv,
1957 + XMLNode *parent_node)
1959 + XMLNode *node = parent_node;
1960 + XMLNode *sub_node;
1962 + const gchar *name = NULL;
1963 + GList *variant_list = NULL;
1965 + g_assert (node != NULL);
1966 + for (p = node->sub_nodes; p; p = p->next) {
1967 + sub_node = (XMLNode *) p->data;
1968 + if (g_strcmp0 (sub_node->name, "configItem") == 0) {
1969 + name = parse_xkb_xml_configitem_node (priv, sub_node);
1972 + if (g_strcmp0 (sub_node->name, "variantList") == 0) {
1973 + if (name == NULL) {
1974 + g_warning ("layout name is NULL in node %s", node->name);
1977 + variant_list = parse_xkb_xml_variantlist_node (priv, sub_node,
1983 + if (g_hash_table_lookup (priv->layout_list, name) != NULL) {
1984 + g_warning ("duplicated name %s exists", name);
1987 + g_hash_table_insert (priv->layout_list,
1988 + (gpointer) g_strdup (name),
1989 + (gpointer) variant_list);
1993 +parse_xkb_xml_top_node (IBusXKBConfigRegistryPrivate *priv,
1994 + XMLNode *parent_node)
1996 + XMLNode *node = parent_node;
1997 + XMLNode *sub_node;
2000 + g_assert (priv != NULL);
2001 + g_assert (node != NULL);
2003 + if (g_strcmp0 (node->name, "xkbConfigRegistry") != 0) {
2004 + g_warning ("node has no xkbConfigRegistry name");
2007 + for (p = node->sub_nodes; p; p = p->next) {
2008 + sub_node = (XMLNode *) p->data;
2009 + if (g_strcmp0 (sub_node->name, "layoutList") == 0) {
2014 + g_warning ("xkbConfigRegistry node has no layoutList node");
2018 + for (p = node->sub_nodes; p; p = p->next) {
2019 + sub_node = (XMLNode *) p->data;
2020 + if (g_strcmp0 (sub_node->name, "layout") == 0) {
2021 + parse_xkb_xml_layout_node (priv, sub_node);
2028 +free_lang_list (GList *list)
2036 + g_list_free (list);
2040 +parse_xkb_config_registry_file (IBusXKBConfigRegistryPrivate *priv,
2041 + const gchar *file)
2045 + g_assert (file != NULL);
2047 + priv->layout_list = g_hash_table_new_full (g_str_hash,
2048 + (GEqualFunc) g_str_equal,
2049 + (GDestroyNotify) g_free,
2050 + (GDestroyNotify) free_lang_list);
2051 + priv->layout_desc = g_hash_table_new_full (g_str_hash,
2052 + (GEqualFunc) g_str_equal,
2053 + (GDestroyNotify) g_free,
2054 + (GDestroyNotify) g_free);
2055 + priv->layout_lang = g_hash_table_new_full (g_str_hash,
2056 + (GEqualFunc) g_str_equal,
2057 + (GDestroyNotify) g_free,
2058 + (GDestroyNotify) free_lang_list);
2059 + priv->variant_desc = g_hash_table_new_full (g_str_hash,
2060 + (GEqualFunc) g_str_equal,
2061 + (GDestroyNotify) g_free,
2062 + (GDestroyNotify) g_free);
2063 + node = ibus_xml_parse_file (file);
2064 + parse_xkb_xml_top_node (priv, node);
2065 + ibus_xml_free (node);
2069 +ibus_xkb_config_registry_init (IBusXKBConfigRegistry *xkb_config)
2071 + IBusXKBConfigRegistryPrivate *priv;
2072 + const gchar *file = XKB_RULES_XML_FILE;
2074 + priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config);
2075 + parse_xkb_config_registry_file (priv, file);
2079 +ibus_xkb_config_registry_destroy (IBusXKBConfigRegistry *xkb_config)
2081 + IBusXKBConfigRegistryPrivate *priv;
2083 + g_return_if_fail (xkb_config != NULL);
2085 + priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config);
2087 + g_hash_table_destroy (priv->layout_list);
2088 + priv->layout_list = NULL;
2089 + g_hash_table_destroy (priv->layout_lang);
2090 + priv->layout_lang= NULL;
2091 + g_hash_table_destroy (priv->layout_desc);
2092 + priv->layout_desc= NULL;
2093 + g_hash_table_destroy (priv->variant_desc);
2094 + priv->variant_desc = NULL;
2096 + IBUS_OBJECT_CLASS(ibus_xkb_config_registry_parent_class)->destroy (IBUS_OBJECT (xkb_config));
2100 +ibus_xkb_config_registry_class_init (IBusXKBConfigRegistryClass *klass)
2102 + IBusObjectClass *ibus_object_class = IBUS_OBJECT_CLASS (klass);
2104 + g_type_class_add_private (klass, sizeof (IBusXKBConfigRegistryPrivate));
2106 + ibus_object_class->destroy = (IBusObjectDestroyFunc) ibus_xkb_config_registry_destroy;
2109 +IBusXKBConfigRegistry *
2110 +ibus_xkb_config_registry_new (void)
2112 + IBusXKBConfigRegistry *xkb_config;
2114 + xkb_config = IBUS_XKB_CONFIG_REGISTRY (g_object_new (IBUS_TYPE_XKB_CONFIG_REGISTRY, NULL));
2115 + return xkb_config;
2118 +#define TABLE_FUNC(field_name) const GHashTable * \
2119 +ibus_xkb_config_registry_get_##field_name (IBusXKBConfigRegistry *xkb_config) \
2121 + IBusXKBConfigRegistryPrivate *priv; \
2123 + g_return_val_if_fail (xkb_config != NULL, NULL); \
2124 + priv = IBUS_XKB_CONFIG_REGISTRY_GET_PRIVATE (xkb_config); \
2125 + return priv->field_name; \
2128 +TABLE_FUNC (layout_list)
2129 +TABLE_FUNC (layout_lang)
2130 +TABLE_FUNC (layout_desc)
2131 +TABLE_FUNC (variant_desc)
2136 +ibus_xkb_config_registry_layout_list_get_layouts (IBusXKBConfigRegistry *xkb_config)
2138 + GHashTable *table;
2139 + GList *list = NULL;
2141 + table = (GHashTable *)
2142 + ibus_xkb_config_registry_get_layout_list (xkb_config);
2143 + list = (GList *) g_hash_table_get_keys (table);
2147 +/* vala could use GLib.List<string> for the returned pointer and
2148 + * the declaration calls g_list_foreach (retval, g_free, NULL).
2149 + * When I think about GLib.List<string> v.s. GLib.List, probably
2150 + * I think GLib.List<string> is better for the function and set
2151 + * g_strdup() here. I do not know about GJS implementation.
2153 +#define TABLE_LOOKUP_LIST_FUNC(field_name, value) GList * \
2154 +ibus_xkb_config_registry_##field_name##_get_##value (IBusXKBConfigRegistry *xkb_config, const gchar *key) \
2156 + GHashTable *table; \
2157 + GList *list = NULL; \
2158 + GList *retval= NULL; \
2159 + GList *p = NULL; \
2161 + table = (GHashTable *) \
2162 + ibus_xkb_config_registry_get_##field_name (xkb_config); \
2163 + list = (GList *) g_hash_table_lookup (table, key); \
2164 + retval = g_list_copy (list); \
2165 + for (p = retval; p; p = p->next) { \
2166 + p->data = g_strdup (p->data); \
2171 +#define TABLE_LOOKUP_STRING_FUNC(field_name, value) gchar * \
2172 +ibus_xkb_config_registry_##field_name##_get_##value (IBusXKBConfigRegistry *xkb_config, const gchar *key) \
2174 + GHashTable *table; \
2175 + const gchar *desc = NULL; \
2177 + table = (GHashTable *) \
2178 + ibus_xkb_config_registry_get_##field_name (xkb_config); \
2179 + desc = (const gchar *) g_hash_table_lookup (table, key); \
2180 + return g_strdup (desc); \
2183 +TABLE_LOOKUP_LIST_FUNC (layout_list, variants)
2184 +TABLE_LOOKUP_LIST_FUNC (layout_lang, langs)
2185 +TABLE_LOOKUP_STRING_FUNC (layout_desc, desc)
2186 +TABLE_LOOKUP_STRING_FUNC (variant_desc, desc)
2188 +#undef TABLE_LOOKUP_LIST_FUNC
2189 +#undef TABLE_LOOKUP_STRING_FUNC
2190 diff --git a/src/ibusxkbxml.h b/src/ibusxkbxml.h
2191 new file mode 100644
2192 index 0000000..6f5b7bd
2194 +++ b/src/ibusxkbxml.h
2196 +/* -*- mode: C; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
2197 +/* vim:set et sts=4: */
2198 +/* bus - The Input Bus
2199 + * Copyright (C) 2012 Takao Fujiwara <takao.fujiwara1@gmail.com>
2200 + * Copyright (C) 2012 Peng Huang <shawn.p.huang@gmail.com>
2201 + * Copyright (C) 2012 Red Hat, Inc.
2203 + * This library is free software; you can redistribute it and/or
2204 + * modify it under the terms of the GNU Lesser General Public
2205 + * License as published by the Free Software Foundation; either
2206 + * version 2 of the License, or (at your option) any later version.
2208 + * This library is distributed in the hope that it will be useful,
2209 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2210 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2211 + * Lesser General Public License for more details.
2213 + * You should have received a copy of the GNU Lesser General Public
2214 + * License along with this library; if not, write to the
2215 + * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
2216 + * Boston, MA 02111-1307, USA.
2218 +#ifndef __IBUS_XKBXML_H_
2219 +#define __IBUS_XKBXML_H_
2221 +#if !defined (__IBUS_H_INSIDE__) && !defined (IBUS_COMPILATION)
2222 +#error "Only <ibus.h> can be included directly"
2230 +/* define IBusXKBConfigRegistry macros */
2231 +#define IBUS_TYPE_XKB_CONFIG_REGISTRY \
2232 + (ibus_xkb_config_registry_get_type ())
2233 +#define IBUS_XKB_CONFIG_REGISTRY(obj) \
2234 + (G_TYPE_CHECK_INSTANCE_CAST ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistry))
2235 +#define IBUS_XKB_CONFIG_REGISTRY_CLASS(klass) \
2236 + (G_TYPE_CHECK_CLASS_CAST ((klass), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryClass))
2237 +#define IBUS_IS_XKB_CONFIG_REGISTRY(obj) \
2238 + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY))
2239 +#define IBUS_IS_XKB_CONFIG_REGISTRY_CLASS(klass) \
2240 + (G_TYPE_CHECK_CLASS_TYPE ((klass), IBUS_TYPE_XKB_CONFIG_REGISTRY))
2241 +#define IBUS_XKB_CONFIG_REGISTRY_GET_CLASS(obj) \
2242 + (G_TYPE_INSTANCE_GET_CLASS ((obj), IBUS_TYPE_XKB_CONFIG_REGISTRY, IBusXKBConfigRegistryClass))
2246 +typedef struct _IBusXKBConfigRegistry IBusXKBConfigRegistry;
2247 +typedef struct _IBusXKBConfigRegistryClass IBusXKBConfigRegistryClass;
2249 +struct _IBusXKBConfigRegistry {
2250 + IBusObject parent;
2253 +struct _IBusXKBConfigRegistryClass {
2254 + IBusObjectClass parent;
2258 + gpointer pdummy[8];
2262 +GType ibus_xkb_config_registry_get_type
2266 + * ibus_xkb_config_registry_new:
2267 + * @returns: A newly allocated IBusXKBConfigRegistry
2269 + * New an IBusXKBConfigRegistry.
2271 +IBusXKBConfigRegistry *
2272 + ibus_xkb_config_registry_new
2276 + * ibus_xkb_config_registry_get_layout_list: (skip)
2277 + * @xkb_config: An IBusXKBConfigRegistry.
2278 + * @returns: A const GHashTable
2280 + * a const GHashTable
2283 + ibus_xkb_config_registry_get_layout_list
2284 + (IBusXKBConfigRegistry *xkb_config);
2287 + * ibus_xkb_config_registry_get_layout_lang: (skip)
2288 + * @xkb_config: An IBusXKBConfigRegistry.
2289 + * @returns: A const GHashTable
2291 + * a const GHashTable
2294 + ibus_xkb_config_registry_get_layout_lang
2295 + (IBusXKBConfigRegistry *xkb_config);
2298 + * ibus_xkb_config_registry_get_layout_desc: (skip)
2299 + * @xkb_config: An IBusXKBConfigRegistry.
2300 + * @returns: A const GHashTable
2302 + * a const GHashTable
2305 + ibus_xkb_config_registry_get_layout_desc
2306 + (IBusXKBConfigRegistry *xkb_config);
2309 + * ibus_xkb_config_registry_get_variant_desc: (skip)
2310 + * @xkb_config: An IBusXKBConfigRegistry.
2311 + * @returns: A const GHashTable
2313 + * a const GHashTable
2316 + ibus_xkb_config_registry_get_variant_desc
2317 + (IBusXKBConfigRegistry *xkb_config);
2320 + * ibus_xkb_config_registry_layout_list_get_layouts:
2321 + * @xkb_config: An IBusXKBConfigRegistry.
2322 + * @returns: (transfer container) (element-type utf8): A GList of layouts
2324 + * a GList of layouts
2327 + ibus_xkb_config_registry_layout_list_get_layouts
2328 + (IBusXKBConfigRegistry *xkb_config);
2331 + * ibus_xkb_config_registry_layout_list_get_variants:
2332 + * @xkb_config: An IBusXKBConfigRegistry.
2333 + * @layout: A layout.
2334 + * @returns: (transfer container) (element-type utf8): A GList
2339 + ibus_xkb_config_registry_layout_list_get_variants
2340 + (IBusXKBConfigRegistry *xkb_config,
2341 + const gchar *layout);
2344 + * ibus_xkb_config_registry_layout_lang_get_langs:
2345 + * @xkb_config: An IBusXKBConfigRegistry.
2346 + * @layout: A layout.
2347 + * @returns: (transfer container) (element-type utf8): A GList
2352 + ibus_xkb_config_registry_layout_lang_get_langs
2353 + (IBusXKBConfigRegistry *xkb_config,
2354 + const gchar *layout);
2357 + * ibus_xkb_config_registry_layout_desc_get_desc:
2358 + * @xkb_config: An IBusXKBConfigRegistry.
2359 + * @layout: A layout.
2360 + * @returns: A layout description
2362 + * a layout description
2365 + ibus_xkb_config_registry_layout_desc_get_desc
2366 + (IBusXKBConfigRegistry *xkb_config,
2367 + const gchar *layout);
2370 + * ibus_xkb_config_registry_variant_desc_get_desc:
2371 + * @xkb_config: An IBusXKBConfigRegistry.
2372 + * @variant: A variant.
2373 + * @returns: A variant description
2375 + * a variant description
2378 + ibus_xkb_config_registry_variant_desc_get_desc
2379 + (IBusXKBConfigRegistry *xkb_config,
2380 + const gchar *variant);
2383 diff --git a/ui/gtk3/Makefile.am b/ui/gtk3/Makefile.am
2384 index 5473027..cbd746c 100644
2385 --- a/ui/gtk3/Makefile.am
2386 +++ b/ui/gtk3/Makefile.am
2387 @@ -47,6 +47,9 @@ USE_SYMBOL_ICON = FALSE
2388 # force include config.h before gi18n.h.
2389 AM_CPPFLAGS = -include $(CONFIG_HEADER)
2391 +HAVE_IBUS_XKB_C = $(strip $(subst false, FALSE, $(subst true, TRUE, $(HAVE_IBUS_XKB))))
2392 +HAVE_IBUS_GKBD_C = $(strip $(subst false, FALSE, $(subst true, TRUE, $(HAVE_IBUS_GKBD))))
2397 @@ -58,6 +61,10 @@ AM_CFLAGS = \
2398 -DBINDIR=\"$(bindir)\" \
2399 -DIBUS_DISABLE_DEPRECATED \
2400 -DSWITCHER_USE_SYMBOL_ICON=$(USE_SYMBOL_ICON) \
2401 + -DHAVE_IBUS_XKB=$(HAVE_IBUS_XKB_C) \
2402 + -DHAVE_IBUS_GKBD=$(HAVE_IBUS_GKBD_C) \
2403 + -DIBUS_XKB_COMMAND=\"$(libexecdir)/ibus-xkb\" \
2404 + -DXKB_LAYOUTS_MAX_LENGTH=4 \
2405 -Wno-unused-variable \
2406 -Wno-unused-but-set-variable \
2407 -Wno-unused-function \
2408 @@ -91,6 +98,7 @@ ibus_ui_gtk3_SOURCES = \
2410 candidatearea.vala \
2411 candidatepanel.vala \
2415 keybindingmanager.vala \
2416 @@ -99,17 +107,48 @@ ibus_ui_gtk3_SOURCES = \
2423 ibus_ui_gtk3_LDADD = \
2427 +if ENABLE_LIBGNOMEKBD
2429 + @LIBGNOMEKBDUI_CFLAGS@ \
2434 + @LIBGNOMEKBDUI_LIBS@ \
2440 + --metadatadir=$(top_srcdir)/bindings/vala \
2442 + --pkg=gmodule-2.0 \
2447 +$(srcdir)/gkbdlayout.vala: $(top_builddir)/bindings/vala/gkbd.vapi
2448 + @cp $(srcdir)/gkbdlayout.vala.true $(srcdir)/gkbdlayout.vala
2450 +$(srcdir)/gkbdlayout.vala:
2451 + @cp $(srcdir)/gkbdlayout.vala.false $(srcdir)/gkbdlayout.vala
2460 + gkbdlayout.vala.false \
2461 + gkbdlayout.vala.true \
2462 gtkpanel.xml.in.in \
2465 diff --git a/ui/gtk3/gkbdlayout.vala.false b/ui/gtk3/gkbdlayout.vala.false
2466 new file mode 100644
2467 index 0000000..a387de9
2469 +++ b/ui/gtk3/gkbdlayout.vala.false
2471 +/* vim:set et sts=4 sw=4:
2473 + * ibus - The Input Bus
2475 + * Copyright 2012 Red Hat, Inc.
2476 + * Copyright(c) 2012 Peng Huang <shawn.p.huang@gmail.com>
2477 + * Copyright(c) 2012 Takao Fujiwara <tfujiwar@redhat.com>
2479 + * This library is free software; you can redistribute it and/or
2480 + * modify it under the terms of the GNU Lesser General Public
2481 + * License as published by the Free Software Foundation; either
2482 + * version 2 of the License, or(at your option) any later version.
2484 + * This library is distributed in the hope that it will be useful,
2485 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2486 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2487 + * GNU Lesser General Public License for more details.
2489 + * You should have received a copy of the GNU Lesser General Public
2490 + * License along with this program; if not, write to the
2491 + * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
2492 + * Boston, MA 02111-1307 USA
2495 +public class GkbdLayout
2497 + public signal void changed();
2498 + public signal void group_changed (int object);
2500 + public GkbdLayout() {
2503 + public string[] get_layouts() {
2504 + return new string[0];
2507 + public string[] get_group_names() {
2508 + return new string[0];
2511 + public void lock_group(int id) {
2514 + public void start_listen() {
2517 + public void stop_listen() {
2521 + public static int main(string[] args) {
2522 + GkbdLayout ibus_layouts = new GkbdLayout();
2524 + string[] layouts = ibus_layouts.get_layouts();
2525 + string[] names = ibus_layouts.get_group_names();
2526 + for (int i = 0; layouts != null && i < layouts.length; i++) {
2527 + stdout.printf("%s %s\n", layouts[i], names[i]);
2534 diff --git a/ui/gtk3/gkbdlayout.vala.true b/ui/gtk3/gkbdlayout.vala.true
2535 new file mode 100644
2536 index 0000000..2b78c69
2538 +++ b/ui/gtk3/gkbdlayout.vala.true
2540 +/* vim:set et sts=4 sw=4:
2542 + * ibus - The Input Bus
2544 + * Copyright 2012 Red Hat, Inc.
2545 + * Copyright(c) 2012 Peng Huang <shawn.p.huang@gmail.com>
2546 + * Copyright(c) 2012 Takao Fujiwara <tfujiwar@redhat.com>
2548 + * This library is free software; you can redistribute it and/or
2549 + * modify it under the terms of the GNU Lesser General Public
2550 + * License as published by the Free Software Foundation; either
2551 + * version 2 of the License, or(at your option) any later version.
2553 + * This library is distributed in the hope that it will be useful,
2554 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
2555 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2556 + * GNU Lesser General Public License for more details.
2558 + * You should have received a copy of the GNU Lesser General Public
2559 + * License along with this program; if not, write to the
2560 + * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
2561 + * Boston, MA 02111-1307 USA
2564 +public class GkbdLayout
2566 + public signal void changed();
2567 + public signal void group_changed (int object);
2569 + private Gkbd.Configuration m_config = null;
2571 + public GkbdLayout() {
2572 + m_config = Gkbd.Configuration.get();
2573 + if (m_config != null) {
2574 + m_config.changed.connect(config_changed_cb);
2575 + m_config.group_changed.connect(config_group_changed_cb);
2580 + if (m_config != null) {
2581 + m_config.changed.disconnect(config_changed_cb);
2582 + m_config.group_changed.disconnect(config_group_changed_cb);
2583 + /* gkbd_configuration_get reuses the object and do not
2584 + * destroy m_config here. */
2590 + private void config_changed_cb() {
2594 + private void config_group_changed_cb(int object) {
2595 + group_changed(object);
2598 + public string[] get_layouts() {
2599 + if (m_config == null) {
2600 + return new string[0];
2602 + return m_config.get_short_group_names();
2605 + public string[] get_group_names() {
2606 + if (m_config == null) {
2607 + return new string[0];
2609 + return m_config.get_group_names();
2612 + public void lock_group(int id) {
2613 + if (m_config == null) {
2616 + m_config.lock_group(id);
2619 + public void start_listen() {
2620 + if (m_config == null) {
2623 + m_config.start_listen();
2626 + public void stop_listen() {
2627 + if (m_config == null) {
2630 + m_config.stop_listen();
2634 + public static int main(string[] args) {
2635 + Gtk.init(ref args);
2636 + GkbdLayout ibus_layouts = new GkbdLayout();
2638 + string[] layouts = ibus_layouts.get_layouts();
2639 + string[] names = ibus_layouts.get_group_names();
2640 + for (int i = 0; layouts != null && i < layouts.length; i++) {
2641 + stdout.printf("%s %s\n", layouts[i], names[i]);
2648 diff --git a/ui/gtk3/keybindingmanager.vala b/ui/gtk3/keybindingmanager.vala
2649 index 5ff0c65..bfe560c 100644
2650 --- a/ui/gtk3/keybindingmanager.vala
2651 +++ b/ui/gtk3/keybindingmanager.vala
2652 @@ -41,15 +41,18 @@ public class KeybindingManager : GLib.Object {
2653 private class Keybinding {
2654 public Keybinding(uint keysym,
2655 Gdk.ModifierType modifiers,
2656 - KeybindingHandlerFunc handler) {
2657 + KeybindingHandlerFunc handler,
2659 this.keysym = keysym;
2660 this.modifiers = modifiers;
2661 this.handler = handler;
2662 + this.reverse = reverse;
2665 public uint keysym { get; set; }
2666 public Gdk.ModifierType modifiers { get; set; }
2667 public unowned KeybindingHandlerFunc handler { get; set; }
2668 + public bool reverse { get; set; }
2672 @@ -57,7 +60,7 @@ public class KeybindingManager : GLib.Object {
2674 * @param event passing on gdk event
2676 - public delegate void KeybindingHandlerFunc(Gdk.Event event);
2677 + public delegate void KeybindingHandlerFunc(Gdk.Event event, bool reverse);
2680 private KeybindingManager() {
2681 @@ -73,7 +76,8 @@ public class KeybindingManager : GLib.Object {
2683 public bool bind(uint keysym,
2684 Gdk.ModifierType modifiers,
2685 - KeybindingHandlerFunc handler) {
2686 + KeybindingHandlerFunc handler,
2688 unowned X.Display display = Gdk.x11_get_default_xdisplay();
2690 int keycode = display.keysym_to_keycode(keysym);
2691 @@ -84,7 +88,7 @@ public class KeybindingManager : GLib.Object {
2692 grab_keycode (Gdk.Display.get_default(), keysym, modifiers);
2695 - Keybinding binding = new Keybinding(keysym, modifiers, handler);
2696 + Keybinding binding = new Keybinding(keysym, modifiers, handler, reverse);
2697 m_bindings.append(binding);
2700 @@ -198,7 +202,7 @@ public class KeybindingManager : GLib.Object {
2701 if (event.key.keyval != binding.keysym ||
2702 modifiers != binding.modifiers)
2704 - binding.handler(event);
2705 + binding.handler(event, binding.reverse);
2709 diff --git a/ui/gtk3/panel.vala b/ui/gtk3/panel.vala
2710 index 40079ec..8e6f756 100644
2711 --- ibus-1.4.99.20121109/ui/gtk3/panel.vala.orig 2012-11-09 07:16:19.000000000 +0100
2712 +++ ibus-1.4.99.20121109/ui/gtk3/panel.vala 2012-11-17 19:22:03.176142457 +0100
2716 class Panel : IBus.PanelService {
2717 + private class Keybinding {
2718 + public Keybinding(uint keysym,
2719 + Gdk.ModifierType modifiers,
2721 + this.keysym = keysym;
2722 + this.modifiers = modifiers;
2723 + this.reverse = reverse;
2726 + public uint keysym { get; set; }
2727 + public Gdk.ModifierType modifiers { get; set; }
2728 + public bool reverse { get; set; }
2731 private IBus.Bus m_bus;
2732 private IBus.Config m_config;
2733 private Gtk.StatusIcon m_status_icon;
2735 private Gtk.AboutDialog m_about_dialog;
2736 private Gtk.CssProvider m_css_provider;
2737 private int m_switcher_delay_time = 400;
2738 + private GkbdLayout m_gkbdlayout = null;
2739 + private XKBLayout m_xkblayout = null;
2740 + private string[] m_layouts = {};
2741 + private string[] m_variants = {};
2742 + private int m_fallback_lock_id = -1;
2743 + private bool m_changed_xkb_option = false;
2744 + private GLib.Timer m_changed_layout_timer;
2745 private const string ACCELERATOR_SWITCH_IME_FOREWARD = "<Control>space";
2746 + private const string ACCELERATOR_SWITCH_IME_BACKWARD = "<Control><Shift>space";
2748 - private uint m_switch_keysym = 0;
2749 - private Gdk.ModifierType m_switch_modifiers = 0;
2750 + private GLib.List<Keybinding> m_keybindings = new GLib.List<Keybinding>();
2752 public Panel(IBus.Bus bus) {
2753 GLib.assert(bus.is_connected());
2755 m_candidate_panel.page_down.connect((w) => this.page_down());
2757 m_switcher = new Switcher();
2758 - bind_switch_shortcut();
2760 if (m_switcher_delay_time >= 0) {
2761 m_switcher.set_popup_delay_time((uint) m_switcher_delay_time);
2762 @@ -76,64 +96,135 @@
2765 unbind_switch_shortcut();
2768 - private void bind_switch_shortcut() {
2769 - var keybinding_manager = KeybindingManager.get_instance();
2770 + if (HAVE_IBUS_GKBD && m_gkbdlayout != null) {
2771 + m_gkbdlayout.changed.disconnect(gkbdlayout_changed_cb);
2772 + m_gkbdlayout.stop_listen();
2773 + m_gkbdlayout = null;
2776 + m_xkblayout = null;
2779 - var accelerator = ACCELERATOR_SWITCH_IME_FOREWARD;
2780 + private void keybinding_manager_bind(KeybindingManager keybinding_manager,
2781 + string? accelerator,
2783 + uint switch_keysym = 0;
2784 + Gdk.ModifierType switch_modifiers = 0;
2785 Gtk.accelerator_parse(accelerator,
2786 - out m_switch_keysym, out m_switch_modifiers);
2787 + out switch_keysym, out switch_modifiers);
2789 - // Map virtual modifiers to (i.e.Mod2, Mod3, ...)
2790 + // Map virtual modifiers to (i.e. Mod2, Mod3, ...)
2791 const Gdk.ModifierType VIRTUAL_MODIFIERS = (
2792 Gdk.ModifierType.SUPER_MASK |
2793 Gdk.ModifierType.HYPER_MASK |
2794 Gdk.ModifierType.META_MASK);
2795 - if ((m_switch_modifiers & VIRTUAL_MODIFIERS) != 0) {
2796 + if ((switch_modifiers & VIRTUAL_MODIFIERS) != 0) {
2797 // workaround a bug in gdk vapi vala > 0.18
2798 // https://bugzilla.gnome.org/show_bug.cgi?id=677559
2800 Gdk.Keymap.get_default().map_virtual_modifiers(
2801 - ref m_switch_modifiers);
2802 + ref switch_modifiers);
2804 - if ((m_switch_modifiers & Gdk.ModifierType.SUPER_MASK) != 0)
2805 - m_switch_modifiers |= Gdk.ModifierType.MOD4_MASK;
2806 - if ((m_switch_modifiers & Gdk.ModifierType.HYPER_MASK) != 0)
2807 - m_switch_modifiers |= Gdk.ModifierType.MOD4_MASK;
2808 + if ((switch_modifiers & Gdk.ModifierType.SUPER_MASK) != 0)
2809 + switch_modifiers |= Gdk.ModifierType.MOD4_MASK;
2810 + if ((switch_modifiers & Gdk.ModifierType.HYPER_MASK) != 0)
2811 + switch_modifiers |= Gdk.ModifierType.MOD4_MASK;
2813 - m_switch_modifiers &= ~VIRTUAL_MODIFIERS;
2814 + switch_modifiers &= ~VIRTUAL_MODIFIERS;
2817 - if (m_switch_keysym == 0 && m_switch_modifiers == 0) {
2818 + if (switch_keysym == 0 && switch_modifiers == 0) {
2819 warning("Parse accelerator '%s' failed!", accelerator);
2823 - keybinding_manager.bind(m_switch_keysym, m_switch_modifiers,
2824 - (e) => handle_engine_switch(e, false));
2825 + Keybinding keybinding = new Keybinding(switch_keysym,
2828 + m_keybindings.append(keybinding);
2830 + keybinding_manager.bind(switch_keysym, switch_modifiers,
2831 + (e, _reverse) => handle_engine_switch(e, _reverse),
2835 - // accelerator already has Shift mask
2836 - if ((m_switch_modifiers & Gdk.ModifierType.SHIFT_MASK) != 0)
2838 + // ToDo: Customize the input method with ibus-setup
2839 + private void bind_switch_shortcut() {
2840 + string locale = GLib.Intl.setlocale(GLib.LocaleCategory.ALL,
2842 + if (locale == null) {
2846 + string[] ACCELERATOR_IME_HOTKEYS = {};
2847 + ACCELERATOR_IME_HOTKEYS += ACCELERATOR_SWITCH_IME_FOREWARD;
2849 - keybinding_manager.bind(m_switch_keysym,
2850 - m_switch_modifiers | Gdk.ModifierType.SHIFT_MASK,
2851 - (e) => handle_engine_switch(e, true));
2852 + if (m_config != null) {
2853 + GLib.Variant variant = m_config.get_value("general/hotkey",
2855 + if (variant != null) {
2856 + ACCELERATOR_IME_HOTKEYS = {};
2857 + for (int i = 0; i < variant.n_children(); i++) {
2858 + ACCELERATOR_IME_HOTKEYS += variant.get_child_value(i).dup_string();
2863 + if (ACCELERATOR_IME_HOTKEYS.length == 1 &&
2864 + ACCELERATOR_IME_HOTKEYS[0] == ACCELERATOR_SWITCH_IME_FOREWARD) {
2865 + // FIXME: When us keyboard is used, Zenkaku_Hankaku does not work.
2867 + if (locale[0:2] == "ja") {
2868 + ACCELERATOR_IME_HOTKEYS += "Zenkaku_Hankaku";
2871 + if (locale[0:2] == "ko") {
2872 + ACCELERATOR_IME_HOTKEYS += "Hangul";
2873 + ACCELERATOR_IME_HOTKEYS += "Alt_R";
2877 + var keybinding_manager = KeybindingManager.get_instance();
2879 + foreach (var accelerator in ACCELERATOR_IME_HOTKEYS) {
2880 + keybinding_manager_bind(keybinding_manager, accelerator, false);
2883 + ACCELERATOR_IME_HOTKEYS = {};
2884 + ACCELERATOR_IME_HOTKEYS += ACCELERATOR_SWITCH_IME_BACKWARD;
2886 + if (m_config != null) {
2887 + GLib.Variant variant = m_config.get_value("general/hotkey",
2888 + "trigger_accel_backward");
2889 + if (variant != null) {
2890 + ACCELERATOR_IME_HOTKEYS = {};
2891 + for (int i = 0; i < variant.n_children(); i++) {
2892 + ACCELERATOR_IME_HOTKEYS += variant.get_child_value(i).dup_string();
2897 + foreach (var accelerator in ACCELERATOR_IME_HOTKEYS) {
2898 + keybinding_manager_bind(keybinding_manager, accelerator, true);
2902 private void unbind_switch_shortcut() {
2903 var keybinding_manager = KeybindingManager.get_instance();
2905 - if (m_switch_keysym == 0 && m_switch_modifiers == 0)
2907 + unowned GLib.List<Keybinding> keybindings = m_keybindings;
2909 + while (keybindings != null) {
2910 + Keybinding keybinding = keybindings.data;
2912 - keybinding_manager.unbind(m_switch_keysym, m_switch_modifiers);
2913 - keybinding_manager.unbind(m_switch_keysym,
2914 - m_switch_modifiers | Gdk.ModifierType.SHIFT_MASK);
2915 + keybinding_manager.unbind(keybinding.keysym,
2916 + keybinding.modifiers);
2918 - m_switch_keysym = 0;
2919 - m_switch_modifiers = 0;
2920 + // Need to get keybindings.next before GList.remove is called.
2921 + keybindings = keybindings.next;
2922 + m_keybindings.remove(keybinding);
2926 private void set_custom_font() {
2927 @@ -220,13 +311,17 @@
2931 + bind_switch_shortcut();
2932 if (m_config != null) {
2933 m_config.value_changed.connect(config_value_changed_cb);
2934 m_config.watch("general", "preload_engines");
2935 m_config.watch("general", "engines_order");
2936 m_config.watch("general", "switcher_delay_time");
2937 + m_config.watch("general/hotkey", "trigger_accel");
2938 + m_config.watch("general/hotkey", "trigger_accel_backward");
2939 m_config.watch("panel", "custom_font");
2940 m_config.watch("panel", "use_custom_font");
2941 + init_engines_order();
2942 update_engines(m_config.get_value("general", "preload_engines"),
2943 m_config.get_value("general", "engines_order"));
2944 set_switcher_delay_time(null);
2945 @@ -282,6 +377,192 @@
2949 + private void gkbdlayout_changed_cb() {
2950 + /* The callback is called four times after set_layout is called
2951 + * so check the elapsed and take the first signal only. */
2952 + double elapsed = m_changed_layout_timer.elapsed();
2953 + if (elapsed < 1.0 && elapsed > 0.0) {
2957 + if (m_fallback_lock_id != -1) {
2958 + /* Call lock_group only when set_layout is called. */
2959 + m_gkbdlayout.lock_group(m_fallback_lock_id);
2960 + m_fallback_lock_id = -1;
2962 + /* Reset default layout when gnome-control-center is called. */
2963 + m_xkblayout.reset_layout();
2966 + update_xkb_engines();
2967 + m_changed_layout_timer.reset();
2970 + private void init_gkbd() {
2971 + m_gkbdlayout = new GkbdLayout();
2972 + m_gkbdlayout.changed.connect(gkbdlayout_changed_cb);
2974 + /* Probably we cannot support both keyboard and ibus indicators
2975 + * How can I get the engine from keymap of group_id?
2976 + * e.g. 'en' could be owned by xkb:en and pinyin engines. */
2977 + //m_gkbdlayout.group_changed.connect((object) => {});
2979 + m_changed_layout_timer = new GLib.Timer();
2980 + m_changed_layout_timer.start();
2981 + m_gkbdlayout.start_listen();
2984 + private void init_engines_order() {
2985 + if (m_config == null) {
2989 + m_xkblayout = new XKBLayout(m_config);
2991 + if (HAVE_IBUS_GKBD) {
2995 + update_xkb_engines();
2998 + private void update_xkb_engines() {
2999 + string var_layout = m_xkblayout.get_layout();
3000 + string var_variant = m_xkblayout.get_variant();
3001 + if (var_layout == "") {
3005 + m_layouts = var_layout.split(",");
3006 + m_variants = var_variant.split(",");
3008 + IBus.XKBConfigRegistry registry = new IBus.XKBConfigRegistry();
3009 + string[] var_xkb_engine_names = {};
3010 + for (int i = 0; i < m_layouts.length; i++) {
3011 + string name = m_layouts[i];
3012 + string lang = null;
3014 + if (i < m_variants.length && m_variants[i] != "") {
3015 + name = "%s:%s".printf(name, m_variants[i]);
3016 + string layout = "%s(%s)".printf(name, m_variants[i]);
3017 + GLib.List<string> langs =
3018 + registry.layout_lang_get_langs(layout);
3019 + if (langs.length() != 0) {
3020 + lang = langs.data;
3023 + name = "%s:".printf(name);
3026 + if (lang == null) {
3027 + GLib.List<string> langs =
3028 + registry.layout_lang_get_langs(m_layouts[i]);
3029 + if (langs.length() != 0) {
3030 + lang = langs.data;
3034 + var_xkb_engine_names += "%s:%s:%s".printf("xkb", name, lang);
3037 + GLib.Variant var_engines =
3038 + m_config.get_value("general", "preload_engines");
3039 + string[] engine_names = {};
3040 + bool updated_engine_names = false;
3042 + if (var_engines != null) {
3043 + engine_names = var_engines.dup_strv();
3046 + foreach (string name in var_xkb_engine_names) {
3047 + if (name in engine_names)
3049 + updated_engine_names = true;
3050 + engine_names += name;
3053 + if (updated_engine_names) {
3054 + m_config.set_value("general",
3055 + "preload_engines",
3056 + new GLib.Variant.strv(engine_names));
3059 + GLib.Variant var_order =
3060 + m_config.get_value("general", "engines_order");
3061 + string[] order_names = {};
3062 + bool updated_order_names = false;
3064 + if (var_order != null) {
3065 + order_names = var_order.dup_strv();
3068 + foreach (var name in var_xkb_engine_names) {
3069 + if (name in order_names)
3071 + order_names += name;
3072 + updated_order_names = true;
3075 + if (updated_order_names) {
3076 + m_config.set_value("general",
3078 + new GLib.Variant.strv(order_names));
3082 + private void set_xkb_group_layout(string layout) {
3083 + int[] retval = m_xkblayout.set_layout(layout);
3084 + if (retval[0] >= 0) {
3085 + /* If an XKB keymap is added into the XKB group,
3086 + * this._gkbdlayout.lock_group will be called after
3087 + * 'group-changed' signal is received. */
3088 + m_fallback_lock_id = retval[0];
3089 + m_changed_xkb_option = (retval[1] != 0) ? true : false;
3093 + private bool set_gkbd_layout(string layout) {
3094 + /* If a previous ibus engine changed XKB options, need to set the
3095 + * default XKB option. */
3096 + if (m_changed_xkb_option == true) {
3097 + m_changed_xkb_option = false;
3101 + int gkbd_len = m_gkbdlayout.get_group_names().length;
3102 + for (int i = 0; i < m_layouts.length && i < gkbd_len; i++) {
3103 + string sys_layout = m_layouts[i];
3104 + if (i < m_variants.length && m_variants[i] != "") {
3105 + sys_layout = "%s(%s)".printf(sys_layout, m_variants[i]);
3107 + if (sys_layout == layout) {
3108 + m_gkbdlayout.lock_group(i);
3115 + private void set_layout(string layout) {
3116 + if (layout == "default" || layout == null) {
3120 + if (m_xkblayout == null) {
3121 + init_engines_order();
3124 + if (HAVE_IBUS_GKBD) {
3125 + if (set_gkbd_layout(layout)) {
3128 + set_xkb_group_layout(layout);
3132 + m_xkblayout.set_layout(layout);
3135 private void switch_engine(int i, bool force = false) {
3136 GLib.assert(i >= 0 && i < m_engines.length);
3142 - exec_setxkbmap(engine);
3143 + set_layout(engine.get_layout());
3146 private void config_value_changed_cb(IBus.Config config,
3147 @@ -308,6 +589,13 @@
3151 + if (section == "general/hotkey" &&
3152 + name.length >= 13 && name[0:13] == "trigger_accel") {
3153 + unbind_switch_shortcut();
3154 + bind_switch_shortcut();
3158 if (section == "panel" && (name == "custom_font" ||
3159 name == "use_custom_font")) {
3162 event, primary_modifiers);
3163 if (pressed && m_switcher_delay_time >= 0) {
3164 int i = revert ? m_engines.length - 1 : 1;
3165 - i = m_switcher.run(m_switch_keysym, m_switch_modifiers, event,
3167 + i = m_switcher.run(m_keybindings, event, m_engines, i);
3169 debug("switch cancelled");
3171 diff --git a/ui/gtk3/switcher.vala b/ui/gtk3/switcher.vala
3172 index ab2040b..dff5c96 100644
3173 --- ibus-1.4.99.20121109/ui/gtk3/switcher.vala.orig 2012-11-17 19:05:59.422829209 +0100
3174 +++ ibus-1.4.99.20121109/ui/gtk3/switcher.vala 2012-11-17 19:23:40.539473761 +0100
3176 public string longname { get; set; }
3179 + private class Keybinding {
3180 + public Keybinding(uint keysym,
3181 + Gdk.ModifierType modifiers,
3183 + this.keysym = keysym;
3184 + this.modifiers = modifiers;
3185 + this.reverse = reverse;
3188 + public uint keysym { get; set; }
3189 + public Gdk.ModifierType modifiers { get; set; }
3190 + public bool reverse { get; set; }
3193 private Gtk.Box m_box;
3194 private Gtk.Label m_label;
3195 private IBusEngineButton[] m_buttons = {};
3196 private IBus.EngineDesc[] m_engines;
3197 private uint m_selected_engine;
3198 - private uint m_keyval;
3199 - private uint m_modifiers;
3200 + private unowned GLib.List<Keybinding> m_keybindings;
3201 private Gdk.ModifierType m_primary_modifier;
3202 private GLib.MainLoop m_loop;
3203 private int m_result;
3204 @@ -109,19 +122,17 @@
3208 - public int run(uint keyval,
3210 + public int run(GLib.List keybindings,
3212 IBus.EngineDesc[] engines,
3214 assert (m_loop == null);
3215 assert (index < engines.length);
3217 - m_keyval = keyval;
3218 - m_modifiers = state;
3219 + m_keybindings = (GLib.List<Keybinding>) keybindings;
3220 m_primary_modifier =
3221 KeybindingManager.get_primary_modifier(
3222 - state & KeybindingManager.MODIFIER_FILTER);
3223 + event.key.state & KeybindingManager.MODIFIER_FILTER);
3225 update_engines(engines);
3226 /* Let gtk recalculate the window size. */
3227 @@ -328,27 +339,29 @@
3228 public override bool key_press_event(Gdk.EventKey e) {
3230 Gdk.EventKey *pe = &e;
3231 + uint modifiers = KeybindingManager.MODIFIER_FILTER & pe->state;
3233 if (m_popup_delay_time > 0) {
3234 restore_window_position("pressed");
3238 - uint modifiers = KeybindingManager.MODIFIER_FILTER & pe->state;
3240 - if ((modifiers != m_modifiers) &&
3241 - (modifiers != (m_modifiers | Gdk.ModifierType.SHIFT_MASK))) {
3245 - if (pe->keyval == m_keyval) {
3246 - if (modifiers == m_modifiers)
3247 + for (unowned GLib.List<Keybinding> keybindings = m_keybindings;
3248 + keybindings != null;
3249 + keybindings = keybindings.next) {
3250 + Keybinding keybinding = keybindings.data;
3252 + if (pe->keyval == keybinding.keysym &&
3253 + modifiers == (uint) keybinding.modifiers) {
3254 + if (!keybinding.reverse) {
3256 - else // modififers == m_modifiers | SHIFT_MASK
3266 switch (pe->keyval) {
3267 case 0x08fb: /* leftarrow */
3268 case 0xff51: /* Left */
3269 diff --git a/ui/gtk3/xkblayout.vala b/ui/gtk3/xkblayout.vala
3270 new file mode 100644
3271 index 0000000..33e9d9d
3273 +++ b/ui/gtk3/xkblayout.vala
3275 +/* vim:set et sts=4 sw=4:
3277 + * ibus - The Input Bus
3279 + * Copyright 2012 Red Hat, Inc.
3280 + * Copyright(c) 2012 Peng Huang <shawn.p.huang@gmail.com>
3281 + * Copyright(c) 2012 Takao Fujiwara <tfujiwar@redhat.com>
3283 + * This library is free software; you can redistribute it and/or
3284 + * modify it under the terms of the GNU Lesser General Public
3285 + * License as published by the Free Software Foundation; either
3286 + * version 2 of the License, or(at your option) any later version.
3288 + * This library is distributed in the hope that it will be useful,
3289 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
3290 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3291 + * GNU Lesser General Public License for more details.
3293 + * You should have received a copy of the GNU Lesser General Public
3294 + * License along with this program; if not, write to the
3295 + * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
3296 + * Boston, MA 02111-1307 USA
3299 +public extern const bool HAVE_IBUS_GKBD;
3300 +public extern const bool HAVE_IBUS_XKB;
3301 +public extern const int XKB_LAYOUTS_MAX_LENGTH;
3302 +public extern const string IBUS_XKB_COMMAND;
3306 + string m_xkb_command = IBUS_XKB_COMMAND;
3307 + IBus.Config m_config = null;
3308 + string[] m_xkb_latin_layouts = {};
3309 + GLib.Pid m_xkb_pid = -1;
3310 + GLib.Pid m_xmodmap_pid = -1;
3311 + string m_xmodmap_command = "xmodmap";
3312 + bool m_use_xmodmap = true;
3313 + string[] m_xmodmap_known_files = {".xmodmap", ".xmodmaprc",
3314 + ".Xmodmap", ".Xmodmaprc"};
3315 + string m_default_layout = "";
3316 + string m_default_variant = "";
3317 + string m_default_option = "";
3319 + public XKBLayout(IBus.Config? config) {
3320 + if (!HAVE_IBUS_XKB) {
3321 + m_xkb_command = "setxkbmap";
3324 + m_config = config;
3326 + if (config != null) {
3327 + var value = config.get_value("general", "xkb_latin_layouts");
3328 + for (int i = 0; value != null && i < value.n_children(); i++) {
3329 + m_xkb_latin_layouts +=
3330 + value.get_child_value(i).dup_string();
3332 + if (m_use_xmodmap) {
3333 + m_use_xmodmap = config.get_value("general", "use_xmodmap").get_boolean();
3338 + private string get_output_from_cmdline(string arg, string element) {
3339 + string[] exec_command = {};
3340 + exec_command += m_xkb_command;
3341 + exec_command += arg;
3342 + string standard_output = null;
3343 + string standard_error = null;
3344 + int exit_status = 0;
3345 + string retval = "";
3347 + GLib.Process.spawn_sync(null,
3350 + GLib.SpawnFlags.SEARCH_PATH,
3352 + out standard_output,
3353 + out standard_error,
3355 + } catch (GLib.SpawnError err) {
3356 + stderr.printf("IBUS_ERROR: %s\n", err.message);
3358 + if (exit_status != 0) {
3359 + stderr.printf("IBUS_ERROR: %s\n", standard_error ?? "");
3361 + if (standard_output == null) {
3364 + foreach (string line in standard_output.split("\n")) {
3365 + if (element.length <= line.length &&
3366 + line[0:element.length] == element) {
3367 + retval = line[element.length:line.length];
3373 + private void set_layout_cb(GLib.Pid pid, int status) {
3374 + if (m_xkb_pid != pid) {
3375 + stderr.printf("IBUS_ERROR: set_layout_cb has another pid\n");
3378 + GLib.Process.close_pid(m_xkb_pid);
3383 + private void set_xmodmap_cb(GLib.Pid pid, int status) {
3384 + if (m_xmodmap_pid != pid) {
3385 + stderr.printf("IBUS_ERROR: set_xmodmap_cb has another pid\n");
3388 + GLib.Process.close_pid(m_xmodmap_pid);
3389 + m_xmodmap_pid = -1;
3392 + private string get_fullpath(string command) {
3393 + string envpath = GLib.Environment.get_variable("PATH");
3394 + foreach (string dir in envpath.split(":")) {
3395 + string filepath = GLib.Path.build_filename(dir, command);
3396 + if (GLib.FileUtils.test(filepath, GLib.FileTest.EXISTS)) {
3403 + private string[] get_xkb_group_layout (string layout,
3405 + int layouts_max_length) {
3408 + string[] layouts = m_default_layout.split(",");
3409 + string[] variants = m_default_variant.split(",");
3410 + string group_layouts = "";
3411 + string group_variants = "";
3412 + bool has_variant = false;
3413 + bool include_keymap = false;
3415 + for (i = 0; i < layouts.length; i++) {
3416 + if (i >= layouts_max_length - 1) {
3421 + group_layouts = layouts[i];
3423 + group_layouts = "%s,%s".printf(group_layouts, layouts[i]);
3426 + if (i >= variants.length) {
3428 + group_variants = "";
3430 + group_variants += ",";
3432 + if (layout == layouts[i] && variant == "") {
3433 + include_keymap = true;
3438 + if (layout == layouts[i] && variant == variants[i]) {
3439 + include_keymap = true;
3443 + if (variants[i] != "") {
3444 + has_variant = true;
3448 + group_variants = variants[i];
3450 + group_variants = "%s,%s".printf(group_variants, variants[i]);
3454 + if (variant != "") {
3455 + has_variant = true;
3458 + if (!include_keymap) {
3459 + group_layouts = "%s,%s".printf(group_layouts, layout);
3460 + group_variants = "%s,%s".printf(group_variants, variant);
3464 + if (!has_variant) {
3465 + group_variants = null;
3468 + return {group_layouts, group_variants, group_id.to_string()};
3471 + public string[] get_variant_from_layout(string layout) {
3472 + int left_bracket = layout.index_of("(");
3473 + int right_bracket = layout.index_of(")");
3474 + if (left_bracket >= 0 && right_bracket > left_bracket) {
3475 + return {layout[0:left_bracket] +
3476 + layout[right_bracket + 1:layout.length],
3477 + layout[left_bracket + 1:right_bracket]};
3479 + return {layout, "default"};
3482 + public string[] get_option_from_layout(string layout) {
3483 + int left_bracket = layout.index_of("[");
3484 + int right_bracket = layout.index_of("]");
3485 + if (left_bracket >= 0 && right_bracket > left_bracket) {
3486 + return {layout[0:left_bracket] +
3487 + layout[right_bracket + 1:layout.length],
3488 + layout[left_bracket + 1:right_bracket]};
3490 + return {layout, "default"};
3493 + public string get_layout() {
3494 + if (HAVE_IBUS_XKB) {
3495 + return get_output_from_cmdline("--get", "layout: ");
3497 + return get_output_from_cmdline("-query", "layout: ");
3501 + public string get_variant() {
3502 + if (HAVE_IBUS_XKB) {
3503 + return get_output_from_cmdline("--get", "variant: ");
3505 + return get_output_from_cmdline("-query", "variant: ");
3509 + public string get_option() {
3510 + if (HAVE_IBUS_XKB) {
3511 + return get_output_from_cmdline("--get", "option: ");
3513 + return get_output_from_cmdline("-query", "options: ");
3518 + public string get_group() {
3519 + return get_output_from_cmdline("--get-group", "group: ");
3523 + public int[] set_layout(string _layout="default",
3524 + string _variant="default",
3525 + string _option="default") {
3526 + assert (_layout != null);
3528 + int xkb_group_id = 0;
3529 + int changed_option = 0;
3531 + if (m_xkb_pid != -1) {
3535 + if (_layout == "default" && _variant == "default" &&
3536 + _option == "default") {
3539 + // const gchar to gchar
3540 + string layout = _layout;
3541 + string variant = _variant;
3542 + string option = _option;
3544 + if (variant == "default") {
3545 + string[] array = get_variant_from_layout(layout);
3546 + layout = array[0];
3547 + variant = array[1];
3550 + if (option == "default") {
3551 + string[] array = get_option_from_layout(layout);
3552 + layout = array[0];
3553 + option = array[1];
3556 + bool need_us_layout = false;
3557 + foreach (string latin_layout in m_xkb_latin_layouts) {
3558 + if (layout == latin_layout && variant != "eng") {
3559 + need_us_layout = true;
3562 + if (variant != null &&
3563 + "%s(%s)".printf(layout, variant) == latin_layout) {
3564 + need_us_layout = true;
3569 + int layouts_max_length = XKB_LAYOUTS_MAX_LENGTH;
3570 + if (need_us_layout) {
3571 + layouts_max_length--;
3574 + if (m_default_layout == "") {
3575 + m_default_layout = get_layout();
3577 + if (m_default_variant == "") {
3578 + m_default_variant = get_variant();
3580 + if (m_default_option == "") {
3581 + m_default_option = get_option();
3584 + if (layout == "default") {
3585 + layout = m_default_layout;
3586 + variant = m_default_variant;
3588 + if (HAVE_IBUS_GKBD) {
3589 + if (variant == "default") {
3592 + string[] retval = get_xkb_group_layout (layout, variant,
3593 + layouts_max_length);
3594 + layout = retval[0];
3595 + variant = retval[1];
3596 + xkb_group_id = int.parse(retval[2]);
3600 + if (layout == "") {
3601 + warning("Could not get the correct layout");
3605 + if (variant == "default" || variant == "") {
3609 + if (option == "default" || option == "") {
3610 + option = m_default_option;
3612 + if (!(option in m_default_option.split(","))) {
3613 + option = "%s,%s".printf(m_default_option, option);
3614 + changed_option = 1;
3616 + option = m_default_option;
3620 + if (option == "") {
3624 + if (need_us_layout) {
3626 + if (variant != null) {
3631 + string[] args = {};
3632 + args += m_xkb_command;
3633 + if (HAVE_IBUS_XKB) {
3634 + args += "--layout";
3636 + if (variant != null) {
3637 + args += "--variant";
3640 + if (option != null) {
3641 + args += "--option";
3646 + if (variant != null) {
3649 + if (option != null) {
3654 + GLib.Pid child_pid;
3656 + GLib.Process.spawn_async(null,
3659 + GLib.SpawnFlags.DO_NOT_REAP_CHILD |
3660 + GLib.SpawnFlags.SEARCH_PATH,
3663 + } catch (GLib.SpawnError err) {
3664 + stderr.printf("IBUS_ERROR: %s\n", err.message);
3667 + m_xkb_pid = child_pid;
3668 + GLib.ChildWatch.add(m_xkb_pid, set_layout_cb);
3670 + return {xkb_group_id, changed_option};
3673 + public void set_xmodmap() {
3674 + if (!m_use_xmodmap) {
3678 + if (m_xmodmap_pid != -1) {
3682 + string xmodmap_cmdpath = get_fullpath(m_xmodmap_command);
3683 + if (xmodmap_cmdpath == "") {
3684 + xmodmap_cmdpath = m_xmodmap_command;
3686 + string homedir = GLib.Environment.get_home_dir();
3687 + foreach (string xmodmap_file in m_xmodmap_known_files) {
3688 + string xmodmap_filepath = GLib.Path.build_filename(homedir, xmodmap_file);
3689 + if (!GLib.FileUtils.test(xmodmap_filepath, GLib.FileTest.EXISTS)) {
3692 + string[] args = {xmodmap_cmdpath, xmodmap_filepath};
3694 + GLib.Pid child_pid;
3696 + GLib.Process.spawn_async(null,
3699 + GLib.SpawnFlags.DO_NOT_REAP_CHILD |
3700 + GLib.SpawnFlags.SEARCH_PATH,
3703 + } catch (GLib.SpawnError err) {
3704 + stderr.printf("IBUS_ERROR: %s\n", err.message);
3707 + m_xmodmap_pid = child_pid;
3708 + GLib.ChildWatch.add(m_xmodmap_pid, set_xmodmap_cb);
3714 + public void reset_layout() {
3715 + m_default_layout = get_layout();
3716 + m_default_variant = get_variant();
3717 + m_default_option = get_option();
3721 + public static int main(string[] args) {
3722 + IBus.Bus bus = new IBus.Bus();
3723 + IBus.Config config = bus.get_config();
3724 + XKBLayout xkblayout = new XKBLayout(config);
3725 + stdout.printf ("layout: %s\n", xkblayout.get_layout());
3726 + stdout.printf ("variant: %s\n", xkblayout.get_variant());
3727 + stdout.printf ("option: %s\n", xkblayout.get_option());
3728 + xkblayout.set_layout("jp");
3729 + if (config != null) {
3732 + Gtk.init (ref args);