Making the Magic Trackpad Work

Funny enough, I actually did all of this work a while ago, before apple announced their new trackpad thingy.

Many people who use the Magic Trackpad (or the Macbook’s trackpad) prefer to do a two finger click instead of a right mouse click. Let me preface by saying, I am not one of you. I like myself a good ol’ fashion right mouse click. Like the computer gods intended.

All sacrilege aside, I have always been really pissed about how Apple hasn’t been able to get their act together when it comes to a right mouse click. Allow me to defend my claim. This is the Magic Trackpad

magic trackpad

It is beautiful and lovely (if you ignore my shadow). And quite large, which I like. I can comfortably stretch my hand over the trackpad and scroll, swipe, pinch, etc with no problems whatsoever. I tend to keep my hand in the center of this giant thing. And this is a picture where a piece of paper is covering the part of the trackpad that is recognized as a right click

magic trackpad right click

What the hell. Why is it that on this giant beast of a trackpad, there’s less than one square inch of a right click region? That is completely useless, which is why so many people go with a two finger click, or control clicking. Not me. Instead, i spend way too much time fighting against the man.

So my solution to the problem was to write an application to make it so the whole right half of the trackpad is recognized as a right click. AKA, making the magic mouse work the way it should have to begin with.

I’m going to assume at this point that you understand the basics of the event tap. if you don’t, go read this. It was originally going to be part of this post, but it got a little long.

Apples Private Multi Touch API


Private doesn’t have to mean scary. Just undocumented, and not really intended for anyone else to know about/use. ūüôā

If you link in Apple’s multi touch api, and you have the right headers, you can do some pretty neat things. Most of what I know on the subject came from pouring over the source of FingerMgmt. I started off by looking for an existing tool such as BetterTouchTool¬†or MagicPrefs¬†to see if I could accomplish my goal, but was quickly underwhelmed. If you want to be able to have gestures to play/pause, skip, previous, run an apple script or all sorts of other crazy things, BetterTouchTool or MagicPrefs has got you covered. But if you want to just make the right half of the track pad be recognized as a right click, you’re out of luck.

But in one of the windows buried deep inside one of those two apps (don’t remember which) I found a vague reference to FingerMgmt, and I spent some time looking at the source. It’s pretty complex as it relies on you having some knowledge about the subject ahead of time, but that’s ok.

You need to get yourself a copy of the multi touch headers. I think that I ended up with a self-modified version. I think it came from a mix of this github, and FingerMgmt. But I did this so long ago that I’m not positive.

With the header added to your Xcode project, you need to link to  /System/Library/PrivateFrameworks/MultitouchSupport.framework

With all that in place, you can hook into the multi touch to recognize when a user touches the trackpad.

This will get a reference to the device you want to monitor, add touchCallback¬†¬†as a function to execute when stuff happens, and then start monitoring the multi touch frame. Unfortunately, the multi touch framework will only tell you information about the touches, it doesn’t tell you when clicks happen – which is why you need to know about the event loop. Also in this code chunk I got my device by it’s ID. I just happened to know (from debugging) that for me it’s¬† 0x400000015dd4d84. I assume these are unique. You could certainly hook up to all multi touch devices in a loop with MTDeviceCreateList¬†¬†or if you’re on a macbook MTDeviceCreateDefault¬†¬†should always give you the one that’s built into the laptop that way you’d never have to go through the trouble of debugging to figure out what your trackpad’s id is.

The App


The app I threw together is really quite simple. Everything can fit in the app delegate.
I put  Application is agent (UIElement) : YES inside my info.plist so that nothing shows up in the dock. At runtime, I created a menu item with an Enable/Disable and Quit button. This allows me to disable the app if I ever have the need. This comes in handy when something causes the event loop to be upset with my app.

I tied into the multi touch framework with this callback

if there’s only one touch, and that touch is on the right half of the trackpad, I set a static bool to YES so that the event tap piece knows to transform any left click into a right click.

Note that the normalizedVector.position.x and  normalizedVector.position.y  points are a 0 to 1 scale.

My event tap looks like this

As you can see right off, I didn’t set up the mask like I should have when i tied into the event tap, so i filter out the undesired events manually. This is something i’m going to go back and fix, but i don’t feel the need to update the code here.

After filtering out the event types i don’t care about, i check that the event came from the HID device with the same ID as my magic trackpad.

When I want to turn the left click into a right click, I create a new mouse event and return the new right click event from my event handler. This will make everything else act as though I had made a right click.

There have been a few issues with this here and there, but they happen pretty infrequently. Whenever I do have problems, I tend to just disable the app, do what I need, and then enable it again.

Rather than supply all of the source in this post, I thought I’d just supply the Xcode project. Keep in mind that since this was a personal project, I didn’t spend too much time making the code beautiful.

Download

It started off as a project named MouseFun. And then I renamed it to RCR because it fit nicely in my menu bar. Though Honestly I forgot what RCR stood for. I think it was… Right Click….. something that starts with the letter R.

Hope someone else out there finds this useful.

3 thoughts on “Making the Magic Trackpad Work

  1. Wow. Cool stuff. Amazing.

    Hey, I’m looking to get access to the ‘secondary’ trackpads (i.e. magic trackpad, magic mouse) in addition to the built-in mac notebook trackpad in my Java program.

    GluLogicMT already has a little lib file for that:

    https://kenai.com/projects/macmultitouch/sources/source-code-repository/content/src/com/alderstone/multitouch/mac/touchpad/TouchpadObservablejnilib.c?rev=6

    But it only captures data from the built-in trackpad.

    Would you know how to extend this to ‘automagically’ include events from all trackpad sources?

    • Sorry for the horrible formatting in this reply. I apparently need to figure out how to get markdown working in comments.

      Looking at the file you referenced, you’d need to change `startMT()` which is line 107. Right now it does

      dev = MTDeviceCreateDefault(0);
      if (dev) {
      MTRegisterContactFrameCallback(dev, mtcallback);
      }
      MTDeviceStart(dev,0 );

      The call to `MTDeviceCreateDefault` is the method that is tying you to the built-in trackpad. Change the variable `dev` into an array and do a call to `MTDeviceCreateList()` this will give you all of the multi touch devices. You’d just need to run through the array in a loop to add the callback and start monitoring the devices. And make sure in `stopMT` that you loop through the array to stop the devices

      The code would look something like this https://gist.github.com/dlprows/4a13db52e2720fe2df1b

      Beyond changing the code file you linked to, there’s not really anything you could do to access the other multi touch devices.
      You might also need to do something so that your java callback includes the specific multitouch device that was being used, but that’s a little beyond my current knowledge.

Leave a Reply

Your email address will not be published. Required fields are marked *