2015-02-02 5 views
33

Próbuję mieć program obsługi w mojej aplikacji Mac OS X napisany w języku Swift dla globalnego (ogólnosystemowego) zestawu klawiszy skrótu, ale po prostu nie mogę znaleźć odpowiedniej dokumentacji dla niego. Czytałem, że musiałbym się z tym pogodzić w jakimś legendarnym Carbon API, czy nie ma lepszego sposobu? Czy możesz pokazać mi jakiś dowód koncepcji kodu Swift? Z góry dziękuję!Jak słuchać globalnych skrótów klawiszowych za pomocą Swift w aplikacji OS X?

+0

Co dokładnie wypróbowałeś? Co masz na myśli przez klawisze skrótów? Czy wypróbowałeś globalny monitor NSEvent lub CGEventTap – uchuugaka

Odpowiedz

10

Od Swift 2.0 można teraz przekazać wskaźnik funkcji do API C.

var gMyHotKeyID = EventHotKeyID() 
    gMyHotKeyID.signature = OSType("swat".fourCharCodeValue) 
    gMyHotKeyID.id = UInt32(keyCode) 

    var eventType = EventTypeSpec() 
    eventType.eventClass = OSType(kEventClassKeyboard) 
    eventType.eventKind = OSType(kEventHotKeyPressed) 

    // Install handler. 
    InstallEventHandler(GetApplicationEventTarget(), {(nextHanlder, theEvent, userData) -> OSStatus in 
      var hkCom = EventHotKeyID() 
      GetEventParameter(theEvent, EventParamName(kEventParamDirectObject), EventParamType(typeEventHotKeyID), nil, sizeof(EventHotKeyID), nil, &hkCom) 

      /// Check that hkCom in indeed your hotkey ID and handle it. 
     }, 1, &eventType, nil, nil) 

    // Register hotkey. 
    let status = RegisterEventHotKey(UInt32(keyCode), UInt32(modifierKeys), gMyHotKeyID, GetApplicationEventTarget(), 0, &hotKeyRef) 
+0

Nie działa w 'Swift 4' i bez bardziej szczegółowego wyjaśnienia nie można go zrealizować. – ixany

+0

Działa dobrze w Swift 4, przekonwertowałem swoje projekty na Swift 4 i działa dobrze. Jako programista powinieneś wiedzieć, że "nie działa" to najgorszy możliwy opis problemu - co oznacza "nie działa"? Nie kompiluje? Jaki błąd kompilacji dostałeś? Naprawdę nie ma wiele do wyjaśnienia - każda z użytych funkcji jest udokumentowana przez Apple. –

+0

Tylko dobre wibracje, Charlie! Byłoby wspaniale, gdybyś mógł również udostępnić swoje rozwiązanie Swift 4. Opublikowane rozwiązanie jest niekompletne, co utrudnia początkującym adaptację. Jedną rzeczą, która może być pomocna, jest to, że import "węgla" jest konieczny. Następnym problemem, z którym miałem do czynienia jest to, że 'String' nie ma właściwości' .fourCharCodeValue'. Również byłoby wspaniale, gdybyś mógł podać przykład dla 'keyCode' i' modifierKeys'. – ixany

10

Nie wierzę, że możesz zrobić to w 100% Swift już dziś. Będziesz musiał zadzwonić pod numer InstallEventHandler() lub CGEventTapCreate(), a oba te wymagają numeru CFunctionPointer, którego nie można utworzyć w Swift. Twoim najlepszym pomysłem jest użycie sprawdzonych rozwiązań ObjC, takich jak DDHotKey i przejście do Swift.

Możesz spróbować użyć NSEvent.addGlobalMonitorForEventsMatchingMask(handler:), ale to tylko tworzy kopie wydarzeń. Nie możesz ich konsumować. Oznacza to, że skrót będzie również przekazywany do aktualnie aktywnej aplikacji, co może powodować problemy. Oto przykład, ale polecam podejście ObjC; prawie na pewno będzie lepiej.

let keycode = UInt16(kVK_ANSI_X) 
let keymask: NSEventModifierFlags = .CommandKeyMask | .AlternateKeyMask | .ControlKeyMask 

func handler(event: NSEvent!) { 
    if event.keyCode == self.keycode && 
     event.modifierFlags & self.keymask == self.keymask { 
      println("PRESSED") 
    } 
} 

// ... to set it up ... 
    let options = NSDictionary(object: kCFBooleanTrue, forKey: kAXTrustedCheckOptionPrompt.takeUnretainedValue() as NSString) as CFDictionaryRef 
    let trusted = AXIsProcessTrustedWithOptions(options) 
    if (trusted) { 
     NSEvent.addGlobalMonitorForEventsMatchingMask(.KeyDownMask, handler: self.handler) 
    } 

Wymaga to również zatwierdzenia usług dostępności dla tej aplikacji. Nie przechwytuje również zdarzeń, które są wysyłane do Twojej aplikacji, więc musisz je przechwycić łańcuchem odpowiadającym, naszemu użyciu addLocalMointorForEventsMatchingMask(handler:), aby dodać lokalny handler.

+0

Chociaż jest to użyteczne, ważne jest, aby pamiętać, że użytkownik przyznaje Twojej aplikacji możliwość monitorowania każdego pojedynczego uderzenia klucza, co jest potencjalnie niebezpieczne, zwłaszcza, jeśli twoja aplikacja nie jest piaskownica i może zostać wstrzyknięta . Stary Carbon API zrobi to tylko dla kombinacji zdefiniowanych przez użytkownika, czyniąc je "bezpieczniejszym" rozwiązaniem. –

6

Szybkie Swift 3 aktualizacja dla konfiguracji:

let opts = NSDictionary(object: kCFBooleanTrue, forKey: kAXTrustedCheckOptionPrompt.takeUnretainedValue() as NSString) as CFDictionary 

    guard AXIsProcessTrustedWithOptions(opts) == true else { return } 

    NSEvent.addGlobalMonitorForEvents(matching: .keyDown, handler: self.handler) 
+0

Uwaga: Oparty na węglu interfejs API klawiszy skrótu nie wymaga uprawnień dostępu (nie może być w sklepie Mac App Store), chociaż jest to z pewnością łatwiejsze do wdrożenia. – ctietze

+0

Istnieją aplikacje takie jak CopyLess 2, które nasłuchują na keyDown i nie wymagają dostępu, czy wiesz coś o nich? Może aplikacje ze sklepu nie wymagają tego? –

0

Spójrz w Bibliotece skrótu klawiaturowego. Możesz po prostu użyć Kartaginy, aby zaimplementować ją w swojej własnej aplikacji. HotKey Library

Powiązane problemy