Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added conditional imports for macOS in multiple files #138

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/CarbonKeyboardShortcuts.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
import Carbon.HIToolbox

private func carbonKeyboardShortcutsEventHandler(eventHandlerCall: EventHandlerCallRef?, event: EventRef?, userData: UnsafeMutableRawPointer?) -> OSStatus {
Expand Down Expand Up @@ -345,3 +346,4 @@
}
}
}
#endif

Check warning on line 349 in Sources/KeyboardShortcuts/CarbonKeyboardShortcuts.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/Key.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
import Carbon.HIToolbox

extension KeyboardShortcuts {
Expand Down Expand Up @@ -192,3 +193,4 @@
*/
var isFunctionKey: Bool { Self.functionKeys.contains(self) }
}
#endif

Check warning on line 196 in Sources/KeyboardShortcuts/Key.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/KeyboardShortcuts.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
import AppKit.NSMenu

/**
Expand Down Expand Up @@ -589,3 +590,4 @@
extension Notification.Name {
static let shortcutByNameDidChange = Self("KeyboardShortcuts_shortcutByNameDidChange")
}
#endif

Check warning on line 593 in Sources/KeyboardShortcuts/KeyboardShortcuts.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)
156 changes: 79 additions & 77 deletions Sources/KeyboardShortcuts/NSMenuItem++.swift
Original file line number Diff line number Diff line change
@@ -1,109 +1,111 @@
import AppKit
#if os(macOS)
import AppKit

extension NSMenuItem {
private enum AssociatedKeys {
static let observer = ObjectAssociation<NSObjectProtocol>()
}

private func clearShortcut() {
keyEquivalent = ""
keyEquivalentModifierMask = []

if #available(macOS 12, *) {
allowsAutomaticKeyEquivalentLocalization = true
extension NSMenuItem {
private enum AssociatedKeys {
static let observer = ObjectAssociation<NSObjectProtocol>()
}
}

// TODO: Make this a getter/setter. We must first add the ability to create a `Shortcut` from a `keyEquivalent`.
/**
Show a recorded keyboard shortcut in a `NSMenuItem`.
private func clearShortcut() {
keyEquivalent = ""
keyEquivalentModifierMask = []

The menu item will automatically be kept up to date with changes to the keyboard shortcut.

Pass in `nil` to clear the keyboard shortcut.
if #available(macOS 12, *) {
allowsAutomaticKeyEquivalentLocalization = true
}
}

This method overrides `.keyEquivalent` and `.keyEquivalentModifierMask`.
// TODO: Make this a getter/setter. We must first add the ability to create a `Shortcut` from a `keyEquivalent`.
/**
Show a recorded keyboard shortcut in a `NSMenuItem`.

```swift
import Cocoa
import KeyboardShortcuts
The menu item will automatically be kept up to date with changes to the keyboard shortcut.

extension KeyboardShortcuts.Name {
static let toggleUnicornMode = Self("toggleUnicornMode")
}
Pass in `nil` to clear the keyboard shortcut.

// … `Recorder` logic for recording the keyboard shortcut …
This method overrides `.keyEquivalent` and `.keyEquivalentModifierMask`.

let menuItem = NSMenuItem()
menuItem.title = "Toggle Unicorn Mode"
menuItem.setShortcut(for: .toggleUnicornMode)
```
```swift
import Cocoa
import KeyboardShortcuts

You can test this method in the example project. Run it, record a shortcut and then look at the “Test” menu in the app's main menu.
extension KeyboardShortcuts.Name {
static let toggleUnicornMode = Self("toggleUnicornMode")
}

- Important: You will have to disable the global keyboard shortcut while the menu is open, as otherwise, the keyboard events will be buffered up and triggered when the menu closes. This is because `NSMenu` puts the thread in tracking-mode, which prevents the keyboard events from being received. You can listen to whether a menu is open by implementing `NSMenuDelegate#menuWillOpen` and `NSMenuDelegate#menuDidClose`. You then use `KeyboardShortcuts.disable` and `KeyboardShortcuts.enable`.
*/
public func setShortcut(for name: KeyboardShortcuts.Name?) {
guard let name else {
clearShortcut()
AssociatedKeys.observer[self] = nil
return
}
// … `Recorder` logic for recording the keyboard shortcut …

func set() {
let shortcut = KeyboardShortcuts.Shortcut(name: name)
setShortcut(shortcut)
}
let menuItem = NSMenuItem()
menuItem.title = "Toggle Unicorn Mode"
menuItem.setShortcut(for: .toggleUnicornMode)
```

set()
You can test this method in the example project. Run it, record a shortcut and then look at the “Test” menu in the app's main menu.

// TODO: Use AsyncStream when targeting macOS 10.15.
AssociatedKeys.observer[self] = NotificationCenter.default.addObserver(forName: .shortcutByNameDidChange, object: nil, queue: nil) { notification in
guard
let nameInNotification = notification.userInfo?["name"] as? KeyboardShortcuts.Name,
nameInNotification == name
else {
- Important: You will have to disable the global keyboard shortcut while the menu is open, as otherwise, the keyboard events will be buffered up and triggered when the menu closes. This is because `NSMenu` puts the thread in tracking-mode, which prevents the keyboard events from being received. You can listen to whether a menu is open by implementing `NSMenuDelegate#menuWillOpen` and `NSMenuDelegate#menuDidClose`. You then use `KeyboardShortcuts.disable` and `KeyboardShortcuts.enable`.
*/
public func setShortcut(for name: KeyboardShortcuts.Name?) {
guard let name else {
clearShortcut()
AssociatedKeys.observer[self] = nil
return
}

func set() {
let shortcut = KeyboardShortcuts.Shortcut(name: name)
setShortcut(shortcut)
}

set()

// TODO: Use AsyncStream when targeting macOS 10.15.
AssociatedKeys.observer[self] = NotificationCenter.default.addObserver(forName: .shortcutByNameDidChange, object: nil, queue: nil) { notification in
guard
let nameInNotification = notification.userInfo?["name"] as? KeyboardShortcuts.Name,
nameInNotification == name
else {
return
}

set()
}
}
}

/**
Add a keyboard shortcut to a `NSMenuItem`.
/**
Add a keyboard shortcut to a `NSMenuItem`.

This method is only recommended for dynamic shortcuts. In general, it's preferred to create a static shortcut name and use `NSMenuItem.setShortcut(for:)` instead.
This method is only recommended for dynamic shortcuts. In general, it's preferred to create a static shortcut name and use `NSMenuItem.setShortcut(for:)` instead.

Pass in `nil` to clear the keyboard shortcut.
Pass in `nil` to clear the keyboard shortcut.

This method overrides `.keyEquivalent` and `.keyEquivalentModifierMask`.
This method overrides `.keyEquivalent` and `.keyEquivalentModifierMask`.

- Important: You will have to disable the global keyboard shortcut while the menu is open, as otherwise, the keyboard events will be buffered up and triggered when the menu closes. This is because `NSMenu` puts the thread in tracking-mode, which prevents the keyboard events from being received. You can listen to whether a menu is open by implementing `NSMenuDelegate#menuWillOpen` and `NSMenuDelegate#menuDidClose`. You then use `KeyboardShortcuts.disable` and `KeyboardShortcuts.enable`.
*/
@_disfavoredOverload
public func setShortcut(_ shortcut: KeyboardShortcuts.Shortcut?) {
func set() {
guard let shortcut else {
clearShortcut()
return
}
- Important: You will have to disable the global keyboard shortcut while the menu is open, as otherwise, the keyboard events will be buffered up and triggered when the menu closes. This is because `NSMenu` puts the thread in tracking-mode, which prevents the keyboard events from being received. You can listen to whether a menu is open by implementing `NSMenuDelegate#menuWillOpen` and `NSMenuDelegate#menuDidClose`. You then use `KeyboardShortcuts.disable` and `KeyboardShortcuts.enable`.
*/
@_disfavoredOverload
public func setShortcut(_ shortcut: KeyboardShortcuts.Shortcut?) {
func set() {
guard let shortcut else {
clearShortcut()
return
}

keyEquivalent = shortcut.keyEquivalent
keyEquivalentModifierMask = shortcut.modifiers
keyEquivalent = shortcut.keyEquivalent
keyEquivalentModifierMask = shortcut.modifiers

if #available(macOS 12, *) {
allowsAutomaticKeyEquivalentLocalization = false
if #available(macOS 12, *) {
allowsAutomaticKeyEquivalentLocalization = false
}
}
}

// `TISCopyCurrentASCIICapableKeyboardLayoutInputSource` works on a background thread, but crashes when used in a `NSBackgroundActivityScheduler` task, so we ensure it's not run in that queue.
if DispatchQueue.isCurrentQueueNSBackgroundActivitySchedulerQueue {
DispatchQueue.main.async {
// `TISCopyCurrentASCIICapableKeyboardLayoutInputSource` works on a background thread, but crashes when used in a `NSBackgroundActivityScheduler` task, so we ensure it's not run in that queue.
if DispatchQueue.isCurrentQueueNSBackgroundActivitySchedulerQueue {
DispatchQueue.main.async {
set()
}
} else {
set()
}
} else {
set()
}
}
}
#endif
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/Name.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
extension KeyboardShortcuts {
/**
The strongly-typed name of the keyboard shortcut.
Expand Down Expand Up @@ -56,3 +57,4 @@
self.init(rawValue)
}
}
#endif

Check warning on line 60 in Sources/KeyboardShortcuts/Name.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/Recorder.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
import SwiftUI

@available(macOS 10.15, *)
Expand Down Expand Up @@ -161,3 +162,4 @@
}
}
}
#endif

Check warning on line 165 in Sources/KeyboardShortcuts/Recorder.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/RecorderCocoa.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
import Cocoa
import Carbon.HIToolbox

Expand Down Expand Up @@ -282,3 +283,4 @@
}
}
}
#endif

Check warning on line 286 in Sources/KeyboardShortcuts/RecorderCocoa.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/Shortcut.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
import Cocoa
import Carbon.HIToolbox

Expand Down Expand Up @@ -323,3 +324,4 @@
modifiers.description + (keyToCharacter()?.uppercased() ?? "�")
}
}
#endif

Check warning on line 327 in Sources/KeyboardShortcuts/Shortcut.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/Utilities.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
import Carbon.HIToolbox
import SwiftUI

Expand Down Expand Up @@ -463,3 +464,4 @@
.alignmentGuide(.leading) { $0[.controlAlignment] }
}
}
#endif

Check warning on line 467 in Sources/KeyboardShortcuts/Utilities.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)
2 changes: 2 additions & 0 deletions Sources/KeyboardShortcuts/ViewModifiers.swift
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#if os(macOS)
import SwiftUI

@available(macOS 12, *)
Expand Down Expand Up @@ -38,3 +39,4 @@
}
}
}
#endif

Check warning on line 42 in Sources/KeyboardShortcuts/ViewModifiers.swift

View workflow job for this annotation

GitHub Actions / lint

Trailing Newline Violation: Files should have a single trailing newline (trailing_newline)