             eventMask |= (1 << mask.rawValue)
         }
         
-        guard let eventTap = CGEvent.tapCreate(tap: .cgSessionEventTap,
-                                               place: .headInsertEventTap,
-                                               options: .defaultTap,
-                                               eventsOfInterest: CGEventMask(eventMask),
-                                               callback: KeyEventWatchCGEventCallback,
-                                               userInfo: nil)
-            else {
+        let observer = UnsafeMutableRawPointer(Unmanaged.passRetained(self).toOpaque())
+        
+        guard let eventTap = CGEvent.tapCreate(
+            tap: .cgSessionEventTap,
+            place: .headInsertEventTap,
+            options: .defaultTap,
+            eventsOfInterest: CGEventMask(eventMask),
+            callback: { (proxy: CGEventTapProxy, type: CGEventType, event: CGEvent, refcon: UnsafeMutableRawPointer?) -> Unmanaged<CGEvent>? in
+                if let observer = refcon {
+                    let mySelf = Unmanaged<KeyEvent>.fromOpaque(observer).takeUnretainedValue()
+                    return mySelf.callback(proxy: proxy, type: type, event: event, refcon: nil)
+                }
+                return Unmanaged.passRetained(event)
+            },
+            userInfo: observer
+        ) else {
                 print("failed to create event tap")
                 exit(1)
         }

//  Copyright (c) 2016 iMasanari
//

// watchCGEventCallbackをクラスの中に入れ、CGEvent.tapCreateのcallbackに設定すると
// `A C function pointer can only be formed from a reference to a 'func' or a literal closure`
// エラーが出たため、watchCGEventCallback、keyCodeなどをクラスの外に

import Cocoa

var KeyEventKeyCode: Int64? = nil

class KeyEvent: NSObject {
    
    override init() {
        super.init()

        CGEvent.tapEnable(tap: eventTap, enable: true)
        CFRunLoopRun()
    }
    
    func callback(proxy: CGEventTapProxy, type: CGEventType, event: CGEvent, refcon: UnsafeMutableRawPointer?) -> Unmanaged<CGEvent>? {
        if [.flagsChanged].contains(type) {
            let keyCode = event.getIntegerValueField(.keyboardEventKeycode)
            
            if let action = singleModifierKeyUpActions[keyCode] {
                if event.flags.rawValue & modifierMasks[keyCode]!.rawValue != 0 {
                    self.keyCode = keyCode
                }
                else if keyCode == self.keyCode {
                    action()
                }
            }
        }
        else {
            self.keyCode = nil
        }
        
        return Unmanaged.passRetained(event)
    }
}

let modifierMasks: [Int64: CGEventFlags] = [
    54: CGEventFlags.maskCommand,
    55: CGEventFlags.maskCommand,
    56: CGEventFlags.maskShift,
    60: CGEventFlags.maskShift,
    59: CGEventFlags.maskControl,
    62: CGEventFlags.maskControl,
    58: CGEventFlags.maskAlternate,
    61: CGEventFlags.maskAlternate,
    63: CGEventFlags.maskSecondaryFn
]

func postKeyboardEvent(_ virtualKey: CGKeyCode, flags: CGEventFlags = CGEventFlags()) -> () -> Void {
    let loc = CGEventTapLocation.cghidEventTap
    let keyDownEvent = CGEvent(keyboardEventSource: nil, virtualKey: virtualKey, keyDown: true)!
    let keyUpEvent = CGEvent(keyboardEventSource: nil, virtualKey: virtualKey, keyDown: false)!
    
    keyDownEvent.flags = flags
    keyUpEvent.flags = CGEventFlags()
    
    return { () -> Void in
        keyDownEvent.post(tap: loc)
        keyUpEvent.post(tap: loc)
    }
}
