Blame js/misc/keyboardManager.js

Packit Service ed5168
// -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
Packit Service ed5168
Packit Service ed5168
const { GLib, GnomeDesktop, Meta } = imports.gi;
Packit Service ed5168
Packit Service ed5168
const Main = imports.ui.main;
Packit Service ed5168
Packit Service ed5168
var DEFAULT_LOCALE = 'en_US';
Packit Service ed5168
var DEFAULT_LAYOUT = 'us';
Packit Service ed5168
var DEFAULT_VARIANT = '';
Packit Service ed5168
Packit Service ed5168
let _xkbInfo = null;
Packit Service ed5168
Packit Service ed5168
function getXkbInfo() {
Packit Service ed5168
    if (_xkbInfo == null)
Packit Service ed5168
        _xkbInfo = new GnomeDesktop.XkbInfo();
Packit Service ed5168
    return _xkbInfo;
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
let _keyboardManager = null;
Packit Service ed5168
Packit Service ed5168
function getKeyboardManager() {
Packit Service ed5168
    if (_keyboardManager == null)
Packit Service ed5168
        _keyboardManager = new KeyboardManager();
Packit Service ed5168
    return _keyboardManager;
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
function releaseKeyboard() {
Packit Service ed5168
    if (Main.modalCount > 0)
Packit Service ed5168
        global.display.unfreeze_keyboard(global.get_current_time());
Packit Service ed5168
    else
Packit Service ed5168
        global.display.ungrab_keyboard(global.get_current_time());
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
function holdKeyboard() {
Packit Service ed5168
    global.display.freeze_keyboard(global.get_current_time());
Packit Service ed5168
}
Packit Service ed5168
Packit Service ed5168
var KeyboardManager = class {
Packit Service ed5168
    constructor() {
Packit Service ed5168
        // The XKB protocol doesn't allow for more that 4 layouts in a
Packit Service ed5168
        // keymap. Wayland doesn't impose this limit and libxkbcommon can
Packit Service ed5168
        // handle up to 32 layouts but since we need to support X clients
Packit Service ed5168
        // even as a Wayland compositor, we can't bump this.
Packit Service ed5168
        this.MAX_LAYOUTS_PER_GROUP = 4;
Packit Service ed5168
Packit Service ed5168
        this._xkbInfo = getXkbInfo();
Packit Service ed5168
        this._current = null;
Packit Service ed5168
        this._localeLayoutInfo = this._getLocaleLayout();
Packit Service ed5168
        this._layoutInfos = {};
Packit Service ed5168
        this._currentKeymap = null;
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    _applyLayoutGroup(group) {
Packit Service ed5168
        let options = this._buildOptionsString();
Packit Service ed5168
        let [layouts, variants] = this._buildGroupStrings(group);
Packit Service ed5168
Packit Service ed5168
        if (this._currentKeymap &&
Packit Service ed5168
            this._currentKeymap.layouts == layouts &&
Packit Service ed5168
            this._currentKeymap.variants == variants &&
Packit Service ed5168
            this._currentKeymap.options == options)
Packit Service ed5168
            return;
Packit Service ed5168
Packit Service ed5168
        this._currentKeymap = {layouts, variants, options};
Packit Service ed5168
        Meta.get_backend().set_keymap(layouts, variants, options);
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    _applyLayoutGroupIndex(idx) {
Packit Service ed5168
        Meta.get_backend().lock_layout_group(idx);
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    apply(id) {
Packit Service ed5168
        let info = this._layoutInfos[id];
Packit Service ed5168
        if (!info)
Packit Service ed5168
            return;
Packit Service ed5168
Packit Service ed5168
        if (this._current && this._current.group == info.group) {
Packit Service ed5168
            if (this._current.groupIndex != info.groupIndex)
Packit Service ed5168
                this._applyLayoutGroupIndex(info.groupIndex);
Packit Service ed5168
        } else {
Packit Service ed5168
            this._applyLayoutGroup(info.group);
Packit Service ed5168
            this._applyLayoutGroupIndex(info.groupIndex);
Packit Service ed5168
        }
Packit Service ed5168
Packit Service ed5168
        this._current = info;
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    reapply() {
Packit Service ed5168
        if (!this._current)
Packit Service ed5168
            return;
Packit Service ed5168
Packit Service ed5168
        this._applyLayoutGroup(this._current.group);
Packit Service ed5168
        this._applyLayoutGroupIndex(this._current.groupIndex);
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    setUserLayouts(ids) {
Packit Service ed5168
        this._current = null;
Packit Service ed5168
        this._layoutInfos = {};
Packit Service ed5168
Packit Service ed5168
        for (let i = 0; i < ids.length; ++i) {
Packit Service ed5168
            let [found, , , _layout, _variant] = this._xkbInfo.get_layout_info(ids[i]);
Packit Service ed5168
            if (found)
Packit Service ed5168
                this._layoutInfos[ids[i]] = { id: ids[i], layout: _layout, variant: _variant };
Packit Service ed5168
        }
Packit Service ed5168
Packit Service ed5168
        let i = 0;
Packit Service ed5168
        let group = [];
Packit Service ed5168
        for (let id in this._layoutInfos) {
Packit Service ed5168
            // We need to leave one slot on each group free so that we
Packit Service ed5168
            // can add a layout containing the symbols for the
Packit Service ed5168
            // language used in UI strings to ensure that toolkits can
Packit Service ed5168
            // handle mnemonics like Alt+ะค even if the user is
Packit Service ed5168
            // actually typing in a different layout.
Packit Service ed5168
            let groupIndex = i % (this.MAX_LAYOUTS_PER_GROUP - 1);
Packit Service ed5168
            if (groupIndex == 0)
Packit Service ed5168
                group = [];
Packit Service ed5168
Packit Service ed5168
            let info = this._layoutInfos[id];
Packit Service ed5168
            group[groupIndex] = info;
Packit Service ed5168
            info.group = group;
Packit Service ed5168
            info.groupIndex = groupIndex;
Packit Service ed5168
Packit Service ed5168
            i += 1;
Packit Service ed5168
        }
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    _getLocaleLayout() {
Packit Service ed5168
        let locale = GLib.get_language_names()[0];
Packit Service ed5168
        if (locale.indexOf('_') == -1)
Packit Service ed5168
            locale = DEFAULT_LOCALE;
Packit Service ed5168
Packit Service ed5168
        let [found, , id] = GnomeDesktop.get_input_source_from_locale(locale);
Packit Service ed5168
        if (!found)
Packit Service ed5168
            [, , id] = GnomeDesktop.get_input_source_from_locale(DEFAULT_LOCALE);
Packit Service ed5168
Packit Service ed5168
        let _layout, _variant;
Packit Service ed5168
        [found, , , _layout, _variant] = this._xkbInfo.get_layout_info(id);
Packit Service ed5168
        if (found)
Packit Service ed5168
            return { layout: _layout, variant: _variant };
Packit Service ed5168
        else
Packit Service ed5168
            return { layout: DEFAULT_LAYOUT, variant: DEFAULT_VARIANT };
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    _buildGroupStrings(_group) {
Packit Service ed5168
        let group = _group.concat(this._localeLayoutInfo);
Packit Service ed5168
        let layouts = group.map(g => g.layout).join(',');
Packit Service ed5168
        let variants = group.map(g => g.variant).join(',');
Packit Service ed5168
        return [layouts, variants];
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    setKeyboardOptions(options) {
Packit Service ed5168
        this._xkbOptions = options;
Packit Service ed5168
    }
Packit Service ed5168
Packit Service ed5168
    _buildOptionsString() {
Packit Service ed5168
        let options = this._xkbOptions.join(',');
Packit Service ed5168
        return options;
Packit Service ed5168
    }
Packit Service ed5168
};