Skip to content

Instantly share code, notes, and snippets.

@Burgestrand
Created March 29, 2013 17:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Burgestrand/29c1a845648448becc5d to your computer and use it in GitHub Desktop.
Save Burgestrand/29c1a845648448becc5d to your computer and use it in GitHub Desktop.
require "pry"
require "ffi"
module ObjC
extend FFI::Library
ffi_lib "/System/Library/Frameworks/ApplicationServices.framework/Versions/Current/ApplicationServices"
typedef :pointer, :CFRunLoopSourceRef
typedef :pointer, :CFAllocatorRef
typedef :pointer, :CFMachPortRef
typedef FFI::Type::SLONG, :CFIndex
attach_function :CFMachPortCreateRunLoopSource, [ :CFAllocatorRef, :CFMachPortRef, :CFIndex ], :CFRunLoopSourceRef
enum :CGEventTapLocation, [ :HID, 0, :Session, :AnnotatedSession ]
enum :CGEventTapPlacement, [ :HeadInsert, 0, :TailAppend ]
enum :CGEventTapOptions, [ :Default, 0x00, :ListenOnly ]
typedef :uint64, :CGEventMask
typedef :pointer, :refcon
typedef :pointer, :CGEventTapProxy
typedef :uint32, :CGEventType
typedef :pointer, :CGEventRef
callback :CGEventTapCallBack, [ :CGEventTapProxy, :CGEventType, :CGEventRef, :refcon ], :CGEventRef
attach_function :CGEventTapCreate, [ :CGEventTapLocation, :CGEventTapPlacement, :CGEventTapOptions, :CGEventMask, :CGEventTapCallBack, :refcon ], :CFMachPortRef
typedef :pointer, :CFRunLoopRef
typedef :pointer, :CFRunLoopSourceRef
typedef :pointer, :CFStringRef
attach_function :CFRunLoopAddSource, [ :CFRunLoopRef, :CFRunLoopSourceRef, :CFStringRef ], :void
attach_function :CFRunLoopGetCurrent, [], :CFRunLoopRef
attach_variable :kCFRunLoopCommonModes, :CFStringRef
attach_function :CGEventTapEnable, [ :CFMachPortRef, :bool ], :void
attach_function :CFRunLoopRun, [], :void
typedef :uint16, :CGKeyCode
attach_function :CGEventGetIntegerValueField, [ :CGEventRef, :uint16 ], :CGKeyCode
end
$callback = proc do |proxy, type, event, void|
begin
code = ObjC.CGEventGetIntegerValueField(event, 9)
puts "Code: #{code}"
rescue => e
$stderr.puts "OMG #{e.message}"
end
event
end
tapper = ObjC.CGEventTapCreate(:Session, :HeadInsert, 0, (1 << 10) | (1 << 11), $callback, nil)
abort "Failed to create event tapper" if tapper.null?
source = ObjC.CFMachPortCreateRunLoopSource(nil, tapper, 0)
current = ObjC.CFRunLoopGetCurrent
ObjC.CFRunLoopAddSource(current, source, ObjC.kCFRunLoopCommonModes)
ObjC.CGEventTapEnable(tapper, true)
ObjC.CFRunLoopRun()
binding.pry
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment