Hook Keyboard

Discussion in 'Mac Programming' started by Sergio10, Jun 16, 2010.

  1. Sergio10 macrumors regular

    Joined:
    Oct 3, 2007
    #1
    Hi,

    I've developed application as agent which placed in status bar(near clock).

    1. Is it possible to handle hot keys(e.g. when user press: Mac + G) out of application?
    2. Is it possible to handle text selecting in some text editor etc. when my app is running?

    Thanks
     
  2. mrbash macrumors 6502

    Joined:
    Aug 10, 2008
    #2
    It may be possible with a kernel extension. You would have to over-write the HID driver or wrap something around an existing one.
     
  3. Sergio10 thread starter macrumors regular

    Joined:
    Oct 3, 2007
    #3
    Could you please provide me some url with more detailed info?

    Thank you.
     
  4. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #4
    I'm pretty sure you can do this without writing a kernel extension, by making use of the "Enable access for assistive devices" in Univeral Access.

    Several applications tell you to check that off, then allow you to map key combos to applications that are not the first responder.
     
  5. mrbash macrumors 6502

    Joined:
    Aug 10, 2008
    #5
    Here is a site I found via GOOGLE. Just a reminder that Goolge is useful for finding information
     
  6. Sergio10 thread starter macrumors regular

    Joined:
    Oct 3, 2007
    #6
    jared_kipe, it's very interesting.
    I've turned on "Enable access for assistive devices" option but when run my application and press hot key combination nothing heppens.

    Could you please explain how to fix it or provide some simple example?

    Thank you very much.
     
  7. jared_kipe macrumors 68030

    jared_kipe

    Joined:
    Dec 8, 2003
    Location:
    Seattle
    #7
    Its not magic, you can't just check off the box and expect it to start working in your application. Otherwise... every application would suddenly get key commands when they are not the first responder and it would get really confusing really fast.

    I'm not going to "explain how to fix it" because you need to look into it yourself. I don't know how to do it, and I'm not going to learn how to just so I can "provide some simple example."

    I would suspect that there is something like the NSNotification that you can register to receive these special key combos on, probably has something to do with the checkbox I described earlier.
     
  8. Sergio10 thread starter macrumors regular

    Joined:
    Oct 3, 2007
    #8
    Guys,

    According to the guide I've developed a simple application which should track all keyboard events: http://slil.ru/29371847
    But it doesn't work:confused:
    Could you please help with fixing the issue?

    Here is a code:
    PHP:
    @implementation MyApplication


    static OSStatus MonitorHandler(EventHandlerCallRef nextHandlerEventRef theEventvoid inRefcon)
    {
        
    // Useless on 10.4 for keyboard events. If you requested to watch other events
        // (mouse or tablet events for example) they would into funnel to here.
        
        
    NSLog(@"it's working!!!!\n");
        
        return 
    CallNextEventHandler(nextHandlertheEvent);
    }

    - (
    void)installMonitorHandler;
    {
        
    OSStatus error noErr;
        
    EventTypeSpec    kEvents[] =
        {
            { 
    kEventClassKeyboardkEventRawKeyDown },
            { 
    kEventClassKeyboardkEventRawKeyUp }
        };
        
        
    // the magic happens here with the call to GetEventMonitorTarget as described in CarbonEvents.h
        // The event monitor target is a special event target used to monitor user input events across all processes.
        // When the monitor target detects a matching event, then MonitorHandler is called.
        
    error InstallEventHandlerGetEventMonitorTarget(), MonitorHandlerGetEventTypeCountkEvents ),
                                    
    kEventsNULL, &mMonitorHandlerRef );
        if (
    error != noErr) {
            
    NSBeep();
            
    NSLog(@"InstallEventHandler error %d"error);
        }
    }


    - (
    void)uninstallMonitorHandler;
    {
        if (
    mMonitorHandlerRef) {
            
    RemoveEventHandler(mMonitorHandlerRef);
            
    mMonitorHandlerRef NULL;
        }
    }


    - (
    void)sendEvent:(NSEvent *)event;
    {
        
    NSEventType eventType = [event type];
        
        
    // Catch keyboard events destined for other apps when recording
        
    if (![self isActive] && (eventType == NSKeyDown || eventType == NSKeyUp || eventType == NSFlagsChanged)) {
            
    NSLog(@"sendEvent: interior");
            return;
        }
        
        [
    super sendEvent:event];
    }
    PHP:
    @implementation MyApplicationAppDelegate

    @synthesize window;

    - (
    void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        
        
    // Insert code here to initialize your application     
        
    MyApplication *app = [[MyApplication allocinit];
        [
    app installMonitorHandler];
    }

    @
    end
    Thank you very much
     
  9. whooleytoo macrumors 603

    whooleytoo

    Joined:
    Aug 2, 2002
    Location:
    Cork, Ireland.
    #9
    The comment "// Useless on 10.4 for keyboard events." would seem to suggest it won't work for keyboard events (depending on whether they mean "10.4 and later" or "10.4 and earlier". ;)

    Some time ago, I used the following page which describes a Carbon solution. It might not be recommended (or work at all) on recent OS releases, but it might help you.

    Global hotkeys
     
  10. Sergio10 thread starter macrumors regular

    Joined:
    Oct 3, 2007
    #10
    Also I've tried this code sample you provided. But it doesn't work as well:confused:

    Here is my project: http://slil.ru/29376587
    My app is as agent.

    PHP:
    - (void)activateStatusMenu
    {
        
    NSStatusBar *statusBar = [NSStatusBar systemStatusBar];
        
        
    NSStatusItem *dictItem = [statusBar statusItemWithLength:NSVariableStatusItemLength];
        [
    dictItem retain];
        
        [
    dictItem setTitleNSLocalizedString(@"Dictionary",@"")];
        [
    dictItem setHighlightMode:YES];
        [
    dictItem setMenu:menu];
        
    }

    - (
    IBAction)onAutostartup:(id)sender {

        exit(
    0);
    }

    OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEventvoid *userData)
    {
        
    NSLog(@"it works...\n");
        
        
    //Do something once the key is pressed
        
    return noErr;
    }

    - (
    void)applicationDidFinishLaunching:(NSNotification *)aNotification {

        
    //Register the Hotkeys
        
    EventHotKeyRef gMyHotKeyRef;
        
    EventHotKeyID gMyHotKeyID;
        
    EventTypeSpec eventType;
        
    eventType.eventClass=kEventClassKeyboard;
        
    eventType.eventKind=kEventHotKeyPressed;

        
    InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,NULL,NULL);
        
        
    gMyHotKeyID.signature='htk1';
        
    gMyHotKeyID.id=1;
        
    RegisterEventHotKey(49cmdKey+optionKeygMyHotKeyIDGetApplicationEventTarget(), 0, &gMyHotKeyRef);        
        
        
    // Insert code here to initialize your application
        
    [self activateStatusMenu];
    }
    Please help with this issue.

    Thank you.
     
  11. Sergio10 thread starter macrumors regular

    Joined:
    Oct 3, 2007
    #12
    Yes, I've researched this point but didn't found an example.(

    Could you please help me with the code I've already developed?
     
  12. Sergio10 thread starter macrumors regular

    Joined:
    Oct 3, 2007
    #13
    Update:

    I've fixed the code. Now it's working. But have a few questions:

    1. I'm hooking command + "C" (copy to clipboard). It works just fine but it is not coping data to the buffer after my hooking(( Even I send noErr in MyHotKeyHandler() function. How to fix this problem?
    According to this topic(http://groups.jonzu.com/z_apple_how-can-i-not-block-hotkey-from-other-apps.html) I do it in next way:
    PHP:
    OSStatus MyHotKeyHandler(EventHandlerCallRef nextHandler,EventRef theEventvoid *userData)
    {
        
    NSLog(@"it works...\n");
        
    UnregisterEventHotKey(gMyHotKeyRef);
        
    SendEventToEventTarget(theEventeventTargetRef);
        return 
    noErr;
    }

    - (
    void)applicationDidFinishLaunching:(NSNotification *)aNotification {

        
    //Register the Hotkey
        
    EventHotKeyID gMyHotKeyID;
        
    EventTypeSpec eventType;
        
    eventType.eventClass kEventClassKeyboard;
        
    eventType.eventKind kEventHotKeyPressed;

        
    InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,NULL,NULL);
        
        
    gMyHotKeyID.signature 'htk1';
        
    gMyHotKeyID.id 1;
        
        
    eventTargetRef GetApplicationEventTarget();
        
    RegisterEventHotKey(8cmdKeygMyHotKeyIDeventTargetRef0, &gMyHotKeyRef);    
        
        
    // Insert code here to initialize your application
        
    [self activateStatusMenu];
    }
    2. Also I need to hook double click. Current code doesn't do it:
    PHP:
        EventTypeSpec eventType;
        
    eventType.eventClass kEventClassMouse;
        
    eventType.eventKind kEventMouseDown;
        
        
    InstallApplicationEventHandler(&MyHotKeyHandler,1,&eventType,NULL,NULL);
    Where is the problem?

    Thanks.
     
  13. Sergio10 thread starter macrumors regular

    Joined:
    Oct 3, 2007

Share This Page