From 455526804beab00adc7b96d01b7e53355123c3d7 Mon Sep 17 00:00:00 2001
From: Ray Strode <rstrode@redhat.com>
Date: Wed, 16 Aug 2023 11:13:39 -0400
Subject: [PATCH 2/3] status/keyboard: Load keyboard from system settings if
 gsettings unconfigured

Right now if a user hasn't configured their input sources, the code falls back to
using the current layout on Xorg and the mutter default with wayland.

This commit changes the code to instead fall back to using the system
default (as configured by localed).
---
 js/ui/status/keyboard.js | 58 +++++++++++++++++++++++++++++++---------
 1 file changed, 45 insertions(+), 13 deletions(-)

diff --git a/js/ui/status/keyboard.js b/js/ui/status/keyboard.js
index 7277c6d09..97e35d482 100644
--- a/js/ui/status/keyboard.js
+++ b/js/ui/status/keyboard.js
@@ -1,54 +1,57 @@
 // -*- mode: js; js-indent-level: 4; indent-tabs-mode: nil -*-
 
 import Clutter from 'gi://Clutter';
 import Gio from 'gi://Gio';
 import GLib from 'gi://GLib';
 import GObject from 'gi://GObject';
 import IBus from 'gi://IBus';
 import Meta from 'gi://Meta';
 import Shell from 'gi://Shell';
 import St from 'gi://St';
 import * as Gettext from 'gettext';
 import * as Signals from '../../misc/signals.js';
 
 import * as IBusManager from '../../misc/ibusManager.js';
 import * as KeyboardManager from '../../misc/keyboardManager.js';
 import * as Main from '../main.js';
 import * as PopupMenu from '../popupMenu.js';
 import * as PanelMenu from '../panelMenu.js';
 import * as SwitcherPopup from '../switcherPopup.js';
 import * as Util from '../../misc/util.js';
 
 export const INPUT_SOURCE_TYPE_XKB = 'xkb';
 export const INPUT_SOURCE_TYPE_IBUS = 'ibus';
 
+const DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources';
+const KEY_INPUT_SOURCES = 'sources';
+
 export const LayoutMenuItem = GObject.registerClass(
 class LayoutMenuItem extends PopupMenu.PopupBaseMenuItem {
     _init(displayName, shortName) {
         super._init();
 
         this.setOrnament(PopupMenu.Ornament.NONE);
 
         this.label = new St.Label({
             text: displayName,
             x_expand: true,
         });
         this.indicator = new St.Label({text: shortName});
         this.add_child(this.label);
         this.add(this.indicator);
         this.label_actor = this.label;
     }
 });
 
 export class InputSource extends Signals.EventEmitter {
     constructor(type, id, displayName, shortName, index) {
         super();
 
         this.type = type;
         this.id = id;
         this.displayName = displayName;
         this._shortName = shortName;
         this.index = index;
 
         this.properties = null;
 
@@ -236,166 +239,195 @@ class InputSourceSystemSettings extends InputSourceSettings {
             this._layouts = layouts;
             this._variants = variants;
             this._emitInputSourcesChanged();
         }
         if (options !== this._options) {
             this._options = options;
             this._emitKeyboardOptionsChanged();
         }
     }
 
     get inputSources() {
         let sourcesList = [];
         let layouts = this._layouts.split(',');
         let variants = this._variants.split(',');
 
         for (let i = 0; i < layouts.length && !!layouts[i]; i++) {
             let id = layouts[i];
             if (variants[i])
                 id += `+${variants[i]}`;
             sourcesList.push({type: INPUT_SOURCE_TYPE_XKB, id});
         }
         return sourcesList;
     }
 
     get keyboardOptions() {
         return this._options.split(',');
     }
 }
 
 class InputSourceSessionSettings extends InputSourceSettings {
-    constructor() {
+    constructor(settings) {
         super();
 
-        this._DESKTOP_INPUT_SOURCES_SCHEMA = 'org.gnome.desktop.input-sources';
-        this._KEY_INPUT_SOURCES = 'sources';
         this._KEY_MRU_SOURCES = 'mru-sources';
         this._KEY_KEYBOARD_OPTIONS = 'xkb-options';
         this._KEY_PER_WINDOW = 'per-window';
 
-        this._settings = new Gio.Settings({schema_id: this._DESKTOP_INPUT_SOURCES_SCHEMA});
-        this._settings.connect(`changed::${this._KEY_INPUT_SOURCES}`, this._emitInputSourcesChanged.bind(this));
+        this._settings = settings;
+        this._settings.connect(`changed::${KEY_INPUT_SOURCES}`, this._emitInputSourcesChanged.bind(this));
         this._settings.connect(`changed::${this._KEY_KEYBOARD_OPTIONS}`, this._emitKeyboardOptionsChanged.bind(this));
         this._settings.connect(`changed::${this._KEY_PER_WINDOW}`, this._emitPerWindowChanged.bind(this));
     }
 
     _getSourcesList(key) {
         let sourcesList = [];
         let sources = this._settings.get_value(key);
         let nSources = sources.n_children();
 
         for (let i = 0; i < nSources; i++) {
             let [type, id] = sources.get_child_value(i).deepUnpack();
             sourcesList.push({type, id});
         }
         return sourcesList;
     }
 
     get inputSources() {
-        return this._getSourcesList(this._KEY_INPUT_SOURCES);
+        return this._getSourcesList(KEY_INPUT_SOURCES);
     }
 
     get mruSources() {
         return this._getSourcesList(this._KEY_MRU_SOURCES);
     }
 
     set mruSources(sourcesList) {
         let sources = GLib.Variant.new('a(ss)', sourcesList);
         this._settings.set_value(this._KEY_MRU_SOURCES, sources);
     }
 
     get keyboardOptions() {
         return this._settings.get_strv(this._KEY_KEYBOARD_OPTIONS);
     }
 
     get perWindow() {
         return this._settings.get_boolean(this._KEY_PER_WINDOW);
     }
 }
 
 export class InputSourceManager extends Signals.EventEmitter {
     constructor() {
         super();
 
         // All valid input sources currently in the gsettings
         // KEY_INPUT_SOURCES list indexed by their index there
         this._inputSources = {};
         // All valid input sources currently in the gsettings
         // KEY_INPUT_SOURCES list of type INPUT_SOURCE_TYPE_IBUS
         // indexed by the IBus ID
         this._ibusSources = {};
 
         this._currentSource = null;
 
         // All valid input sources currently in the gsettings
         // KEY_INPUT_SOURCES list ordered by most recently used
         this._mruSources = [];
         this._mruSourcesBackup = null;
         this._keybindingAction =
             Main.wm.addKeybinding('switch-input-source',
                 new Gio.Settings({schema_id: 'org.gnome.desktop.wm.keybindings'}),
                 Meta.KeyBindingFlags.NONE,
                 Shell.ActionMode.ALL,
                 this._switchInputSource.bind(this));
         this._keybindingActionBackward =
             Main.wm.addKeybinding('switch-input-source-backward',
                 new Gio.Settings({schema_id: 'org.gnome.desktop.wm.keybindings'}),
                 Meta.KeyBindingFlags.IS_REVERSED,
                 Shell.ActionMode.ALL,
                 this._switchInputSource.bind(this));
-        if (Main.sessionMode.isGreeter)
-            this._settings = new InputSourceSystemSettings();
-        else
-            this._settings = new InputSourceSessionSettings();
-        this._settings.connect('input-sources-changed', this._inputSourcesChanged.bind(this));
-        this._settings.connect('keyboard-options-changed', this._keyboardOptionsChanged.bind(this));
 
         this._xkbInfo = KeyboardManager.getXkbInfo();
         this._keyboardManager = KeyboardManager.getKeyboardManager();
 
         this._ibusReady = false;
         this._ibusManager = IBusManager.getIBusManager();
         this._ibusManager.connect('ready', this._ibusReadyCallback.bind(this));
         this._ibusManager.connect('properties-registered', this._ibusPropertiesRegistered.bind(this));
         this._ibusManager.connect('property-updated', this._ibusPropertyUpdated.bind(this));
         this._ibusManager.connect('set-content-type', this._ibusSetContentType.bind(this));
 
+        this._inputSettings = new Gio.Settings({schema_id: DESKTOP_INPUT_SOURCES_SCHEMA});
+        this._setupInputSettings();
+
         global.display.connect('modifiers-accelerator-activated', this._modifiersSwitcher.bind(this));
 
         this._sourcesPerWindow = false;
         this._focusWindowNotifyId = 0;
-        this._settings.connect('per-window-changed', this._sourcesPerWindowChanged.bind(this));
         this._sourcesPerWindowChanged();
         this._disableIBus = false;
         this._reloading = false;
     }
 
+    _sessionHasNoInputSettings() {
+        return this._inputSettings.get_user_value(KEY_INPUT_SOURCES) === null;
+    }
+
+    _reloadInputSettings() {
+        const hadNoSessionInputSettings = this._hasNoSessionInputSettings;
+
+        if (Main.sessionMode.isGreeter)
+            this._hasNoSessionInputSettings = true;
+        else
+            this._hasNoSessionInputSettings = this._sessionHasNoInputSettings();
+
+        if (this._settings && hadNoSessionInputSettings === this._hasNoSessionInputSettings)
+            return;
+
+        this._settings?.disconnectObject(this);
+
+        if (this._hasNoSessionInputSettings)
+            this._settings = new InputSourceSystemSettings();
+        else
+            this._settings = new InputSourceSessionSettings(this._inputSettings);
+
+        this._settings.connectObject('input-sources-changed', this._inputSourcesChanged.bind(this),
+                                     'keyboard-options-changed', this._keyboardOptionsChanged.bind(this),
+                                     'per-window-changed', this._sourcesPerWindowChanged.bind(this), this);
+        this.reload();
+    }
+
+    _setupInputSettings() {
+        if (!Main.sessionMode.isGreeter)
+            this._inputSettings.connect(`changed::${KEY_INPUT_SOURCES}`, this._reloadInputSettings.bind(this));
+
+        this._reloadInputSettings();
+    }
+
     reload() {
         this._reloading = true;
         this._keyboardManager.setKeyboardOptions(this._settings.keyboardOptions);
         this._inputSourcesChanged();
         this._reloading = false;
     }
 
     _ibusReadyCallback(im, ready) {
         if (this._ibusReady === ready)
             return;
 
         this._ibusReady = ready;
         this._mruSources = [];
         this._inputSourcesChanged();
     }
 
     _modifiersSwitcher() {
         let sourceIndexes = Object.keys(this._inputSources);
         if (sourceIndexes.length === 0) {
             KeyboardManager.releaseKeyboard();
             return true;
         }
 
         let is = this._currentSource;
         if (!is)
             is = this._inputSources[sourceIndexes[0]];
 
         let nextIndex = is.index + 1;
         if (nextIndex > sourceIndexes[sourceIndexes.length - 1])
             nextIndex = 0;
-- 
2.41.0.rc2

