gnome-shell/js/misc/keyboardManager.js
Florian Müllner a42f7c2384 cleanup: Use type-safe comparisons
We have been using type-safe comparisons in new code for quite a while
now, however old code has only been adapted slowly.

Change all the remaining bits to get rid of another legacy style
difference.

Part-of: <https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/2866>
2023-08-09 15:10:38 +00:00

170 lines
4.9 KiB
JavaScript

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