objective-cmacosmacos-catalinamacos-big-surdictation

MacOS (OSX) Dictation - Is there a way to read the shortcut keys assigned to dictation feature in Mac? or programmatically start dictation?


I want to enable dictation on any keyboard key press.

Currently I am using AppleScript to click on Menu->Edit->Start Dictation of front most app. This script requires Automation permissions and I am hesitating to create app with so many permissions.

Is there a way to get the shortcut keys assigned to Dictation feature?

Goal is to:

  1. Read shortcut keys from preference file
  2. Fire those keys from app (CGEVENTPOST)

Solution

  • I ended up implementing myself. Captured changes made to Preferences folder after modifying any Keyboard setting.

    Came across a file called com.apple.symbolichotkeys.plist which changed when any shortcuts were modified.

    Here is sample code implemented to enable dictation programmatically (Hope my code is self explanatory)

    #include <Carbon/Carbon.h>
    
    [self enableDication];
    
    -(void) enableDication
    {
        int press_count = 2;
    
        NSString *pathSymbHotKeys = @"~/Library/Preferences/com.apple.symbolichotkeys.plist";
        NSMutableDictionary *symbolicHotKeysDict = [[NSMutableDictionary alloc]initWithContentsOfFile:pathSymbHotKeys.stringByExpandingTildeInPath];
        
        NSNumber *enabled = symbolicHotKeysDict[@"AppleSymbolicHotKeys"][@"164"][@"enabled"] ;
        if (![enabled boolValue]) {
            NSLog(@"Dication shortcut not enabled");
            return;
        }
        
        NSString *type = symbolicHotKeysDict[@"AppleSymbolicHotKeys"][@"164"][@"value"][@"type"];
        
        NSNumber *param_key_code  = nil;
        NSNumber *param_mask = nil;
        
        if ([type isEqualToString:@"standard"]) {
            //mask
            param_mask = symbolicHotKeysDict[@"AppleSymbolicHotKeys"][@"164"][@"value"][@"parameters"][2];
            param_key_code = symbolicHotKeysDict[@"AppleSymbolicHotKeys"][@"164"][@"value"][@"parameters"][1];
            press_count = 1;
        }
        else {
            param_key_code = symbolicHotKeysDict[@"AppleSymbolicHotKeys"][@"164"][@"value"][@"parameters"][0];
        }
    
        CGEventRef fnDown = CGEventCreateKeyboardEvent(NULL, [self keyCode:param_key_code type:type], true);
        if ([type isEqualToString:@"standard"]) {
            CGEventSetFlags(fnDown, (CGEventFlags)([param_mask intValue] | CGEventGetFlags(fnDown)));
        }
    
        CGEventRef fnUp   = CGEventCreateKeyboardEvent(NULL, [self keyCode:param_key_code type:type], false);
        if ([type isEqualToString:@"standard"]) {
            CGEventSetFlags(fnUp, (CGEventFlags)([param_mask intValue]));
        }
        
        for (int i = 0; i <press_count; i++)
        {
            CGEventPost(kCGSessionEventTap, fnDown);
            CGEventPost(kCGSessionEventTap, fnUp);
        }
    
        CFRelease (fnDown);
        CFRelease (fnUp);
    }
    
    
    -(CGKeyCode) keyCode:(NSNumber *)code type:(NSString *)type
    {
        if ([type isEqualToString:@"standard"]) {
            return (CGKeyCode)[code longValue];
        }
        else{
            //Default Modifier shortcuts provided by Mac for dictation
            if (([code longValue] & 0x00100008) == 0x00100008) {
                //Left command key
                return kVK_Command;
            }
            else if (([code longValue] & 0x00100010) == 0x00100010) {
                // right command key
                return kVK_RightCommand;
            }
            else if (([code longValue] & kCGEventFlagMaskCommand) == kCGEventFlagMaskCommand) {
                //any command key
                return kVK_Command;
            }
            else if (([code longValue] & NSEventModifierFlagFunction) == NSEventModifierFlagFunction)
            {
                //function key
                return kVK_Function;
            }
            else if (([code longValue] & kCGEventFlagMaskControl) == kCGEventFlagMaskControl)
            {
                //control key
                return kVK_Control;
            }
        }
        return -1;
    }