Vision Keyboard Kit



  • Full sized (104-keys) or 60% (no arrow/num keys) mode
  • Support for multiple keyboard layouts
  • PS/2 Set 1 scan code generation
  • Multiple instances with independent event handlers
  • Key down and key up events


Declare KeyboardWindowGroup in your Scene:

import SwiftUI
import VisionKeyboardKit

struct YourApp: App {
    var body: some Scene {
        WindowGroup {

Open/close the keyboard window using OpenWindowAction/DismissWindowAction and receive events through KeyboardEvent.publisher(for:):

import SwiftUI
import VisionKeyboardKit

struct ContentView: View {
    @Environment(\.openWindow) private var openWindow
    @Environment(\.dismissWindow) private var dismissWindow
    @State private var isKeyboardShown: Bool = false

    var body: some View {
        Button {
            if !isKeyboardShown {
                openWindow(keyboardFor: .global)
            } else {
                dismissWindow(keyboardFor: .global)
        } label: {
            Text("Toggle Keyboard")
        }.onReceive(KeyboardEvent.publisher(for: .global)) { event in
            if case .keyboardDidAppear = event {
                isKeyboardShown = true
            } else if case .keyboardDidDisappear = event {
                isKeyboardShown = false
            } else {
                print("Got event: \(event)")

If you need more than one keyboard with independent event publishers, just pass in any Hashable which serves as an identifier for the keyboard.

The returned Publisher can be used in the Combine framework for chained processing (such as debounce).


View Github