286
273
m_keybindings = null;
277
* panel_get_engines_from_xkb:
278
* @self: #Panel class
279
* @engines: all engines from ibus_bus_list_engines()
280
* @returns: ibus xkb engines
282
* Made ibus engines from the current XKB keymaps.
283
* This returns only XKB engines whose name start with "xkb:".
285
private GLib.List<IBus.EngineDesc>
286
get_engines_from_xkb(GLib.List<IBus.EngineDesc> engines) {
290
XKBLayout.get_layout(out layouts, out variants, out option);
292
GLib.List<IBus.EngineDesc> xkb_engines =
293
new GLib.List<IBus.EngineDesc>();
294
IBus.EngineDesc us_engine =
295
new IBus.EngineDesc("xkb:us::eng",
296
"", "", "", "", "", "", "");
297
string[] layout_array = layouts.split(",");
298
string[] variant_array = variants.split(",");
300
for (int i = 0; i < layout_array.length; i++) {
301
string layout = layout_array[i];
302
string variant = null;
303
IBus.EngineDesc current_engine = null;
305
if (i < variant_array.length)
306
variant = variant_array[i];
308
/* If variants == "", variants.split(",") is { null }.
309
* To meet engine.get_layout_variant(), convert null to ""
315
foreach (unowned IBus.EngineDesc engine in engines) {
317
string name = engine.get_name();
318
if (!name.has_prefix("xkb:"))
321
if (engine.get_layout() == layout &&
322
engine.get_layout_variant() == variant) {
323
current_engine = engine;
328
if (current_engine != null) {
329
xkb_engines.append(current_engine);
330
} else if (xkb_engines.find(us_engine) == null) {
331
warning("Fallback %s(%s) to us layout.", layout, variant);
332
xkb_engines.append(us_engine);
336
if (xkb_engines.length() == 0)
337
warning("Not found IBus XKB engines from the session.");
343
* panel_get_engines_from_locale:
344
* @self: #Panel class
345
* @engines: all engines from ibus_bus_list_engines()
346
* @returns: ibus im engines
348
* Made ibus engines from the current locale and IBus.EngineDesc.lang .
349
* This returns non-XKB engines whose name does not start "xkb:".
351
private GLib.List<IBus.EngineDesc>
352
get_engines_from_locale(GLib.List<IBus.EngineDesc> engines) {
353
string locale = Intl.setlocale(LocaleCategory.CTYPE, null);
358
string lang = locale.split(".")[0];
359
GLib.List<IBus.EngineDesc> im_engines =
360
new GLib.List<IBus.EngineDesc>();
362
foreach (unowned IBus.EngineDesc engine in engines) {
363
string name = engine.get_name();
365
if (name.has_prefix("xkb:"))
368
if (engine.get_language() == lang &&
369
engine.get_rank() > 0)
370
im_engines.append(engine);
373
if (im_engines.length() == 0) {
374
lang = lang.split("_")[0];
376
foreach (unowned IBus.EngineDesc engine in engines) {
377
string name = engine.get_name();
379
if (name.has_prefix("xkb:"))
382
if (engine.get_language() == lang &&
383
engine.get_rank() > 0)
384
im_engines.append(engine);
388
if (im_engines.length() == 0)
391
im_engines.sort((a, b) => {
392
return (int) b.get_rank() - (int) a.get_rank();
398
private void init_engines_order() {
399
m_xkblayout.set_latin_layouts(
400
m_settings_general.get_strv("xkb-latin-layouts"));
402
if (inited_engines_order)
405
if (m_settings_general.get_strv("preload-engines").length > 0)
408
GLib.List<IBus.EngineDesc> engines = m_bus.list_engines();
409
GLib.List<IBus.EngineDesc> xkb_engines = get_engines_from_xkb(engines);
410
GLib.List<IBus.EngineDesc> im_engines =
411
get_engines_from_locale(engines);
414
foreach (unowned IBus.EngineDesc engine in xkb_engines)
415
names += engine.get_name();
416
foreach (unowned IBus.EngineDesc engine in im_engines)
417
names += engine.get_name();
419
m_settings_general.set_strv("preload-engines", names);
289
422
private void set_custom_font() {
290
423
Gdk.Display display = Gdk.Display.get_default();
291
424
Gdk.Screen screen = (display != null) ?
524
672
set_timeout_property_panel();
525
673
set_follow_input_cursor_when_always_shown_property_panel();
526
674
set_xkb_icon_rgba();
531
private void gkbdlayout_changed_cb() {
532
/* The callback is called four times after set_layout is called
533
* so check the elapsed and take the first signal only. */
534
double elapsed = m_changed_layout_timer.elapsed();
535
if (elapsed < 1.0 && elapsed > 0.0) {
539
if (m_fallback_lock_id != -1) {
540
/* Call lock_group only when set_layout is called. */
541
m_gkbdlayout.lock_group(m_fallback_lock_id);
542
m_fallback_lock_id = -1;
544
/* Reset default layout when gnome-control-center is called. */
545
m_xkblayout.reset_layout();
548
update_xkb_engines();
549
m_changed_layout_timer.reset();
552
private void init_gkbd() {
553
m_gkbdlayout = new GkbdLayout();
554
m_gkbdlayout.changed.connect(gkbdlayout_changed_cb);
556
/* Probably we cannot support both keyboard and ibus indicators
557
* How can I get the engine from keymap of group_id?
558
* e.g. 'en' could be owned by xkb:en and pinyin engines. */
559
//m_gkbdlayout.group_changed.connect((object) => {});
561
m_changed_layout_timer = new GLib.Timer();
562
m_changed_layout_timer.start();
563
m_gkbdlayout.start_listen();
566
private void init_engines_order() {
567
m_xkblayout = new XKBLayout();
568
string session = Environment.get_variable("DESKTOP_SESSION");
570
if (HAVE_IBUS_GKBD &&
571
session != null && session.length >= 5 &&
572
session[0:5] == "gnome") {
576
string[] preload_engines =
577
m_settings_general.get_strv("preload-engines");
579
bool preload_engines_inited =
580
m_settings_general.get_boolean("preload-engines-inited");
582
// Set preload_engines_inited = true for back compatibility
583
if (preload_engines.length != 0 && !preload_engines_inited) {
584
preload_engines_inited = true;
585
m_settings_general.set_boolean("preload-engines-inited", true);
588
update_xkb_engines();
590
// Before update preload_engine_mode, update_xkb_engines() is called
591
// because "preload-engine-mode" signal calls update_im_engines().
592
if (!preload_engines_inited)
593
m_settings_general.set_int("preload-engine-mode",
594
IBus.PreloadEngineMode.LANG_RELATIVE);
598
if (!preload_engines_inited)
599
m_settings_general.set_boolean("preload-engines-inited", true);
602
private bool set_lang_relative_preload_engines() {
603
string locale = Intl.setlocale(LocaleCategory.CTYPE, null);
608
string lang = locale.split(".")[0];
609
GLib.List<IBus.EngineDesc> engines = m_bus.list_engines();
610
string[] im_engines = {};
612
for (unowned GLib.List<IBus.EngineDesc> p = engines;
615
unowned IBus.EngineDesc engine = p.data;
616
if (engine.get_language() == lang && engine.get_rank() > 0)
617
im_engines += engine.get_name();
620
lang = lang.split("_")[0];
621
if (im_engines.length == 0) {
622
for (unowned GLib.List<IBus.EngineDesc> p = engines;
625
unowned IBus.EngineDesc engine = p.data;
626
if (engine.get_language() == lang && engine.get_rank() > 0)
627
im_engines += engine.get_name();
631
if (im_engines.length == 0)
634
string[] orig_preload_engines =
635
m_settings_general.get_strv("preload-engines");
636
string[] preload_engines = {};
638
// clear input method engines
639
foreach (string name in orig_preload_engines) {
640
if (name.ascii_ncasecmp("xkb:", 4) != 0)
643
preload_engines += name;
646
foreach (string name in im_engines) {
647
if (!(name in preload_engines))
648
preload_engines += name;
651
if (string.joinv(",", orig_preload_engines) !=
652
string.joinv(",", preload_engines))
653
m_settings_general.set_strv("preload-engines", preload_engines);
658
private void update_im_engines() {
659
int preload_engine_mode =
660
m_settings_general.get_int("preload-engine-mode");
662
if (preload_engine_mode == IBus.PreloadEngineMode.USER)
665
set_lang_relative_preload_engines();
668
private void update_xkb_engines() {
669
string var_layout = m_xkblayout.get_layout();
670
string var_variant = m_xkblayout.get_variant();
671
if (var_layout == "") {
675
m_layouts = var_layout.split(",");
676
m_variants = var_variant.split(",");
678
IBus.XKBConfigRegistry registry = new IBus.XKBConfigRegistry();
679
string[] var_xkb_engine_names = {};
680
for (int i = 0; i < m_layouts.length; i++) {
681
string name = m_layouts[i];
684
if (i < m_variants.length && m_variants[i] != "") {
685
name = "%s:%s".printf(name, m_variants[i]);
686
string layout = "%s(%s)".printf(name, m_variants[i]);
687
GLib.List<string> langs =
688
registry.layout_lang_get_langs(layout);
689
if (langs.length() != 0) {
693
name = "%s:".printf(name);
697
GLib.List<string> langs =
698
registry.layout_lang_get_langs(m_layouts[i]);
699
if (langs.length() != 0) {
704
var_xkb_engine_names += "%s:%s:%s".printf("xkb", name, lang);
707
string[] engine_names =
708
m_settings_general.get_strv("preload-engines");
709
bool updated_engine_names = false;
711
foreach (string name in var_xkb_engine_names) {
712
if (name in engine_names)
714
updated_engine_names = true;
715
engine_names += name;
718
if (updated_engine_names)
719
m_settings_general.set_strv("preload-engines", engine_names);
721
string[] order_names =
722
m_settings_general.get_strv("engines-order");
723
bool updated_order_names = false;
725
foreach (var name in var_xkb_engine_names) {
726
if (name in order_names)
729
updated_order_names = true;
732
if (updated_order_names)
733
m_settings_general.set_strv("engines-order", order_names);
736
private void set_xkb_group_layout(IBus.EngineDesc engine) {
737
int[] retval = m_xkblayout.set_layout(engine, true);
738
if (retval[0] >= 0) {
739
/* If an XKB keymap is added into the XKB group,
740
* this._gkbdlayout.lock_group will be called after
741
* 'group-changed' signal is received. */
742
m_fallback_lock_id = retval[0];
743
m_changed_xkb_option = (retval[1] != 0) ? true : false;
747
private bool set_gkbd_layout(IBus.EngineDesc engine) {
748
string layout = engine.get_layout();
749
string variant = engine.get_layout_variant();
751
/* If a previous ibus engine changed XKB options, need to set the
752
* default XKB option. */
753
if (m_changed_xkb_option == true) {
754
m_changed_xkb_option = false;
758
if (variant != "" && variant != "default") {
759
layout = "%s(%s)".printf(layout, variant);
762
int gkbd_len = m_gkbdlayout.get_group_names().length;
763
for (int i = 0; i < m_layouts.length && i < gkbd_len; i++) {
764
string sys_layout = m_layouts[i];
765
if (i < m_variants.length && m_variants[i] != "") {
766
sys_layout = "%s(%s)".printf(sys_layout, m_variants[i]);
768
if (sys_layout == layout) {
769
m_gkbdlayout.lock_group(i);
776
private void set_layout(IBus.EngineDesc engine) {
777
string layout = engine.get_layout();
779
if (layout == "" || layout == null) {
783
if (m_xkblayout == null) {
784
init_engines_order();
787
if (HAVE_IBUS_GKBD && m_gkbdlayout != null) {
788
if (set_gkbd_layout(engine)) {
791
set_xkb_group_layout(engine);
795
m_xkblayout.set_layout(engine);
798
private void exec_setxkbmap(IBus.EngineDesc engine) {
799
string layout = engine.get_layout();
800
string variant = engine.get_layout_variant();
801
string option = engine.get_layout_option();
802
string standard_error = null;
804
string[] args = { "setxkbmap" };
806
if (layout != null && layout != "" && layout != "default") {
810
if (variant != null && variant != "" && variant != "default") {
814
if (option != null && option != "" && option != "default") {
815
/*TODO: Need to get the session XKB options */
821
if (args.length == 1) {
826
if (!GLib.Process.spawn_sync(null, args, null,
827
GLib.SpawnFlags.SEARCH_PATH,
831
warning("Switch xkb layout to %s failed.",
832
engine.get_layout());
834
} catch (GLib.SpawnError e) {
835
warning("Execute setxkbmap failed: %s", e.message);
838
if (exit_status != 0) {
839
warning("Execute setxkbmap failed: %s", standard_error ?? "(null)");
843
677
private void engine_contexts_insert(IBus.EngineDesc engine) {