As many of you, last week i bought a brand new Apple Magic Mouse. As expected, it's a very powerful device rich of potential. However, it's misteriously software limited. Yet.
The Magic Mouse is powered by a glass surface all touchable as a standard touchpad. This means that every single mm of the upper surface of your Magic Mouse is touchable and highly sensitive. Really amazing!
Apple official driver is really limited (see my other post about momentum scrolling support on Leopard 10.5.x). This include the lack of support for advanced gestures like pinch and rotate.
As many other big troubles, the answer is around us: Trackpad shipped with new MacBook already contains the support for this kind of gestures. Instead, Magic mouse uses a new driver (required to detect the basic multi-touch gestures like swipe and momentum scrolling). Without this driver your new toy is like a water bottle without water.
So, let's start from this new package, named WirelessMouseSoftware.pkg. As you can see from the shoot below, there're two interesting bundles that the package install onto your system disk:
- AppleMultitouchDriver.kext
- PrivateFrameworks/MultitouchSupport.framework
As you can imagine, this binaries contains all that you need in order to disclose the full potentials of our MagicMouse. Using otx tool we can dump and enhance the disassembled code from Mach-O executable files. Using as input files the above ones, we obtain an interesting result:
This call will grab our MultiTouch compliance device list, returning it as an NSArray.
So, a call like this:
Will give us a list of all device that support multi-touch (including trackpad and magicmouse, of course).
Very well!, now we need some kind of callback, in order to bind our device with a standard ObjC function. Searching for callback keyword, we obtain:
Nice shot! Now we need to pass all acquired devices to the callback assigner. Something like this:
One last thing that we need to do is to start the events sending queue:
At this point, we need to code a touchCallback function, in order to grab the desired multitouch events and send an appropriate response to the CGEvents queue:
The following proof of concept grab (very rawly) the pinch event, using the euclide's distance between the two fingers, and send a combined keystrokes as response to the front most application (kCGHIDEEventTap). Launching the binary and bring a Preview.app window to the front, you'll able to pinch in/out, using your magic mouse...amazing! :-)
I've included a commented function, to dump the whole output from magicmouse. You can use it as a skeleton to write an userspace level wrapper driver, in order to catch appropriately all events.
I think that the next OSX update, will include a built-in support for multi-touches gestures of MagicMouse. However, you've all the details to write your own support.
Happy hack!
References
- NSTouch Class Reference
- NSEvent Class Reference