~ubuntu-branches/ubuntu/wily/ibus/wily-proposed

« back to all changes in this revision

Viewing changes to ui/gtk3/panel.vala

  • Committer: Package Import Robot
  • Author(s): Osamu Aoki
  • Date: 2013-10-15 22:01:21 UTC
  • mfrom: (1.5.3)
  • Revision ID: package-import@ubuntu.com-20131015220121-f5lga4jvbxplinjx
Tags: 1.5.4-1
* New upstream release.
* Depend on gir1.2-gtk-3.0 (>=3.8.5). Closes: #723031, #725134, #726467
* wrap-and-sort.
* Sync upstream with ibus-HEAD.patch which fixes candidate orientation
  bug.  Closes: #725024

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 *
3
3
 * ibus - The Input Bus
4
4
 *
5
 
 * Copyright(c) 2011 Peng Huang <shawn.p.huang@gmail.com>
 
5
 * Copyright(c) 2011-2013 Peng Huang <shawn.p.huang@gmail.com>
6
6
 *
7
7
 * This library is free software; you can redistribute it and/or
8
8
 * modify it under the terms of the GNU Lesser General Public
9
9
 * License as published by the Free Software Foundation; either
10
 
 * version 2 of the License, or(at your option) any later version.
 
10
 * version 2.1 of the License, or (at your option) any later version.
11
11
 *
12
12
 * This library is distributed in the hope that it will be useful,
13
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
 
 * GNU Lesser General Public License for more details.
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
16
16
 *
17
17
 * You should have received a copy of the GNU Lesser General Public
18
 
 * License along with this program; if not, write to the
19
 
 * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
20
 
 * Boston, MA  02111-1307  USA
 
18
 * License along with this library; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301
 
20
 * USA
21
21
 */
22
22
 
23
23
class Panel : IBus.PanelService {
36
36
    }
37
37
 
38
38
    private IBus.Bus m_bus;
39
 
    private IBus.Config m_config;
 
39
    private GLib.Settings m_settings_general = null;
 
40
    private GLib.Settings m_settings_hotkey = null;
 
41
    private GLib.Settings m_settings_panel = null;
40
42
    private Gtk.StatusIcon m_status_icon;
41
43
    private Gtk.Menu m_ime_menu;
42
44
    private Gtk.Menu m_sys_menu;
43
45
    private IBus.EngineDesc[] m_engines = {};
 
46
    private GLib.HashTable<string, IBus.EngineDesc> m_engine_contexts =
 
47
            new GLib.HashTable<string, IBus.EngineDesc>(GLib.str_hash,
 
48
                                                        GLib.str_equal);
 
49
    private string m_current_context_path = "";
 
50
    private bool m_use_global_engine = true;
44
51
    private CandidatePanel m_candidate_panel;
45
52
    private Switcher m_switcher;
 
53
    private bool m_switcher_is_running = false;
46
54
    private PropertyManager m_property_manager;
47
55
    private GLib.Pid m_setup_pid = 0;
48
56
    private Gtk.AboutDialog m_about_dialog;
56
64
    private int m_fallback_lock_id = -1;
57
65
    private bool m_changed_xkb_option = false;
58
66
    private GLib.Timer m_changed_layout_timer;
59
 
    private const string ACCELERATOR_SWITCH_IME_FOREWARD = "<Super>space";
60
67
 
61
68
    private GLib.List<Keybinding> m_keybindings = new GLib.List<Keybinding>();
62
69
 
68
75
 
69
76
        m_bus = bus;
70
77
 
 
78
        init_settings();
 
79
 
71
80
        // init ui
72
81
        m_status_icon = new Gtk.StatusIcon();
73
82
        m_status_icon.set_name("ibus-ui-gtk");
79
88
        m_candidate_panel = new CandidatePanel();
80
89
        m_candidate_panel.page_up.connect((w) => this.page_up());
81
90
        m_candidate_panel.page_down.connect((w) => this.page_down());
 
91
        m_candidate_panel.candidate_clicked.connect(
 
92
                (w, i, b, s) => this.candidate_clicked(i, b, s));
82
93
 
83
94
        m_switcher = new Switcher();
84
95
        // The initial shortcut is "<Super>space"
85
 
        bind_switch_shortcut(null);
 
96
        bind_switch_shortcut();
86
97
 
87
98
        if (m_switcher_delay_time >= 0) {
88
99
            m_switcher.set_popup_delay_time((uint) m_switcher_delay_time);
108
119
        m_xkblayout = null;
109
120
    }
110
121
 
 
122
    private void init_settings() {
 
123
        m_settings_general = new GLib.Settings("org.freedesktop.ibus.general");
 
124
        m_settings_hotkey =
 
125
                new GLib.Settings("org.freedesktop.ibus.general.hotkey");
 
126
        m_settings_panel = new GLib.Settings("org.freedesktop.ibus.panel");
 
127
 
 
128
        m_settings_general.changed["preload-engines"].connect((key) => {
 
129
                update_engines(m_settings_general.get_strv(key),
 
130
                               null);
 
131
        });
 
132
 
 
133
        m_settings_general.changed["preload-engine-mode"].connect((key) => {
 
134
                update_im_engines();
 
135
        });
 
136
 
 
137
        m_settings_general.changed["switcher-delay-time"].connect((key) => {
 
138
                set_switcher_delay_time();
 
139
        });
 
140
 
 
141
        m_settings_general.changed["use-system-keyboard-layout"].connect(
 
142
            (key) => {
 
143
                set_use_system_keyboard_layout();
 
144
        });
 
145
 
 
146
        m_settings_general.changed["embed-preedit-text"].connect((key) => {
 
147
                set_embed_preedit_text();
 
148
        });
 
149
 
 
150
        m_settings_general.changed["use-global-engine"].connect((key) => {
 
151
                set_use_global_engine();
 
152
        });
 
153
 
 
154
        m_settings_hotkey.changed["triggers"].connect((key) => {
 
155
                unbind_switch_shortcut();
 
156
                bind_switch_shortcut();
 
157
        });
 
158
 
 
159
        m_settings_panel.changed["custom-font"].connect((key) => {
 
160
                set_custom_font();
 
161
        });
 
162
 
 
163
        m_settings_panel.changed["use-custom-font"].connect((key) => {
 
164
                set_custom_font();
 
165
        });
 
166
 
 
167
        m_settings_panel.changed["show-icon-on-systray"].connect((key) => {
 
168
                set_show_icon_on_systray();
 
169
        });
 
170
 
 
171
        m_settings_panel.changed["lookup-table-orientation"].connect((key) => {
 
172
                set_lookup_table_orientation();
 
173
        });
 
174
    }
 
175
 
111
176
    private void keybinding_manager_bind(KeybindingManager keybinding_manager,
112
177
                                         string?           accelerator) {
113
178
        uint switch_keysym = 0;
167
232
                (e) => handle_engine_switch(e, true));
168
233
    }
169
234
 
170
 
    private void bind_switch_shortcut(Variant? variant) {
171
 
        string[] accelerators = {};
172
 
        Variant var_trigger = variant;
173
 
 
174
 
        if (var_trigger == null && m_config != null) {
175
 
            var_trigger = m_config.get_value("general/hotkey",
176
 
                                             "triggers");
177
 
        }
178
 
 
179
 
        if (var_trigger != null) {
180
 
            accelerators = var_trigger.dup_strv();
181
 
        } else {
182
 
            accelerators += ACCELERATOR_SWITCH_IME_FOREWARD;
183
 
        }
 
235
    private void bind_switch_shortcut() {
 
236
        string[] accelerators = m_settings_hotkey.get_strv("triggers");
184
237
 
185
238
        var keybinding_manager = KeybindingManager.get_instance();
186
239
 
215
268
            return;
216
269
        }
217
270
 
218
 
        bool use_custom_font = false;
219
 
        GLib.Variant var_use_custom_font = m_config.get_value("panel",
220
 
                                                              "use_custom_font");
221
 
 
222
 
        if (var_use_custom_font != null) {
223
 
            use_custom_font = var_use_custom_font.get_boolean();
224
 
        }
 
271
        bool use_custom_font = m_settings_panel.get_boolean("use-custom-font");
225
272
 
226
273
        if (m_css_provider != null) {
227
274
            Gtk.StyleContext.remove_provider_for_screen(screen,
233
280
            return;
234
281
        }
235
282
 
236
 
        string font_name = null;
237
 
        GLib.Variant var_custom_font = m_config.get_value("panel",
238
 
                                                          "custom_font");
239
 
        if (var_custom_font != null) {
240
 
            font_name = var_custom_font.dup_string();
241
 
        }
 
283
        string font_name = m_settings_panel.get_string("custom-font");
242
284
 
243
285
        if (font_name == null) {
244
 
            warning("No config panel:custom_font.");
 
286
            warning("No config panel:custom-font.");
245
287
            return;
246
288
        }
247
289
 
262
304
                                                 Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION);
263
305
    }
264
306
 
265
 
    private void set_switcher_delay_time(Variant? variant) {
266
 
        Variant var_switcher_delay_time = variant;
267
 
 
268
 
        if (var_switcher_delay_time == null) {
269
 
            var_switcher_delay_time = m_config.get_value("general",
270
 
                                                         "switcher-delay-time");
271
 
        }
272
 
 
273
 
        if (var_switcher_delay_time == null) {
274
 
            return;
275
 
        }
276
 
 
277
 
        m_switcher_delay_time = var_switcher_delay_time.get_int32();
278
 
 
279
 
        if (m_switcher_delay_time >= 0) {
 
307
    private void set_switcher_delay_time() {
 
308
        m_switcher_delay_time =
 
309
                m_settings_general.get_int("switcher-delay-time");
 
310
 
 
311
        if (m_switcher != null && m_switcher_delay_time >= 0) {
280
312
            m_switcher.set_popup_delay_time((uint) m_switcher_delay_time);
281
313
        }
282
314
    }
283
315
 
284
 
    private void set_use_system_keyboard_layout(Variant? variant) {
285
 
        Variant var_use_system_kbd_layout = variant;
286
 
 
287
 
        if (var_use_system_kbd_layout == null) {
288
 
            var_use_system_kbd_layout = m_config.get_value(
289
 
                    "general",
290
 
                    "use_system_keyboard_layout");
291
 
        }
292
 
 
293
 
        if (var_use_system_kbd_layout == null) {
294
 
            return;
295
 
        }
296
 
 
297
 
        m_use_system_keyboard_layout = var_use_system_kbd_layout.get_boolean();
298
 
    }
299
 
 
300
 
    private void set_embed_preedit_text(Variant? variant) {
301
 
        Variant var_embed_preedit = variant;
302
 
 
303
 
        if (var_embed_preedit == null) {
304
 
            var_embed_preedit = m_config.get_value("general",
305
 
                                                   "embed_preedit_text");
306
 
        }
307
 
 
308
 
        if (var_embed_preedit == null) {
309
 
            return;
310
 
        }
311
 
 
312
 
        m_bus.set_ibus_property("EmbedPreeditText",
313
 
                                var_embed_preedit);
 
316
    private void set_use_system_keyboard_layout() {
 
317
        m_use_system_keyboard_layout =
 
318
                m_settings_general.get_boolean("use-system-keyboard-layout");
 
319
    }
 
320
 
 
321
    private void set_embed_preedit_text() {
 
322
        Variant variant =
 
323
                    m_settings_general.get_value("embed-preedit-text");
 
324
 
 
325
        if (variant == null) {
 
326
            return;
 
327
        }
 
328
 
 
329
        m_bus.set_ibus_property("EmbedPreeditText", variant);
 
330
    }
 
331
 
 
332
    private void set_use_global_engine() {
 
333
        m_use_global_engine =
 
334
                m_settings_general.get_boolean("use-global-engine");
 
335
    }
 
336
 
 
337
    private void set_show_icon_on_systray() {
 
338
        if (m_status_icon == null)
 
339
            return;
 
340
 
 
341
        m_status_icon.set_visible(
 
342
                m_settings_panel.get_boolean("show-icon-on-systray"));
 
343
    }
 
344
 
 
345
    private void set_lookup_table_orientation() {
 
346
        if (m_candidate_panel == null)
 
347
            return;
 
348
 
 
349
        m_candidate_panel.set_vertical(
 
350
                m_settings_panel.get_int("lookup-table-orientation")
 
351
                == IBus.Orientation.VERTICAL);
314
352
    }
315
353
 
316
354
    private int compare_versions(string version1, string version2) {
377
415
    }
378
416
 
379
417
    private void set_version() {
380
 
        Variant var_prev_version = m_config.get_value("general", "version");
381
 
        Variant var_current_version = null;
382
 
        string prev_version = "".dup();
 
418
        string prev_version = m_settings_general.get_string("version");
383
419
        string current_version = null;
384
420
 
385
 
        if (var_prev_version != null) {
386
 
            prev_version = var_prev_version.dup_string();
387
 
        }
388
 
 
389
421
        if (compare_versions(prev_version, "1.5.3") < 0) {
390
422
            update_version_1_5_3();
391
423
        }
398
430
            return;
399
431
        }
400
432
 
401
 
        var_current_version = new Variant.string(current_version);
402
 
        m_config.set_value("general", "version", var_current_version);
 
433
        m_settings_general.set_string("version", current_version);
403
434
    }
404
435
 
405
 
    public void set_config(IBus.Config config) {
406
 
        if (m_config != null) {
407
 
            m_config.value_changed.disconnect(config_value_changed_cb);
408
 
            m_config.watch(null, null);
409
 
            m_config = null;
410
 
        }
411
 
 
412
 
        m_config = config;
413
 
        if (m_config != null) {
414
 
            m_config.value_changed.connect(config_value_changed_cb);
415
 
            m_config.watch("general", "preload_engines");
416
 
            m_config.watch("general", "embed_preedit_text");
417
 
            m_config.watch("general", "preload_engines_inited");
418
 
            m_config.watch("general", "preload_engine_mode");
419
 
            m_config.watch("general", "engines_order");
420
 
            m_config.watch("general", "switcher_delay_time");
421
 
            m_config.watch("general", "use_system_keyboard_layout");
422
 
            m_config.watch("general/hotkey", "triggers");
423
 
            m_config.watch("panel", "custom_font");
424
 
            m_config.watch("panel", "use_custom_font");
425
 
            init_engines_order();
426
 
            // Update m_use_system_keyboard_layout before update_engines()
427
 
            // is called.
428
 
            set_use_system_keyboard_layout(null);
429
 
            update_engines(m_config.get_value("general", "preload_engines"),
430
 
                           m_config.get_value("general", "engines_order"));
431
 
            unbind_switch_shortcut();
432
 
            bind_switch_shortcut(null);
433
 
            set_switcher_delay_time(null);
434
 
            set_embed_preedit_text(null);
435
 
            set_custom_font();
436
 
 
437
 
            set_version();
438
 
        } else {
439
 
            update_engines(null, null);
440
 
        }
 
436
    public void load_settings() {
 
437
        init_engines_order();
 
438
        // Update m_use_system_keyboard_layout before update_engines()
 
439
        // is called.
 
440
        set_use_system_keyboard_layout();
 
441
        set_use_global_engine();
 
442
        update_engines(m_settings_general.get_strv("preload-engines"),
 
443
                       m_settings_general.get_strv("engines-order"));
 
444
        unbind_switch_shortcut();
 
445
        bind_switch_shortcut();
 
446
        set_switcher_delay_time();
 
447
        set_embed_preedit_text();
 
448
        set_custom_font();
 
449
        set_show_icon_on_systray();
 
450
        set_lookup_table_orientation();
 
451
 
 
452
        set_version();
441
453
    }
442
454
 
443
455
    private void gkbdlayout_changed_cb() {
476
488
    }
477
489
 
478
490
    private void init_engines_order() {
479
 
        if (m_config == null) {
480
 
            return;
481
 
        }
482
 
 
483
 
        m_xkblayout = new XKBLayout(m_config);
 
491
        m_xkblayout = new XKBLayout();
484
492
        string session = Environment.get_variable("DESKTOP_SESSION");
485
493
 
486
494
        if (HAVE_IBUS_GKBD &&
489
497
            init_gkbd();
490
498
        }
491
499
 
492
 
        GLib.Variant var_engines = 
493
 
                m_config.get_value("general", "preload_engines");
494
 
        string[] preload_engines = {};
495
 
 
496
 
        if (var_engines != null) {
497
 
            preload_engines = var_engines.dup_strv();
498
 
        }
499
 
 
500
 
        bool preload_engines_inited = false;
501
 
        GLib.Variant var_preload_engines_inited =
502
 
                m_config.get_value("general", "preload_engines_inited");
503
 
 
504
 
        if (var_preload_engines_inited != null) {
505
 
            preload_engines_inited = var_preload_engines_inited.get_boolean();
506
 
        }
 
500
        string[] preload_engines =
 
501
                m_settings_general.get_strv("preload-engines");
 
502
 
 
503
        bool preload_engines_inited =
 
504
                m_settings_general.get_boolean("preload-engines-inited");
507
505
 
508
506
        // Set preload_engines_inited = true for back compatibility
509
507
        if (preload_engines.length != 0 && !preload_engines_inited) {
510
508
                preload_engines_inited = true;
511
 
                m_config.set_value("general",
512
 
                                   "preload_engines_inited",
513
 
                                   new GLib.Variant.boolean(true));
 
509
                m_settings_general.set_boolean("preload-engines-inited", true);
514
510
        }
515
511
 
516
512
        update_xkb_engines();
517
513
 
518
514
        // Before update preload_engine_mode, update_xkb_engines() is called
519
 
        // because config_value_changed_cb() calls update_im_engines().
520
 
        if (!preload_engines_inited) {
521
 
            GLib.Variant variant = new GLib.Variant.int32(
522
 
                    IBus.PreloadEngineMode.LANG_RELATIVE);
523
 
            m_config.set_value("general",
524
 
                               "preload_engine_mode",
525
 
                               variant);
526
 
        }
 
515
        // because "preload-engine-mode" signal calls update_im_engines().
 
516
        if (!preload_engines_inited)
 
517
            m_settings_general.set_int("preload-engine-mode",
 
518
                                       IBus.PreloadEngineMode.LANG_RELATIVE);
527
519
 
528
520
        update_im_engines();
529
521
 
530
 
        if (!preload_engines_inited) {
531
 
            m_config.set_value("general",
532
 
                               "preload_engines_inited",
533
 
                               new GLib.Variant.boolean(true));
534
 
        }
 
522
        if (!preload_engines_inited)
 
523
            m_settings_general.set_boolean("preload-engines-inited", true);
535
524
    }
536
525
 
537
526
    private bool set_lang_relative_preload_engines() {
538
527
        string locale = Intl.setlocale(LocaleCategory.CTYPE, null);
539
528
 
540
 
        if (locale == null) {
 
529
        if (locale == null)
541
530
            locale = "C";
542
 
        }
543
531
 
544
532
        string lang = locale.split(".")[0];
545
533
        GLib.List<IBus.EngineDesc> engines = m_bus.list_engines();
549
537
             p != null;
550
538
             p = p.next) {
551
539
            unowned IBus.EngineDesc engine = p.data;
552
 
            if (engine.get_language() == lang &&
553
 
                engine.get_rank() > 0) {
 
540
            if (engine.get_language() == lang && engine.get_rank() > 0)
554
541
                im_engines += engine.get_name();
555
 
            }
556
542
        }
557
543
 
558
544
        lang = lang.split("_")[0];
561
547
                 p != null;
562
548
                 p = p.next) {
563
549
                unowned IBus.EngineDesc engine = p.data;
564
 
                if (engine.get_language() == lang &&
565
 
                    engine.get_rank() > 0) {
 
550
                if (engine.get_language() == lang && engine.get_rank() > 0)
566
551
                    im_engines += engine.get_name();
567
 
                }
568
552
            }
569
553
        }
570
554
 
571
 
        if (im_engines.length == 0) {
 
555
        if (im_engines.length == 0)
572
556
            return false;
573
 
        }
574
557
 
575
 
        GLib.Variant var_engines = 
576
 
                m_config.get_value("general", "preload_engines");
577
 
        string[] orig_preload_engines = {};
 
558
        string[] orig_preload_engines =
 
559
                m_settings_general.get_strv("preload-engines");
578
560
        string[] preload_engines = {};
579
561
 
580
 
        if (var_engines != null) {
581
 
            orig_preload_engines = var_engines.dup_strv();
582
 
        }
583
 
 
584
562
        // clear input method engines
585
563
        foreach (string name in orig_preload_engines) {
586
 
            if (name.ascii_ncasecmp("xkb:", 4) != 0) {
 
564
            if (name.ascii_ncasecmp("xkb:", 4) != 0)
587
565
                continue;
588
 
            }
 
566
 
589
567
            preload_engines += name;
590
568
        }
591
569
 
592
570
        foreach (string name in im_engines) {
593
 
            if (!(name in preload_engines)) {
 
571
            if (!(name in preload_engines))
594
572
                preload_engines += name;
595
 
            }
596
573
        }
597
574
 
598
575
        if ("".joinv(",", orig_preload_engines) !=
599
 
            "".joinv(",", preload_engines)) {
600
 
            m_config.set_value("general",
601
 
                               "preload_engines",
602
 
                               new GLib.Variant.strv(preload_engines));
603
 
        }
 
576
            "".joinv(",", preload_engines))
 
577
            m_settings_general.set_strv("preload-engines", preload_engines);
604
578
 
605
579
        return true;
606
580
    }
607
581
 
608
582
    private void update_im_engines() {
609
 
        int preload_engine_mode = IBus.PreloadEngineMode.USER;
610
 
        GLib.Variant var_preload_engine_mode =
611
 
                m_config.get_value("general", "preload_engine_mode");
612
 
 
613
 
        if (var_preload_engine_mode != null) {
614
 
            preload_engine_mode = var_preload_engine_mode.get_int32();
615
 
        }
616
 
 
617
 
        if (preload_engine_mode == IBus.PreloadEngineMode.USER) {
 
583
        int preload_engine_mode =
 
584
                m_settings_general.get_int("preload-engine-mode");
 
585
 
 
586
        if (preload_engine_mode == IBus.PreloadEngineMode.USER)
618
587
            return;
619
 
        }
620
588
 
621
589
        set_lang_relative_preload_engines();
622
590
    }
660
628
            var_xkb_engine_names += "%s:%s:%s".printf("xkb", name, lang);
661
629
        }
662
630
 
663
 
        GLib.Variant var_engines =
664
 
           m_config.get_value("general", "preload_engines");
665
 
        string[] engine_names = {};
 
631
        string[] engine_names =
 
632
                m_settings_general.get_strv("preload-engines");
666
633
        bool updated_engine_names = false;
667
634
 
668
 
        if (var_engines != null) {
669
 
            engine_names = var_engines.dup_strv();
670
 
        }
671
 
 
672
635
        foreach (string name in var_xkb_engine_names) {
673
636
            if (name in engine_names)
674
637
                continue;
676
639
            engine_names += name;
677
640
        }
678
641
 
679
 
        if (updated_engine_names) {
680
 
            m_config.set_value("general",
681
 
                               "preload_engines",
682
 
                               new GLib.Variant.strv(engine_names));
683
 
        }
 
642
        if (updated_engine_names)
 
643
            m_settings_general.set_strv("preload-engines", engine_names);
684
644
 
685
 
        GLib.Variant var_order =
686
 
            m_config.get_value("general", "engines_order");
687
 
        string[] order_names = {};
 
645
        string[] order_names =
 
646
                m_settings_general.get_strv("engines-order");
688
647
        bool updated_order_names = false;
689
648
 
690
 
        if (var_order != null) {
691
 
            order_names = var_order.dup_strv();
692
 
        }
693
 
 
694
649
        foreach (var name in var_xkb_engine_names) {
695
650
            if (name in order_names)
696
651
                continue;
698
653
            updated_order_names = true;
699
654
        }
700
655
 
701
 
        if (updated_order_names) {
702
 
            m_config.set_value("general",
703
 
                               "engines_order",
704
 
                               new GLib.Variant.strv(order_names));
705
 
        }
 
656
        if (updated_order_names)
 
657
            m_settings_general.set_strv("engines-order", order_names);
706
658
    }
707
659
 
708
660
    private void set_xkb_group_layout(IBus.EngineDesc engine) {
812
764
        }
813
765
    }
814
766
 
 
767
    private void engine_contexts_insert(IBus.EngineDesc engine) {
 
768
        if (m_use_global_engine)
 
769
            return;
 
770
 
 
771
        if (m_engine_contexts.size() >= 200) {
 
772
            warning ("Contexts by windows are too much counted!");
 
773
            m_engine_contexts.remove_all();
 
774
        }
 
775
 
 
776
        m_engine_contexts.replace(m_current_context_path, engine);
 
777
    }
 
778
 
 
779
    private void set_engine(IBus.EngineDesc engine) {
 
780
        if (!m_bus.set_global_engine(engine.get_name())) {
 
781
            warning("Switch engine to %s failed.", engine.get_name());
 
782
            return;
 
783
        }
 
784
 
 
785
        // set xkb layout
 
786
        if (!m_use_system_keyboard_layout)
 
787
            set_layout(engine);
 
788
 
 
789
        engine_contexts_insert(engine);
 
790
    }
 
791
 
815
792
    private void switch_engine(int i, bool force = false) {
816
793
        GLib.assert(i >= 0 && i < m_engines.length);
817
794
 
821
798
 
822
799
        IBus.EngineDesc engine = m_engines[i];
823
800
 
824
 
        if (!m_bus.set_global_engine(engine.get_name())) {
825
 
            warning("Switch engine to %s failed.", engine.get_name());
826
 
            return;
827
 
        }
828
 
        // set xkb layout
829
 
        if (!m_use_system_keyboard_layout) {
830
 
            set_layout(engine);
831
 
        }
832
 
    }
833
 
 
834
 
    private void config_value_changed_cb(IBus.Config config,
835
 
                                         string section,
836
 
                                         string name,
837
 
                                         Variant variant) {
838
 
        if (section == "general" && name == "preload_engine_mode") {
839
 
            update_im_engines();
840
 
            return;
841
 
        }
842
 
 
843
 
        if (section == "general" && name == "preload_engines") {
844
 
            update_engines(variant, null);
845
 
            return;
846
 
        }
847
 
 
848
 
        if (section == "general/hotkey" && name == "triggers") {
849
 
            unbind_switch_shortcut();
850
 
            bind_switch_shortcut(variant);
851
 
            return;
852
 
        }
853
 
 
854
 
        if (section == "panel" && (name == "custom_font" ||
855
 
                                   name == "use_custom_font")) {
856
 
            set_custom_font();
857
 
            return;
858
 
        }
859
 
 
860
 
        if (section == "general" && name == "switcher_delay_time") {
861
 
            set_switcher_delay_time(variant);
862
 
            return;
863
 
        }
864
 
 
865
 
        if (section == "general" && name == "use_system_keyboard_layout") {
866
 
            set_use_system_keyboard_layout(variant);
867
 
            return;
868
 
        }
869
 
 
870
 
        if (section == "general" && name == "embed_preedit_text") {
871
 
            set_embed_preedit_text(variant);
872
 
            return;
873
 
        }
 
801
        set_engine(engine);
874
802
    }
875
803
 
876
804
    private void handle_engine_switch(Gdk.Event event, bool revert) {
893
821
 
894
822
        if (pressed && m_switcher_delay_time >= 0) {
895
823
            int i = revert ? m_engines.length - 1 : 1;
 
824
 
 
825
            /* The flag of m_switcher_is_running avoids the following problem:
 
826
             *
 
827
             * When an IME is chosen on m_switcher, focus_in() is called
 
828
             * for the root window. If an engine is set in focus_in()
 
829
             * during running m_switcher when m_use_global_engine is false,
 
830
             * state_changed() is also called and m_engines[] is modified
 
831
             * in state_changed() and m_switcher.run() returns the index
 
832
             * for m_engines[] but m_engines[] was modified by state_changed()
 
833
             * and the index is not correct. */
 
834
            m_switcher_is_running = true;
896
835
            i = m_switcher.run(keyval, modifiers, event, m_engines, i);
 
836
            m_switcher_is_running = false;
 
837
 
897
838
            if (i < 0) {
898
839
                debug("switch cancelled");
899
840
            } else {
917
858
        m_bus.preload_engines_async(names, -1, null);
918
859
    }
919
860
 
920
 
    private void update_engines(GLib.Variant? var_engines,
921
 
                                GLib.Variant? var_order) {
922
 
        string[] engine_names = null;
 
861
    private void update_engines(string[]? unowned_engine_names,
 
862
                                string[]? order_names) {
 
863
        string[]? engine_names = unowned_engine_names;
923
864
 
924
 
        if (var_engines != null)
925
 
            engine_names = var_engines.dup_strv();
926
865
        if (engine_names == null || engine_names.length == 0)
927
866
            engine_names = {"xkb:us::eng"};
928
867
 
929
 
        string[] order_names =
930
 
            (var_order != null) ? var_order.dup_strv() : null;
931
 
 
932
868
        string[] names = {};
933
869
 
934
870
        foreach (var name in order_names) {
1113
1049
    }
1114
1050
 
1115
1051
    public override void focus_in(string input_context_path) {
 
1052
        if (m_use_global_engine)
 
1053
            return;
 
1054
 
 
1055
        /* Do not change the order of m_engines during running switcher. */
 
1056
        if (m_switcher_is_running)
 
1057
            return;
 
1058
 
 
1059
        m_current_context_path = input_context_path;
 
1060
 
 
1061
        var engine = m_engine_contexts[m_current_context_path];
 
1062
 
 
1063
        if (engine == null) {
 
1064
            /* If engine == null, need to call set_engine(m_engines[0])
 
1065
             * here and update m_engine_contexts[] to avoid the
 
1066
             * following problem:
 
1067
             *
 
1068
             * If context1 is focused and does not set an engine and
 
1069
             * return here, the current engine1 is used for context1.
 
1070
             * When context2 is focused and switch engine1 to engine2,
 
1071
             * the current engine becomes engine2.
 
1072
             * And when context1 is focused again, context1 still
 
1073
             * does not set an engine and return here,
 
1074
             * engine2 is used for context2 instead of engine1. */
 
1075
            engine = m_engines.length > 0 ? m_engines[0] : null;
 
1076
 
 
1077
            if (engine == null)
 
1078
                return;
 
1079
        } else {
 
1080
            bool in_engines = false;
 
1081
 
 
1082
            foreach (var e in m_engines) {
 
1083
                if (engine.get_name() == e.get_name()) {
 
1084
                    in_engines = true;
 
1085
                    break;
 
1086
                }
 
1087
            }
 
1088
 
 
1089
            /* The engine is deleted by ibus-setup before focus_in()
 
1090
             * is called. */
 
1091
            if (!in_engines)
 
1092
                return;
 
1093
        }
 
1094
 
 
1095
        set_engine(engine);
1116
1096
    }
1117
1097
 
1118
1098
    public override void focus_out(string input_context_path) {
 
1099
        if (m_use_global_engine)
 
1100
            return;
 
1101
 
 
1102
        /* Do not change the order of m_engines during running switcher. */
 
1103
        if (m_switcher_is_running)
 
1104
            return;
 
1105
 
 
1106
        m_current_context_path = "";
 
1107
    }
 
1108
 
 
1109
    public override void destroy_context(string input_context_path) {
 
1110
        if (m_use_global_engine)
 
1111
            return;
 
1112
 
 
1113
        m_engine_contexts.remove(input_context_path);
1119
1114
    }
1120
1115
 
1121
1116
    public override void register_properties(IBus.PropList props) {
1158
1153
    }
1159
1154
 
1160
1155
    public override void state_changed() {
 
1156
        /* Do not change the order of m_engines during running switcher. */
 
1157
        if (m_switcher_is_running)
 
1158
            return;
 
1159
 
1161
1160
        var icon_name = "ibus-keyboard";
1162
1161
 
1163
1162
        var engine = m_bus.get_global_engine();
1201
1200
        foreach(var desc in m_engines) {
1202
1201
            names += desc.get_name();
1203
1202
        }
1204
 
        if (m_config != null)
1205
 
            m_config.set_value("general",
1206
 
                               "engines_order",
1207
 
                               new GLib.Variant.strv(names));
 
1203
        m_settings_general.set_strv("engines-order", names);
1208
1204
    }
1209
1205
}