[Mac] Explicitly close removed devices
authorthefiddler <stapostol@gmail.com>
Wed, 23 Jul 2014 19:19:46 +0000 (21:19 +0200)
committerthefiddler <stapostol@gmail.com>
Wed, 23 Jul 2014 19:19:46 +0000 (21:19 +0200)
Devices are now explicitly closed when they a DeviceRemoved event is
received. Additionally, exceptions are no longer allowed to escape into
unmanaged code, where they might crash the runtime.

Source/OpenTK/Platform/MacOS/HIDInput.cs

index 4a31367..e2014c4 100755 (executable)
@@ -180,53 +180,61 @@ namespace OpenTK.Platform.MacOS
             IntPtr @event,
             IntPtr refcon)
         {
-            CursorState.SetIsConnected(true);
-
-            switch (type)
+            try
             {
-                case CGEventType.MouseMoved:
-                case CGEventType.LeftMouseDragged:
-                case CGEventType.RightMouseDragged:
-                case CGEventType.OtherMouseDragged:
-                    {
-                        Carbon.HIPoint p = CG.EventGetLocation(@event);
-                        CursorState.X = (int)Math.Round(p.X);
-                        CursorState.Y = (int)Math.Round(p.Y);
-                    }
-                    break;
+                CursorState.SetIsConnected(true);
 
-                case CGEventType.ScrollWheel:
-                    {
-                        // Note: OpenTK follows the win32 convention, where
-                        // (+h, +v) = (right, up). MacOS reports (+h, +v) = (left, up)
-                        // so we need to flip the horizontal scroll direction.
-                        double h = CG.EventGetDoubleValueField(@event, CGEventField.ScrollWheelEventPointDeltaAxis2) * MacOSFactory.ScrollFactor;
-                        double v = CG.EventGetDoubleValueField(@event, CGEventField.ScrollWheelEventPointDeltaAxis1) * MacOSFactory.ScrollFactor;
-                        CursorState.SetScrollRelative((float)(-h), (float)v);
-                    }
-                    break;
+                switch (type)
+                {
+                    case CGEventType.MouseMoved:
+                    case CGEventType.LeftMouseDragged:
+                    case CGEventType.RightMouseDragged:
+                    case CGEventType.OtherMouseDragged:
+                        {
+                            Carbon.HIPoint p = CG.EventGetLocation(@event);
+                            CursorState.X = (int)Math.Round(p.X);
+                            CursorState.Y = (int)Math.Round(p.Y);
+                        }
+                        break;
 
-                case CGEventType.LeftMouseDown:
-                case CGEventType.RightMouseDown:
-                case CGEventType.OtherMouseDown:
-                    {
-                        int n = CG.EventGetIntegerValueField(@event, CGEventField.MouseEventButtonNumber);
-                        n = n == 1 ? 2 : n == 2 ? 1 : n; // flip middle and right button numbers to match OpenTK
-                        MouseButton b = MouseButton.Left + n;
-                        CursorState[b] = true;
-                    }
-                    break;
+                    case CGEventType.ScrollWheel:
+                        {
+                            // Note: OpenTK follows the win32 convention, where
+                            // (+h, +v) = (right, up). MacOS reports (+h, +v) = (left, up)
+                            // so we need to flip the horizontal scroll direction.
+                            double h = CG.EventGetDoubleValueField(@event, CGEventField.ScrollWheelEventPointDeltaAxis2) * MacOSFactory.ScrollFactor;
+                            double v = CG.EventGetDoubleValueField(@event, CGEventField.ScrollWheelEventPointDeltaAxis1) * MacOSFactory.ScrollFactor;
+                            CursorState.SetScrollRelative((float)(-h), (float)v);
+                        }
+                        break;
 
-                case CGEventType.LeftMouseUp:
-                case CGEventType.RightMouseUp:
-                case CGEventType.OtherMouseUp:
-                    {
-                        int n = CG.EventGetIntegerValueField(@event, CGEventField.MouseEventButtonNumber);
-                        n = n == 1 ? 2 : n == 2 ? 1 : n; // flip middle and right button numbers to match OpenTK
-                        MouseButton b = MouseButton.Left + n;
-                        CursorState[b] = false;
-                    }
-                    break;
+                    case CGEventType.LeftMouseDown:
+                    case CGEventType.RightMouseDown:
+                    case CGEventType.OtherMouseDown:
+                        {
+                            int n = CG.EventGetIntegerValueField(@event, CGEventField.MouseEventButtonNumber);
+                            n = n == 1 ? 2 : n == 2 ? 1 : n; // flip middle and right button numbers to match OpenTK
+                            MouseButton b = MouseButton.Left + n;
+                            CursorState[b] = true;
+                        }
+                        break;
+
+                    case CGEventType.LeftMouseUp:
+                    case CGEventType.RightMouseUp:
+                    case CGEventType.OtherMouseUp:
+                        {
+                            int n = CG.EventGetIntegerValueField(@event, CGEventField.MouseEventButtonNumber);
+                            n = n == 1 ? 2 : n == 2 ? 1 : n; // flip middle and right button numbers to match OpenTK
+                            MouseButton b = MouseButton.Left + n;
+                            CursorState[b] = false;
+                        }
+                        break;
+                }
+            }
+            catch (Exception e)
+            {
+                // Do not let any exceptions escape into unmanaged code!
+                Debug.Print(e.ToString());
             }
 
             return @event;
@@ -336,6 +344,7 @@ namespace OpenTK.Platform.MacOS
                 {
                     NativeMethods.IOHIDDeviceRegisterInputValueCallback(device, IntPtr.Zero, IntPtr.Zero);
                     NativeMethods.IOHIDDeviceUnscheduleFromRunLoop(device, RunLoop, InputLoopMode);
+                    NativeMethods.IOHIDDeviceClose(device, IOOptionBits.Zero);
                 }
             }
             catch (Exception e)
@@ -1093,7 +1102,7 @@ namespace OpenTK.Platform.MacOS
             [DllImport(hid)]
             public static extern void IOHIDManagerSetDeviceMatching(
                 IOHIDManagerRef manager,
-                CFDictionaryRef matching) ;
+                CFDictionaryRef matching);
 
             [DllImport(hid)]
             public static extern IOReturn IOHIDManagerOpen(
@@ -1106,6 +1115,11 @@ namespace OpenTK.Platform.MacOS
                 IOOptionBits opts);
 
             [DllImport(hid)]
+            public static extern IOReturn IOHIDDeviceClose(
+                IOHIDDeviceRef device,
+                IOOptionBits options);
+
+            [DllImport(hid)]
             public static extern CFTypeRef IOHIDDeviceGetProperty(
                 IOHIDDeviceRef device,
                 CFStringRef key);