Jase's picture

No mouse input on Mac OSX 10.7.2, OpenTK bug? [Updated]

** Updated, see post below

I'm having trouble getting mouse input to work using OpenTK.Mouse.GetState() on my Macbook Pro running MacOSX 10.7.2 & Mono 2.10.6 from within MonoDevelop 2.8.4.2 . **EDIT: I should mention that I'm using a version of OpenTK that I pulled down from the source repository a couple of hours ago.

The string from the start of the debug trace log with more info: "Darwin Kernel Version 11.2.0: Tue Aug 9 20:54:00 PDT 2011; root:xnu-1699.24.8~1/RELEASE_X86_64"

I've spent some time debugging, but I'm not familiar with Carbon or IOKit at all (I'm primarily a PC guy) and so I'm hitting dead ends on alot of things.

As far as I'm able to determine, the problem lies with HID device events not making it through the DeviceValueReceived callback with the correct device id's and thus not reaching the state objects. There are events being fired through it, but the device id IntPtr's are not being matched in either the mouse or keyboard state dictionaries.

However, I added a Debug.Print line to pipe out the value, context and sender from within the DeviceValueReceived callback and noticed that the sender IntPtr was consistent with the pattern that I was using my plugged in USB mouse and the macbook's trackpad (moved the mouse for two seconds, moved the trackpad for two seconds, moved the mouse for two seconds, sender id's are grouped in that same pattern).

Trace Log. I've culled the repetitive lines and marked them as such in order to reduce the size of the log to a more readable size.

One other thing, is that I get an exception about a missing entry point for IOHIDDeviceUnscheduleWithRunLoop when I unplug my USB mouse. Exception Detail

Both of these things make me think that the version of IOKit that came pre-installed on this Macbook is quite different to the one that OpenTK was built against.

Anyone (Fiddler?) have any idea on how I can fix this? Does it look like a legitimate OpenTK bug?

If anyone needs more info I'm happy to provide.


Comments

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
Jase's picture

Okay, I think I've managed to find the problem, even though it doesn't make much sense to me.

During the OpenTK.Platform.MacOS.HIDInput.DeviceAdded callback, calls are made to IOHIDDeviceRegisterInputValueCallback in order to register the callback with IOKit to receive data from the device, it has a couple of parameters. The last parameter of that call is "context" according to the method signature. Currently, this is set to IntPtr.Zero. After finding some documentation on how Apple interfaces with the native method (Namely here, search for Handle_DeviceMatchingCallback), they are passing the device pointer into that last context parameter instead of a zero pointer.

So I followed their lead and did the same, then adjusted the callback to look up devices based on the context parameter instead of the device parameter and I now have mouse input working on my macbook.

DeviceValueReceived now looks like:

        void DeviceValueReceived(IntPtr ctx, IOReturn res, IntPtr sender, IOHIDValueRef val)
        {
            MouseState mouse;
            KeyboardState keyboard;
            if (MouseDevices.TryGetValue(ctx, out mouse))
            {
                MouseDevices[ctx] = UpdateMouse(mouse, val);
            }
            else if (KeyboardDevices.TryGetValue(ctx, out keyboard))
            {
                KeyboardDevices[ctx] = UpdateKeyboard(keyboard, val);
            }
        }

which is registered inside DeviceAdded by this line

NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, HandleDeviceValueReceived, device);

It looks weird indexing mice/keyboards by a contextid instead of deviceid, but since I repurposed the contextid parameter to hold the deviceid when registering the callback it works out.

However in my view this is only a temporary fix until someone who knows much more about IOKit can look at the problem. I have no idea if this solution will work on pre 10.7.2 macs or not.

Jase's picture

I sat down and decided to test the input issue more completely tonight and discovered that input does work, so long as you don't use the Keyboard.GetState() method since the HIDInput integration is broken in OpenTK on OSX 10.7. However, It processes window events just fine and at the moment, OpenTK jams the key events into the dummy devices it has inside OpenTK.Platform.MacOS.CarbonInput which are accessible inside GameWindow via InputDriver.Keyboard[0] and InputDriver.Mouse[0] (there is always 1 mouse and 1 keyboard, they're setup in the constructor of CarbonInput, so it's safe to use [0] even though normally it would be very bad).

I've moved my input routines across to using InputDriver.Keyboard and InputDriver.Mouse and it's working just fine on Windows and Mac, and will be sufficient until the problem can be resolved properly (I prefer the Keyboard.GetState() approach personally) because GameWindow.InputDriver has been marked as Obsolete.

Hope this helps someone.

AndyKorth's picture

Thanks for your help Jase, if you're still out there. I ended up using your solution in a fix here: http://www.opentk.com/node/3242