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.

(cherry picked from commit 296705f)
  • Loading branch information
ermshiperete authored and jasonleenaylor committed Jun 19, 2020
1 parent 9db21df commit 75535ba
Show file tree
Hide file tree
Showing 9 changed files with 122 additions and 15 deletions.
12 changes: 12 additions & 0 deletions SIL.Core/PlatformUtilities/Platform.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}
}
}
3 changes: 2 additions & 1 deletion SIL.Windows.Forms.Keyboarding/KeyboardController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,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 @@ -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");
}
}

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

}
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 75535ba

Please sign in to comment.