Skip to content

Commit

Permalink
Fix keyboard switching on Ubuntu 18.04 (fixes #887)
Browse files Browse the repository at this point in the history
Ubuntu 18.04 changed the way how to switch keyboards. The previous
method of setting a dconf value is deprecated and no longer works.
Instead this is done by a DBus method call.

This change also adds a property to detect if the program runs in
a Gnome Shell, and fixes a bug where the wrong keyboard adaptor was
used in Ubuntu 18.04.
  • Loading branch information
ermshiperete committed Jun 19, 2020
1 parent f4e3d62 commit 296705f
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 20 deletions.
15 changes: 9 additions & 6 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
## [Unreleased]

### Added

- [SIL.DblBundle] `DblMetadata.Load` overload to allow deserialization from a `TextReader`.
- [SIL.Scripture] `Versification.Table.Load` overload to allow deserialization from a `TextReader`.
- [SIL.DblBundle] `TextBundle<TM, TL>.GetVersification` (to replace deprecated `CopyVersificationFile`)
Expand All @@ -25,14 +26,15 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- [SIL.Scripture] `ScrVers.Save` overload to allow serialization to a `TextWriter`.
- [SIL.Core] `XmlSerializationHelper.Serialize<T>` to allow serialization to a `TextWriter`.
- [SIL.Core] `XmlSerializationHelper.Deserialize<T>` to allow deserialization from a `TextReader`.
- [SIL.Core] `Platform.IsGnomeShell` to detect if executing in a Gnome Shell

### Changed

- Add build number to `AssemblyFileVersion`
- Improve nuget symbol packages
- Use NUnit 3 for unit tests
- [SIL.Core, SIL.Core.Desktop] Move several classes back to `SIL.Core` from `SIL.Core.Desktop` to make
them available to .NET Standard clients.
- [SIL.Core, SIL.Core.Desktop] Move several classes back to `SIL.Core` from `SIL.Core.Desktop` to
make them available to .NET Standard clients:
- IO/PathUtilities
- IO/TempFileForSafeWriting
- Reporting/AnalyticsEventSender
Expand All @@ -53,17 +55,18 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed

- [SIL.Windows.Forms.Keyboarding] Use signed version of `Keyman*Interop.dll` (#865)
- [SIL.Windows.Forms] Use signed versions of `ibusdotnet.dll`, `Interop.WIA.dll`, `DialogAdapters.dll`,
and `MarkdownDeep.dll` (#865)
- [SIL.Windows.Forms.Keyboarding] Fixed keyboard switching for Ubuntu 18.04 (#887)
- [SIL.Windows.Forms] Use signed versions of `ibusdotnet.dll`, `Interop.WIA.dll`,
`DialogAdapters.dll`, and `MarkdownDeep.dll` (#865)
- [SIL.Media] Fix missing `irrKlang.NET4.dll` exception by copying it to `lib` folder in output

### Deprecated

- [SIL.Core] Deprecate `ExceptionHandler.Init()` method in favor of more explicit version
`ExceptionHandler.Init(ExceptionHandler)`, e.g. `ExceptionHandler.Init(new WinFormsExceptionHandler())`
- [SIL.Core] Deprecate `HttpUtilityFromMono` class. Use `System.Web.HttpUtility` instead.
- [SIL.DblBundle] Deprecate `TextBundle.CopyVersificationFile`, `CopyFontFiles` and `CopyLdmlFile` in favor
of `GetVersificationFile`, `GetFontFiles`, and `GetLdmlFile`.
- [SIL.DblBundle] Deprecate `TextBundle.CopyVersificationFile`, `CopyFontFiles` and
`CopyLdmlFile` in favor of `GetVersificationFile`, `GetFontFiles`, and `GetLdmlFile`.

### Removed

Expand Down
12 changes: 12 additions & 0 deletions SIL.Core/PlatformUtilities/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -325,5 +325,17 @@ private static string RunTerminalCommand(string cmd, string args = null)
public static string ProcessArchitecture => Environment.Is64BitProcess ? x64 : x86;

public static bool IsRunning64Bit => Environment.Is64BitProcess;

public static bool IsGnomeShell
{
get
{
if (!IsLinux)
return false;

var pids = RunTerminalCommand("pidof", "gnome-shell");
return !string.IsNullOrEmpty(pids);
}
}
}
}
3 changes: 2 additions & 1 deletion SIL.Windows.Forms.Keyboarding/KeyboardController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,8 @@ private void SetDefaultKeyboardAdaptors()
{
new XkbKeyboardRetrievingAdaptor(), new IbusKeyboardRetrievingAdaptor(),
new UnityXkbKeyboardRetrievingAdaptor(), new UnityIbusKeyboardRetrievingAdaptor(),
new CombinedIbusKeyboardRetrievingAdaptor()
new CombinedIbusKeyboardRetrievingAdaptor(),
new GnomeShellIbusKeyboardRetrievingAdaptor()
}
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,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");
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// 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.
/// </summary>
public class GnomeShellIbusKeyboardRetrievingAdaptor: UnityIbusKeyboardRetrievingAdaptor
{
protected override IKeyboardSwitchingAdaptor CreateSwitchingAdaptor()
{
return new GnomeShellIbusKeyboardSwitchingAdaptor(IbusCommunicator);
}

public override bool IsApplicable => _helper.IsApplicable && Platform.IsGnomeShell;
}
}
Original file line number Diff line number Diff line change
@@ -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
{
/// <summary>
/// Class for dealing with ibus keyboards on Gnome Shell (as found in Ubuntu Bionic >= 18.04)
/// </summary>
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);
}
}
}

}
}
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using SIL.PlatformUtilities;

namespace SIL.Windows.Forms.Keyboarding.Linux
{
Expand All @@ -19,15 +20,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);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +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
{
/// <summary>
/// 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)
/// </summary>
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;
Expand Down Expand Up @@ -45,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);
}

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}

0 comments on commit 296705f

Please sign in to comment.