1

Is it possible to find out if a Mac is Force Touch capable - either via a built-in Trackpad, like the new MacBook, or a Bluetooth device like the Magic Trackpad 2?

I'd like to present preferences specific to Force Touch if the Mac is Force Touch capable, but not display (or disable) those preferences if Force Touch is not available.

In the portion after the separator, you see the options I have in mind in the pic linked here. (sorry, embedding the pic itself didn't work).

preferences

So, not showing the preferences wouldn't restrict users who don't have force touch, it would just let users who have it configure how it should work, and those settings would be useless to users who don't have it.

Is there a way to achieve this?

Thank you and kind regards, Matt

Edit: It's in Objective-C.

4

1 に答える 1

0

私はそれを考え出した:

+ (BOOL)isForceTouchCapable
{
    if (![[self class] isAtLeastElCapitan])
        return NO;

    io_iterator_t iterator;

    //get default HIDDevice dictionary
    CFMutableDictionaryRef mDict = IOServiceMatching(kIOHIDDeviceKey);

    //add manufacturer "Apple Inc." to dict
    CFDictionaryAddValue(mDict, CFSTR(kIOHIDManufacturerKey), CFSTR("Apple Inc."));

    //get matching services, depending on dict
    IOReturn ioReturnValue = IOServiceGetMatchingServices(kIOMasterPortDefault, mDict, &iterator);

    BOOL result = YES;
    if (ioReturnValue != kIOReturnSuccess)
        NSLog(@"error getting matching services for force touch devices");
    else
    {
        //recursively go through each device found and its children and grandchildren, etc.
        result = [[self class] _containsForceTouchDevice:iterator];
        IOObjectRelease(iterator);
    }

    return result;
}

+ (BOOL)_containsForceTouchDevice:(io_iterator_t)iterator
{
    io_object_t object = 0;
    BOOL success = NO;
    while ((object = IOIteratorNext(iterator)))
    {
        CFMutableDictionaryRef result = NULL;
        kern_return_t state = IORegistryEntryCreateCFProperties(object, &result, kCFAllocatorDefault, 0);
        if (state == KERN_SUCCESS && result != NULL)
        {
            if (CFDictionaryContainsKey(result, CFSTR("DefaultMultitouchProperties")))
            {
                CFDictionaryRef dict = CFDictionaryGetValue(result, CFSTR("DefaultMultitouchProperties"));
                CFTypeRef val = NULL;
                if (CFDictionaryGetValueIfPresent(dict, CFSTR("ForceSupported"), &val))
                {
                    Boolean aBool = CFBooleanGetValue(val);
                    if (aBool) //supported
                        success = YES;
                }
            }
        }

        if (result != NULL)
            CFRelease(result);

        if (success)
        {
            IOObjectRelease(object);
            break;
        } else
        {
            io_iterator_t childIterator = 0;
            kern_return_t err = IORegistryEntryGetChildIterator(object, kIOServicePlane, &childIterator);
            if (!err)
            {
                success = [[self class] _containsForceTouchDevice:childIterator];
                IOObjectRelease(childIterator);
            } else
                success = NO;

            IOObjectRelease(object);
        }
    }

    return success;
}

+ (BOOL)isForceTouchCapable を呼び出すだけで、Force Touch デバイス (Magic Trackpad 2 または組み込みの force-touch-trackpad) が使用可能な場合は YES が返され、使用できない場合は NO が返されます。

これがどのようになったのかに興味がある人のために、私のブログでサンプル プロジェクトを書いています。

于 2015-11-16T11:20:15.860 に答える