diff --git a/SIL.Core/PlatformUtilities/Platform.cs b/SIL.Core/PlatformUtilities/Platform.cs index 621d3fcf0..b7363d287 100644 --- a/SIL.Core/PlatformUtilities/Platform.cs +++ b/SIL.Core/PlatformUtilities/Platform.cs @@ -319,5 +319,17 @@ private static string RunTerminalCommand(string cmd, string args = null) return output.Trim(); } + + public static bool IsGnomeShell + { + get + { + if (!IsLinux) + return false; + + var pids = RunTerminalCommand("pidof", "gnome-shell"); + return !string.IsNullOrEmpty(pids); + } + } } } diff --git a/SIL.Windows.Forms.Keyboarding/KeyboardController.cs b/SIL.Windows.Forms.Keyboarding/KeyboardController.cs index abf0cff11..ca3c4d3cc 100644 --- a/SIL.Windows.Forms.Keyboarding/KeyboardController.cs +++ b/SIL.Windows.Forms.Keyboarding/KeyboardController.cs @@ -229,7 +229,8 @@ private void SetDefaultKeyboardAdaptors() { new XkbKeyboardRetrievingAdaptor(), new IbusKeyboardRetrievingAdaptor(), new UnityXkbKeyboardRetrievingAdaptor(), new UnityIbusKeyboardRetrievingAdaptor(), - new CombinedIbusKeyboardRetrievingAdaptor() + new CombinedIbusKeyboardRetrievingAdaptor(), + new GnomeShellIbusKeyboardRetrievingAdaptor() } ); } diff --git a/SIL.Windows.Forms.Keyboarding/Linux/CombinedIbusKeyboardRetrievingAdaptor.cs b/SIL.Windows.Forms.Keyboarding/Linux/CombinedIbusKeyboardRetrievingAdaptor.cs index 271c1bf29..ecf312a65 100644 --- a/SIL.Windows.Forms.Keyboarding/Linux/CombinedIbusKeyboardRetrievingAdaptor.cs +++ b/SIL.Windows.Forms.Keyboarding/Linux/CombinedIbusKeyboardRetrievingAdaptor.cs @@ -154,7 +154,7 @@ public override bool IsApplicable } var list = GetMyKeyboards(_settingsGeneral); return list != null && list.Length > 0 && Platform.DesktopEnvironment != "unity" - && Platform.DesktopEnvironment != "gnome"; + && !Platform.DesktopEnvironment.Contains("gnome"); } } diff --git a/SIL.Windows.Forms.Keyboarding/Linux/GnomeShellIbusKeyboardRetrievingAdaptor.cs b/SIL.Windows.Forms.Keyboarding/Linux/GnomeShellIbusKeyboardRetrievingAdaptor.cs new file mode 100644 index 000000000..273fbcfc5 --- /dev/null +++ b/SIL.Windows.Forms.Keyboarding/Linux/GnomeShellIbusKeyboardRetrievingAdaptor.cs @@ -0,0 +1,22 @@ +// Copyright (c) 2020 SIL International +// This software is licensed under the MIT License (http://opensource.org/licenses/MIT) + +using SIL.PlatformUtilities; + +namespace SIL.Windows.Forms.Keyboarding.Linux +{ + /// + /// This class handles initializing the list of keyboards on Ubuntu versions >= 18.04. + /// The keyboard retrieving part is identical to previous versions but switching keyboards + /// changed with 18.04. + /// + public class GnomeShellIbusKeyboardRetrievingAdaptor: UnityIbusKeyboardRetrievingAdaptor + { + protected override IKeyboardSwitchingAdaptor CreateSwitchingAdaptor() + { + return new GnomeShellIbusKeyboardSwitchingAdaptor(IbusCommunicator); + } + + public override bool IsApplicable => _helper.IsApplicable && Platform.IsGnomeShell; + } +} \ No newline at end of file diff --git a/SIL.Windows.Forms.Keyboarding/Linux/GnomeShellIbusKeyboardSwitchingAdaptor.cs b/SIL.Windows.Forms.Keyboarding/Linux/GnomeShellIbusKeyboardSwitchingAdaptor.cs new file mode 100644 index 000000000..5c03948a5 --- /dev/null +++ b/SIL.Windows.Forms.Keyboarding/Linux/GnomeShellIbusKeyboardSwitchingAdaptor.cs @@ -0,0 +1,54 @@ +// Copyright (c) 2020 SIL International +// This software is licensed under the MIT License (http://opensource.org/licenses/MIT) + +using System; +using System.Diagnostics; +using SIL.Reporting; + +namespace SIL.Windows.Forms.Keyboarding.Linux +{ + /// + /// Class for dealing with ibus keyboards on Gnome Shell (as found in Ubuntu Bionic >= 18.04) + /// + public class GnomeShellIbusKeyboardSwitchingAdaptor: UnityIbusKeyboardSwitchingAdaptor, IUnityKeyboardSwitchingAdaptor + { + public GnomeShellIbusKeyboardSwitchingAdaptor(IIbusCommunicator ibusCommunicator) + : base(ibusCommunicator) + { + } + + void IUnityKeyboardSwitchingAdaptor.SelectKeyboard(uint index) + { + var okay = false; + // https://askubuntu.com/a/1039964 + try + { + using (var proc = new Process { + EnableRaisingEvents = false, + StartInfo = { + FileName = "/usr/bin/gdbus", + Arguments = "call --session --dest org.gnome.Shell --object-path /org/gnome/Shell " + + "--method org.gnome.Shell.Eval " + + $"\"imports.ui.status.keyboard.getInputSourceManager().inputSources[{index}].activate()\"", + UseShellExecute = false + } + }) + { + proc.Start(); + proc.WaitForExit(); + okay = proc.ExitCode == 0; + } + } + finally + { + if (!okay) + { + var msg = $"GnomeShellIbusKeyboardSwitchingAdaptor.SelectKeyboard({index}) failed"; + Console.WriteLine(msg); + Logger.WriteEvent(msg); + } + } + } + + } +} \ No newline at end of file diff --git a/SIL.Windows.Forms.Keyboarding/Linux/IUnityKeyboardSwitchingAdaptor.cs b/SIL.Windows.Forms.Keyboarding/Linux/IUnityKeyboardSwitchingAdaptor.cs new file mode 100644 index 000000000..bd690bc77 --- /dev/null +++ b/SIL.Windows.Forms.Keyboarding/Linux/IUnityKeyboardSwitchingAdaptor.cs @@ -0,0 +1,10 @@ +// Copyright (c) 2020 SIL International +// This software is licensed under the MIT License (http://opensource.org/licenses/MIT) + +namespace SIL.Windows.Forms.Keyboarding.Linux +{ + internal interface IUnityKeyboardSwitchingAdaptor + { + void SelectKeyboard(uint index); + } +} \ No newline at end of file diff --git a/SIL.Windows.Forms.Keyboarding/Linux/UnityIbusKeyboardRetrievingAdaptor.cs b/SIL.Windows.Forms.Keyboarding/Linux/UnityIbusKeyboardRetrievingAdaptor.cs index 04dc02d6d..8ab4a2beb 100644 --- a/SIL.Windows.Forms.Keyboarding/Linux/UnityIbusKeyboardRetrievingAdaptor.cs +++ b/SIL.Windows.Forms.Keyboarding/Linux/UnityIbusKeyboardRetrievingAdaptor.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; using System.Linq; +using SIL.PlatformUtilities; namespace SIL.Windows.Forms.Keyboarding.Linux { @@ -20,15 +21,20 @@ public class UnityIbusKeyboardRetrievingAdaptor : IbusKeyboardRetrievingAdaptor #region Specific implementations of IKeyboardRetriever - public override bool IsApplicable => _helper.IsApplicable; + public override bool IsApplicable => _helper.IsApplicable && !Platform.IsGnomeShell; public override void Initialize() { - SwitchingAdaptor = new UnityIbusKeyboardSwitchingAdaptor(IbusCommunicator); + SwitchingAdaptor = CreateSwitchingAdaptor(); KeyboardRetrievingHelper.AddIbusVersionAsErrorReportProperty(); InitKeyboards(); } + protected virtual IKeyboardSwitchingAdaptor CreateSwitchingAdaptor() + { + return new UnityIbusKeyboardSwitchingAdaptor(IbusCommunicator); + } + protected override string GetKeyboardSetupApplication(out string arguments) { var program = _helper.GetKeyboardSetupApplication(out arguments); diff --git a/SIL.Windows.Forms.Keyboarding/Linux/UnityIbusKeyboardSwitchingAdaptor.cs b/SIL.Windows.Forms.Keyboarding/Linux/UnityIbusKeyboardSwitchingAdaptor.cs index 5cb194949..eb7097532 100644 --- a/SIL.Windows.Forms.Keyboarding/Linux/UnityIbusKeyboardSwitchingAdaptor.cs +++ b/SIL.Windows.Forms.Keyboarding/Linux/UnityIbusKeyboardSwitchingAdaptor.cs @@ -1,22 +1,22 @@ // Copyright (c) 2015 SIL International // This software is licensed under the MIT License (http://opensource.org/licenses/MIT) using System; +using SIL.PlatformUtilities; using SIL.Reporting; namespace SIL.Windows.Forms.Keyboarding.Linux { /// - /// Class for dealing with ibus keyboards on Unity (as found in Trusty >= 13.10) + /// Class for dealing with ibus keyboards on Unity (as found in Trusty >= 13.10 < 18.04) /// - [CLSCompliant(false)] - public class UnityIbusKeyboardSwitchingAdaptor : IbusKeyboardSwitchingAdaptor + public class UnityIbusKeyboardSwitchingAdaptor : IbusKeyboardSwitchingAdaptor, IUnityKeyboardSwitchingAdaptor { public UnityIbusKeyboardSwitchingAdaptor(IIbusCommunicator ibusCommunicator) : base(ibusCommunicator) { } - internal static void SelectKeyboard(uint index) + void IUnityKeyboardSwitchingAdaptor.SelectKeyboard(uint index) { const string schema = "org.gnome.desktop.input-sources"; bool okay = true; @@ -46,8 +46,8 @@ internal static void SelectKeyboard(uint index) protected override void SelectKeyboard(KeyboardDescription keyboard) { var ibusKeyboard = (IbusKeyboardDescription) keyboard; - uint systemIndex = ibusKeyboard.SystemIndex; - SelectKeyboard(systemIndex); + var systemIndex = ibusKeyboard.SystemIndex; + ((IUnityKeyboardSwitchingAdaptor)this).SelectKeyboard(systemIndex); } } diff --git a/SIL.Windows.Forms.Keyboarding/Linux/UnityXkbKeyboardSwitchingAdaptor.cs b/SIL.Windows.Forms.Keyboarding/Linux/UnityXkbKeyboardSwitchingAdaptor.cs index 88775e813..6b90a7db0 100644 --- a/SIL.Windows.Forms.Keyboarding/Linux/UnityXkbKeyboardSwitchingAdaptor.cs +++ b/SIL.Windows.Forms.Keyboarding/Linux/UnityXkbKeyboardSwitchingAdaptor.cs @@ -16,11 +16,13 @@ public UnityXkbKeyboardSwitchingAdaptor(IXklEngine engine): base(engine) protected override void SelectKeyboard(KeyboardDescription keyboard) { var xkbKeyboard = keyboard as XkbKeyboardDescription; - if (xkbKeyboard != null) - { - if (xkbKeyboard.GroupIndex >= 0) - UnityIbusKeyboardSwitchingAdaptor.SelectKeyboard((uint)xkbKeyboard.GroupIndex); - } + if (xkbKeyboard == null || xkbKeyboard.GroupIndex < 0) + return; + + var switchingAdaptor = KeyboardController.Instance + .Adaptors[KeyboardAdaptorType.OtherIm] + .SwitchingAdaptor as IUnityKeyboardSwitchingAdaptor; + switchingAdaptor.SelectKeyboard((uint) xkbKeyboard.GroupIndex); } } }