Skip to content

Instantly share code, notes, and snippets.

@niw
Created January 4, 2013 08:39
Show Gist options
  • Select an option

  • Save niw/4450946 to your computer and use it in GitHub Desktop.

Select an option

Save niw/4450946 to your computer and use it in GitHub Desktop.

Revisions

  1. niw created this gist Jan 4, 2013.
    102 changes: 102 additions & 0 deletions FastKeyRepeat.m
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,102 @@
    #import <PreferencePanes/PreferencePanes.h>
    #import <objc/message.h>

    void exchangeInstanceMethodImplementations(NSString *className, SEL originlSelector, SEL replacementSelector)
    {
    Class class = NSClassFromString(className);
    if(class) {
    Method originalMethod = class_getInstanceMethod(class, originlSelector);
    Method replacementMethod = class_getInstanceMethod(class, replacementSelector);
    method_exchangeImplementations(originalMethod, replacementMethod);
    }
    }

    id getInstanceVariable(id object, NSString *ivarName)
    {
    Ivar ivar = class_getInstanceVariable([object class], [ivarName UTF8String]);
    if(ivar) {
    return object_getIvar(object, ivar);
    } else {
    return nil;
    }
    }

    @interface FastKeyRepeat : NSPreferencePane
    - (void)mainViewDidLoad;
    @end

    @interface NSPrefPanesCenter : NSObject
    + (id)sharedPreferencesCenter;
    - (id)prefPaneBundleWithIdentifier:(id)arg1;
    @end

    @interface NSPrefPaneBundle : NSObject
    - (NSPreferencePane *)prefPaneObject;
    - (BOOL)instantiatePrefPaneObject;
    - (id)identifier;
    @end

    @implementation NSPrefPaneBundle(FastKeyRepeat)
    - (NSMutableDictionary *)prefPanesCache
    {
    Class NSPrefPanesManager = NSClassFromString(@"NSPrefPanesManager");
    id manager = [NSPrefPanesManager performSelector:@selector(prefPanesManager)];
    return (NSMutableDictionary *)getInstanceVariable(manager, @"_ppInstanceCache");
    }

    - (BOOL)instantiatePrefPaneObjectAndCache
    {
    if([self instantiatePrefPaneObject]) {
    NSPreferencePane *pane = [self prefPaneObject];
    NSString *identifier = [self identifier];

    NSMutableDictionary *cache = [self prefPanesCache];
    [cache setObject:pane forKey:identifier];

    return YES;
    } else {
    return NO;
    }
    }
    @end

    @implementation NSObject(FastKeyRepeat)
    - (void)fast_key_repeat_willSelect
    {
    NSSlider *repeatRateSlider = (NSSlider *)getInstanceVariable(self, @"_repeatRateSlider");
    NSSlider *repeatDelaySlider = (NSSlider *)getInstanceVariable(self, @"_repeatDelaySlider");

    repeatRateSlider.maxValue = 7 + 1;
    repeatRateSlider.numberOfTickMarks = 8 + 1;

    repeatDelaySlider.maxValue = 6 + 1;
    repeatDelaySlider.numberOfTickMarks = 6 + 1;

    [self fast_key_repeat_willSelect];
    }
    @end

    @implementation FastKeyRepeat
    - (NSPrefPaneBundle *)keyboardPreferencePaneBundle
    {
    return [[NSPrefPanesCenter sharedPreferencesCenter] prefPaneBundleWithIdentifier:@"com.apple.preference.keyboard"];
    }

    - (void)mainViewDidLoad
    {
    NSPrefPaneBundle *keyboardPaneBundle = [self keyboardPreferencePaneBundle];
    if([keyboardPaneBundle instantiatePrefPaneObjectAndCache]) {
    exchangeInstanceMethodImplementations(@"KeyboardTabController",
    @selector(willSelect),
    @selector(fast_key_repeat_willSelect));
    }
    }

    - (void)didSelect
    {
    NSPrefPaneBundle *keyboardPaneBundle = [self keyboardPreferencePaneBundle];
    Class NSPrefPanesManager = NSClassFromString(@"NSPrefPanesManager");
    id manager = [NSPrefPanesManager performSelector:@selector(prefPanesManager)];
    [manager performSelector:@selector(setCurrentPreference:) withObject:keyboardPaneBundle];
    }
    @end