Skip to content

.focused modifier does not work unless used in DispatchQueue.main.async #205

Open
@kopyl

Description

@kopyl

Here is a sample code you can try:

import SwiftUI
import KeyboardShortcuts

let delegate = AppDelegate()

extension KeyboardShortcuts.Name {
    static let openTabsList = Self("openTabsList", default: .init(.tab, modifiers: [.option]))
}

KeyboardShortcuts.onKeyDown(for: .openTabsList) {
    print("Hi")
}

func isUserHoldingShortcutModifiers(event: NSEvent) -> Bool {
    guard let shortcut = KeyboardShortcuts.Name.openTabsList.shortcut else { return false }
    return event.modifierFlags.contains(shortcut.modifiers)
}

var greetingWindow: NSWindow?
var settingsWindow: NSWindow?

struct GreetingView: View {
    var body: some View {
        Text("Hi")
        .frame(width: 759, height: 781)
    }
}

struct SettingsView: View {
    @FocusState private var isFocused: Bool
    
    var body: some View {
        KeyboardShortcuts.Recorder(
            for: .openTabsList
        )
        .focused($isFocused)
        .onAppear {
            DispatchQueue.main.async {
                isFocused = true
            }
        }
        .padding()
    }
}

func showGreetingWindow() {
    if let greetingWindow {
        greetingWindow.makeKeyAndOrderFront(nil)
        return
    }
    greetingWindow = NSWindow(contentViewController: NSHostingController(rootView: GreetingView()))
    greetingWindow?.setContentSize(NSSize(width: 759, height: 781))
    greetingWindow?.center()
    greetingWindow?.makeKeyAndOrderFront(nil)
}

func showSettingsWindow() {
    if let settingsWindow {
        settingsWindow.makeKeyAndOrderFront(nil)
        return
    }
    settingsWindow = NSWindow(contentViewController: NSHostingController(rootView: SettingsView()))
    settingsWindow?.setContentSize(NSSize(width: 200, height: 100))
    settingsWindow?.center()
    settingsWindow?.makeKeyAndOrderFront(nil)
}

class AppDelegate: NSObject, NSApplicationDelegate {
    func applicationDidFinishLaunching(_ notification: Notification) {
        showGreetingWindow()
    }
}

class Application: NSApplication {
    private func createMenu() {
        self.mainMenu = NSMenu()

        let appMenuItem = NSMenuItem()
        self.mainMenu?.addItem(appMenuItem)
        let appMenu = NSMenu()
        appMenuItem.submenu = appMenu
        appMenu.addItem(NSMenuItem(title: "Quit \(ProcessInfo.processInfo.processName)",
           action: #selector(terminate(_:)),
           keyEquivalent: "q")
        )
        appMenu.addItem(NSMenuItem(title: "Settings",
           action: #selector(openSettingsWindow),
           keyEquivalent: ",")
        )

        let windowMenuItem = NSMenuItem()
        self.mainMenu?.addItem(windowMenuItem)
        let windowMenu = NSMenu(title: "Window")
        windowMenuItem.submenu = windowMenu
        windowMenu.addItem(NSMenuItem(title: "Close Window",
          action: #selector(NSWindow.performClose(_:)),
          keyEquivalent: "w")
        )
    }
    
    @objc func openSettingsWindow() {
        showSettingsWindow()
    }
    
    override init() {
        super.init()
        createMenu()
    }
    
    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}

let app = Application.shared
app.delegate = delegate

app.run()

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions