Skip to content

Instantly share code, notes, and snippets.

@anaisbetts
Last active July 26, 2017 21:56
Show Gist options
  • Save anaisbetts/6038cc364acf5b73ba51f8b0f2e0687f to your computer and use it in GitHub Desktop.
Save anaisbetts/6038cc364acf5b73ba51f8b0f2e0687f to your computer and use it in GitHub Desktop.
Get a notification when someone changes the keyboard language
ObservableKeyboard.InputProfileChanged
.Subscribe(_ => Console.WriteLine("Hey it changed!"));
using System;
using System.Reactive;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Runtime.InteropServices;
using ReactiveUI;
using TSF.InteropTypes;
using TSF.TypeLib;
namespace Peach
{
public static class ObservableKeyboard
{
static readonly Guid IID_ITfLanguageProfileNotifySink = new Guid("43C9FE15-F494-4C17-9DE2-B8A4AC350AA8");
static ObservableKeyboard()
{
var inputProfileChanged = Observable.Create<Unit>((subj) => {
var ns = new NotifySink();
var type = Type.GetTypeFromCLSID(new Guid(CLSIDs.CLSID_TF_InputProcessorProfiles));
var source = (ITfSource)Activator.CreateInstance(type);
var disp = ns.Subscribe(subj);
uint cookie = 0;
var hr = source.AdviseSink(IID_ITfLanguageProfileNotifySink, ns, out cookie);
if (!hr.Succeeded) {
subj.OnError(Marshal.GetExceptionForHR(hr.Code));
}
return Disposable.Create(() => {
if (cookie != 0) source.UnadviseSink(cookie);
Marshal.ReleaseComObject(source);
disp.Dispose();
});
});
InputProfileChanged = inputProfileChanged.Publish().RefCount();
}
public static IObservable<Unit> InputProfileChanged { get; private set; }
}
public class NotifySink : ITfLanguageProfileNotifySink, IObservable<Unit>
{
readonly ScheduledSubject<Unit> inner = new ScheduledSubject<Unit>(RxApp.MainThreadScheduler);
public HRESULT OnLanguageChange(LangID langid, out bool pfAccept)
{
// NB: This doesn't even get called most of the time
pfAccept = true;
return new HRESULT { Code = 0 };
}
public HRESULT OnLanguageChanged()
{
inner.OnNext(Unit.Default);
return new HRESULT { Code = 0 };
}
public IDisposable Subscribe(IObserver<Unit> observer)
{
return inner.Subscribe(observer);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment