 class IOKeyEventMonitor{
   private
   let hidManager:IOHIDManager
+  let notificationCenter :CFNotificationCenter
   let match:CFMutableDictionary
-  var lastSeenSender:String=""
+  
+  var lastActiveKeyboard:String=""
+  var kb2is:[String: TISInputSource]=[String: TISInputSource]()
+  
   
   private class func createDeviceMatchingDictionary( usagePage:Int,  usage:Int ) -> CFMutableDictionary {
     let dict = [

//limitations under the License.

import Foundation
import IOKit
import IOKit.usb
import IOKit.hid

struct IOKeyEventMonitorContext{
  var lastSeenSender:String

  
  init? ( usagePage:Int,  usage:Int ){
    hidManager = IOHIDManagerCreate( kCFAllocatorDefault, IOOptionBits(kIOHIDOptionsTypeNone) );
    notificationCenter = CFNotificationCenterGetDistributedCenter();
    match = IOKeyEventMonitor.createDeviceMatchingDictionary(usagePage:usagePage, usage:usage);
    IOHIDManagerSetDeviceMatching( hidManager, match );
    
  }
  
  deinit {
    // FIXME find out how to pass nil as an IOKit.IOHIDValueCallback to unregister the callback
    let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque());
    //IOHIDManagerRegisterInputValueCallback( hidManager, nil , context);
  }
  
  func readInputSource()->String{
    return "Français";
  }
  func restoreInputSource(keyboard:String)->Void{
    if let targetIs=kb2is[keyboard] {
      TISSelectInputSource(targetIs)
    }else {
      self.storeInputSource(keyboard: keyboard);
    }
  }
  
  func storeInputSource(keyboard:String)->Void{
    let currentSource :TISInputSource = TISCopyCurrentKeyboardInputSource().takeUnretainedValue();
    kb2is[keyboard]=currentSource;
  }

  func onKeyboardEvent(keyboard:String)->Void{
    if(self.lastActiveKeyboard != keyboard){
      self.restoreInputSource(keyboard: keyboard);
      self.lastActiveKeyboard=keyboard;
    }else{
      self.storeInputSource(keyboard: keyboard);
    }
  }
  
  func start()-> Void {
    let context = UnsafeMutableRawPointer(Unmanaged.passUnretained(self).toOpaque());
    let myHIDKeyboardCallback: IOHIDValueCallback={
      (context, ioreturn, sender, value) in
      let selfPtr = Unmanaged<IOKeyEventMonitor>.fromOpaque(context!).takeUnretainedValue();
      let senderDevice = Unmanaged<IOHIDDevice>.fromOpaque(sender!).takeUnretainedValue();
      
      let vendorId=String(describing:IOHIDDeviceGetProperty(senderDevice,kIOHIDVendorIDKey as CFString));
      let productId=String(describing:IOHIDDeviceGetProperty(senderDevice,kIOHIDProductIDKey as CFString));
      let product=String(describing:IOHIDDeviceGetProperty(senderDevice,kIOHIDProductKey as CFString));
      let keyboard = "\(product)[\(vendorId)-\(productId)]";
      selfPtr.onKeyboardEvent(keyboard:keyboard);
      
    }
    
    
    IOHIDManagerRegisterInputValueCallback( hidManager, myHIDKeyboardCallback, context);
    IOHIDManagerScheduleWithRunLoop( hidManager, CFRunLoopGetMain(), CFRunLoopMode.defaultMode!.rawValue);
    IOHIDManagerOpen( hidManager,  IOOptionBits(kIOHIDOptionsTypeNone) );
