fix: rare crash when assigning shortcuts with arrow keys
This commit is contained in:
1 parent
f4a54c8f1b
commit
49778089ea
24 files changed
+132
-30
No files matched your search
@@ -160,6 +160,9 @@
|
||||
/* No comment provided by engineer. */
|
||||
"Arrow keys" = "Arrow keys";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Arrow keys already assigned to other actions:\n%@";
|
||||
|
||||
/* No comment provided by engineer. */
|
||||
"Ask whether to send crash reports" = "Ask whether to send crash reports";
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "اسم التطبيق - عنوان النافذة";
|
||||
"Applies in other Appearances" = "يُطبَّق في المظاهر الأخرى";
|
||||
"Arrow keys" = "مفاتيح الأسهم";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "مفاتيح الأسهم معيّنة بالفعل لإجراءات أخرى:\n%@";
|
||||
"Ask whether to send crash reports" = "السؤال عن إرسال تقارير الأعطال";
|
||||
"Auto" = "تلقائي";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "حجم تلقائي — معاينات أكبر مع عدد قليل من النوافذ، وأكثر مرة واحدة مع الكثير منها";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Anwendungsname - Fenstertitel";
|
||||
"Applies in other Appearances" = "Gilt in anderen Darstellungen";
|
||||
"Arrow keys" = "Pfeiltasten";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Pfeiltasten sind bereits anderen Aktionen zugewiesen:\n%@";
|
||||
"Ask whether to send crash reports" = "Fragen, ob Absturzberichte gesendet werden sollen";
|
||||
"Auto" = "Automatisch";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Automatische Größe — größere Vorschauen bei wenigen Fenstern, mehr auf einmal bei vielen";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Application Name - Window Title";
|
||||
"Applies in other Appearances" = "Applies in other Appearances";
|
||||
"Arrow keys" = "Arrow keys";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Arrow keys already assigned to other actions:\n%@";
|
||||
"Ask whether to send crash reports" = "Ask whether to send crash reports";
|
||||
"Auto" = "Auto";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Auto Size — larger previews with few windows, more at once with many";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Nombre de la aplicación - Título de la ventana";
|
||||
"Applies in other Appearances" = "Se aplica en otras Apariencias";
|
||||
"Arrow keys" = "Teclas de flecha";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Teclas de flecha ya asignadas a otras acciones:\n%@";
|
||||
"Ask whether to send crash reports" = "Preguntar si enviar los informes de problema";
|
||||
"Auto" = "Automático";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Tamaño automático — previsualizaciones más grandes con pocas ventanas, más a la vez con muchas";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Nom de l'application - Titre de la fenêtre";
|
||||
"Applies in other Appearances" = "S'applique aux autres apparences";
|
||||
"Arrow keys" = "Touches fléchées";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Touches fléchées déjà affectées à d'autres actions :\n%@";
|
||||
"Ask whether to send crash reports" = "Demander avant d'envoyer un rapport de plantage";
|
||||
"Auto" = "Auto";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Taille automatique — aperçus plus grands avec peu de fenêtres, plus à la fois quand il y en a beaucoup";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "שם היישום - כותרת החלון";
|
||||
"Applies in other Appearances" = "חל במראים אחרים";
|
||||
"Arrow keys" = "מקשי חצים";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "מקשי חצים כבר משויכים לפעולות אחרות:\n%@";
|
||||
"Ask whether to send crash reports" = "שאל לפני שליחת דיווחי קריסה";
|
||||
"Auto" = "אוטומטי";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "גודל אוטומטי — תצוגות מקדימות גדולות יותר עם מעט חלונות, יותר בבת אחת עם רבים";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Nama Aplikasi - Judul Jendela";
|
||||
"Applies in other Appearances" = "Berlaku pada Tampilan lain";
|
||||
"Arrow keys" = "Tombol panah";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Tombol panah sudah ditetapkan untuk tindakan lain:\n%@";
|
||||
"Ask whether to send crash reports" = "Tanya apakah akan mengirim laporan kerusakan";
|
||||
"Auto" = "Otomatis";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Ukuran Otomatis — pratinjau lebih besar saat jendela sedikit, lebih banyak sekaligus saat jendela banyak";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Nome dell'applicazione - Titolo della finestra";
|
||||
"Applies in other Appearances" = "Si applica negli altri Aspetti";
|
||||
"Arrow keys" = "Tasti freccia";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Tasti freccia già assegnati ad altre azioni:\n%@";
|
||||
"Ask whether to send crash reports" = "Chiedi se inviare i resoconti di arresti anomali";
|
||||
"Auto" = "Automatico";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Dimensione automatica — anteprime più grandi con poche finestre, più contemporaneamente con molte";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "アプリケーション名 - ウインドウタイトル";
|
||||
"Applies in other Appearances" = "他の外観にも適用されます";
|
||||
"Arrow keys" = "矢印キー";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "矢印キーはすでに他のアクションに割り当てられています:\n%@";
|
||||
"Ask whether to send crash reports" = "クラッシュレポートの送信を毎回確認";
|
||||
"Auto" = "自動";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "自動サイズ — ウインドウが少ないと大きく、多いとまとめて表示";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "응용 프로그램 이름 - 윈도우 제목";
|
||||
"Applies in other Appearances" = "다른 모양에도 적용됨";
|
||||
"Arrow keys" = "화살표 키";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "화살표 키가 이미 다른 동작에 할당되어 있습니다:\n%@";
|
||||
"Ask whether to send crash reports" = "충돌 보고서 전송 여부 물어보기";
|
||||
"Auto" = "자동";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "자동 크기 — 윈도우가 적으면 미리보기가 크고, 많으면 한 번에 더 많이 표시";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Naam van app - Venstertitel";
|
||||
"Applies in other Appearances" = "Geldt in andere weergaven";
|
||||
"Arrow keys" = "Pijltjestoetsen";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Pijltjestoetsen zijn al toegewezen aan andere acties:\n%@";
|
||||
"Ask whether to send crash reports" = "Vragen of crashrapporten verstuurd moeten worden";
|
||||
"Auto" = "Automatisch";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Automatische grootte — grotere voorvertoningen bij weinig vensters, meer tegelijk bij veel";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Nazwa aplikacji - Tytuł okna";
|
||||
"Applies in other Appearances" = "Stosuje się w innych Wyglądach";
|
||||
"Arrow keys" = "Klawisze strzałek";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Klawisze strzałek są już przypisane do innych akcji:\n%@";
|
||||
"Ask whether to send crash reports" = "Pytaj o wysyłanie raportów awarii";
|
||||
"Auto" = "Automatycznie";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Automatyczny rozmiar — większe podglądy przy małej liczbie okien, więcej naraz przy dużej";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Nome do Aplicativo - Título da Janela";
|
||||
"Applies in other Appearances" = "Aplica-se a outras aparências";
|
||||
"Arrow keys" = "Teclas de seta";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Teclas de seta já atribuídas a outras ações:\n%@";
|
||||
"Ask whether to send crash reports" = "Perguntar se deve enviar relatórios de falha";
|
||||
"Auto" = "Automático";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Tamanho automático — pré-visualizações maiores com poucas janelas, mais janelas de uma vez quando houver muitas";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Название приложения — Заголовок окна";
|
||||
"Applies in other Appearances" = "Применяется в других оформлениях";
|
||||
"Arrow keys" = "Клавиши со стрелками";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Клавиши со стрелками уже назначены другим действиям:\n%@";
|
||||
"Ask whether to send crash reports" = "Спрашивать перед отправкой отчётов о сбоях";
|
||||
"Auto" = "Авто";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Автоматический размер — крупнее при малом числе окон, компактнее при большом";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Programnamn - Fönstertitel";
|
||||
"Applies in other Appearances" = "Gäller i andra Utseenden";
|
||||
"Arrow keys" = "Piltangenter";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Piltangenter är redan tilldelade andra åtgärder:\n%@";
|
||||
"Ask whether to send crash reports" = "Fråga om kraschrapporter ska skickas";
|
||||
"Auto" = "Auto";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Automatisk storlek — större förhandsvisningar med få fönster, fler åt gången med många";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "ชื่อแอปพลิเคชัน - ชื่อหน้าต่าง";
|
||||
"Applies in other Appearances" = "ใช้ในลักษณะอื่น";
|
||||
"Arrow keys" = "ปุ่มลูกศร";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "ปุ่มลูกศรถูกกำหนดให้กับการกระทำอื่นแล้ว:\n%@";
|
||||
"Ask whether to send crash reports" = "ถามว่าจะส่งรายงานการขัดข้องหรือไม่";
|
||||
"Auto" = "อัตโนมัติ";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "ขนาดอัตโนมัติ — ภาพตัวอย่างใหญ่ขึ้นเมื่อมีหน้าต่างน้อย แสดงพร้อมกันมากขึ้นเมื่อมีหน้าต่างเยอะ";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Uygulama Adı - Pencere Başlığı";
|
||||
"Applies in other Appearances" = "Diğer Görünümlerde uygulanır";
|
||||
"Arrow keys" = "Ok tuşları";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Ok tuşları zaten başka eylemlere atanmış:\n%@";
|
||||
"Ask whether to send crash reports" = "Çökme raporlarının gönderilip gönderilmeyeceğini sor";
|
||||
"Auto" = "Otomatik";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Otomatik Boyut — az pencerede büyük önizlemeler, çok pencerede aynı anda daha fazlası";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "Tên ứng dụng - Tiêu đề cửa sổ";
|
||||
"Applies in other Appearances" = "Áp dụng trong các Giao diện khác";
|
||||
"Arrow keys" = "Phím mũi tên";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "Phím mũi tên đã được gán cho các hành động khác:\n%@";
|
||||
"Ask whether to send crash reports" = "Hỏi trước khi gửi báo cáo sự cố";
|
||||
"Auto" = "Tự động";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "Kích cỡ tự động — bản xem trước lớn hơn khi có ít cửa sổ, hiển thị nhiều hơn cùng lúc khi có nhiều cửa sổ";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "应用名称 - 窗口标题";
|
||||
"Applies in other Appearances" = "适用于其他外观";
|
||||
"Arrow keys" = "方向键";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "方向键已分配给其他操作:\n%@";
|
||||
"Ask whether to send crash reports" = "询问是否发送崩溃报告";
|
||||
"Auto" = "自动";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "自动大小 — 窗口较少时预览更大,窗口较多时一次显示更多";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "應用程式名稱 - 視窗標題";
|
||||
"Applies in other Appearances" = "套用至其他外觀";
|
||||
"Arrow keys" = "方向鍵";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "方向鍵已指派給其他動作:\n%@";
|
||||
"Ask whether to send crash reports" = "詢問是否傳送當機報告";
|
||||
"Auto" = "自動";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "自動大小 — 視窗少時預覽較大,視窗多時一次顯示更多";
|
||||
|
||||
@@ -52,6 +52,7 @@
|
||||
"Application Name - Window Title" = "應用程式名稱 - 視窗標題";
|
||||
"Applies in other Appearances" = "套用至其他外觀";
|
||||
"Arrow keys" = "方向鍵";
|
||||
"Arrow keys already assigned to other actions:\n%@" = "方向鍵已指派給其他動作:\n%@";
|
||||
"Ask whether to send crash reports" = "詢問是否傳送當機報告";
|
||||
"Auto" = "自動";
|
||||
"Auto Size — larger previews with few windows, more at once with many" = "自動調整大小 — 視窗少時預覽較大,視窗多時一次顯示更多";
|
||||
|
||||
@@ -41,15 +41,39 @@ class CustomRecorderControl: RecorderControl {
|
||||
set(allowedModifierFlags: CustomRecorderControl.allowedModifiers.subtracting(restrictedModifiers), requiredModifierFlags: [], allowsEmptyModifierFlags: true)
|
||||
}
|
||||
|
||||
private enum ShortcutConflict {
|
||||
case arrow
|
||||
case vim
|
||||
case regular(control: CustomRecorderControl, label: String)
|
||||
case unknown
|
||||
|
||||
var label: String {
|
||||
switch self {
|
||||
case .arrow: return "Arrow keys"
|
||||
case .vim: return "Vim keys"
|
||||
case .regular(_, let label): return label
|
||||
case .unknown: return "an unknown action"
|
||||
}
|
||||
}
|
||||
|
||||
static func classify(_ id: String) -> ShortcutConflict {
|
||||
if ["←", "→", "↑", "↓"].contains(id) { return .arrow }
|
||||
if id.starts(with: "vimCycle") { return .vim }
|
||||
if let existing = ControlsTab.shortcutControls[id] {
|
||||
return .regular(control: existing.0, label: existing.1)
|
||||
}
|
||||
assertionFailure("conflict id '\(id)' missing from shortcutControls")
|
||||
return .unknown
|
||||
}
|
||||
}
|
||||
|
||||
func alertIfSameShortcutAlreadyAssigned(_ candidateShortcut: Shortcut, _ shortcutAlreadyAssigned: String) {
|
||||
let isArrowKeys = ["←", "→", "↑", "↓"].contains(shortcutAlreadyAssigned)
|
||||
let isVimKeys = shortcutAlreadyAssigned.starts(with: "vimCycle")
|
||||
let existingShortcut = ControlsTab.shortcutControls[shortcutAlreadyAssigned]!
|
||||
let conflict = ShortcutConflict.classify(shortcutAlreadyAssigned)
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .warning
|
||||
alert.messageText = NSLocalizedString("Conflicting shortcut", comment: "")
|
||||
alert.informativeText = String(format: NSLocalizedString("Shortcut already assigned to another action: %@", comment: ""),
|
||||
(isArrowKeys ? "Arrow keys" : (isVimKeys ? "Vim keys" : existingShortcut.1)).replacingOccurrences(of: " ", with: "\u{00A0}"))
|
||||
conflict.label.replacingOccurrences(of: " ", with: "\u{00A0}"))
|
||||
if !id.starts(with: "holdShortcut") {
|
||||
alert.addButton(withTitle: NSLocalizedString("Unassign existing shortcut and continue", comment: "")).setAccessibilityFocused(true)
|
||||
}
|
||||
@@ -59,22 +83,26 @@ class CustomRecorderControl: RecorderControl {
|
||||
cancelButton.setAccessibilityFocused(true)
|
||||
}
|
||||
let userChoice = alert.runModal()
|
||||
if !id.starts(with: "holdShortcut") && userChoice == .alertFirstButtonReturn {
|
||||
if isArrowKeys, let cb = ControlsTab.arrowKeysCheckbox {
|
||||
guard !id.starts(with: "holdShortcut"), userChoice == .alertFirstButtonReturn else { return }
|
||||
switch conflict {
|
||||
case .arrow:
|
||||
if let cb = ControlsTab.arrowKeysCheckbox {
|
||||
cb.state = .off
|
||||
ControlsTab.arrowKeysEnabledCallback(cb)
|
||||
LabelAndControl.controlWasChanged(cb, nil)
|
||||
} else if isVimKeys, let cb = ControlsTab.vimKeysCheckbox {
|
||||
}
|
||||
case .vim:
|
||||
if let cb = ControlsTab.vimKeysCheckbox {
|
||||
cb.state = .off
|
||||
ControlsTab.vimKeysEnabledCallback(cb)
|
||||
LabelAndControl.controlWasChanged(cb, nil)
|
||||
} else {
|
||||
updateShortcut(existingShortcut.0, nil, existingShortcut.0, shortcutAlreadyAssigned)
|
||||
}
|
||||
if let target = ControlsTab.shortcutControls[id]?.0 {
|
||||
updateShortcut(target, candidateShortcut, self, id)
|
||||
}
|
||||
case .regular(let existingControl, _):
|
||||
updateShortcut(existingControl, nil, existingControl, shortcutAlreadyAssigned)
|
||||
case .unknown:
|
||||
return
|
||||
}
|
||||
updateShortcut(self, candidateShortcut, self, id)
|
||||
}
|
||||
|
||||
func updateShortcut(_ control: CustomRecorderControl, _ objectValue: Shortcut?, _ senderControl: NSControl, _ id: String) {
|
||||
@@ -84,22 +112,24 @@ class CustomRecorderControl: RecorderControl {
|
||||
}
|
||||
|
||||
func alertIfShortcutReservedByMacos(_ candidateShortcut: Shortcut, _ shortcutReservedByMacos: String) {
|
||||
let existingShortcutLabel = ControlsTab.shortcutControls[shortcutReservedByMacos]!.1
|
||||
let existing = ControlsTab.shortcutControls[shortcutReservedByMacos]
|
||||
if existing == nil {
|
||||
assertionFailure("reserved-by-macos id '\(shortcutReservedByMacos)' missing from shortcutControls")
|
||||
}
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .warning
|
||||
alert.messageText = NSLocalizedString("Conflicting shortcut", comment: "")
|
||||
alert.informativeText = String(format: NSLocalizedString("macOS reserves ⌘⌥⎋, ⌘⌥⇧⎋, and ⌘⌥⇧⌃⎋ for Force Quit and they cannot be unbound. AltTab cannot use them.\n\nYour change would assign one of these to: %@.", comment: ""), existingShortcutLabel)
|
||||
alert.informativeText = String(format: NSLocalizedString("macOS reserves ⌘⌥⎋, ⌘⌥⇧⎋, and ⌘⌥⇧⌃⎋ for Force Quit and they cannot be unbound. AltTab cannot use them.\n\nYour change would assign one of these to: %@.", comment: ""), existing?.1 ?? "an unknown action")
|
||||
alert.addButton(withTitle: NSLocalizedString("Unassign existing shortcut and continue", comment: ""))
|
||||
let cancelButton = alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
|
||||
cancelButton.keyEquivalent = "\u{1b}"
|
||||
cancelButton.setAccessibilityFocused(true)
|
||||
let userChoice = alert.runModal()
|
||||
if userChoice == .alertFirstButtonReturn {
|
||||
guard id != shortcutReservedByMacos else { return }
|
||||
let existingShortcut = ControlsTab.shortcutControls[shortcutReservedByMacos]!
|
||||
updateShortcut(existingShortcut.0, nil, existingShortcut.0, shortcutReservedByMacos)
|
||||
updateShortcut(ControlsTab.shortcutControls[id]!.0, candidateShortcut, self, id)
|
||||
guard userChoice == .alertFirstButtonReturn, id != shortcutReservedByMacos else { return }
|
||||
if let existing {
|
||||
updateShortcut(existing.0, nil, existing.0, shortcutReservedByMacos)
|
||||
}
|
||||
updateShortcut(self, candidateShortcut, self, id)
|
||||
}
|
||||
|
||||
func save(_ candidateShortcut: Shortcut) {
|
||||
|
||||
@@ -51,6 +51,7 @@ class ControlsTab {
|
||||
"showAppsOrWindows",
|
||||
]
|
||||
private static let arrowKeys = ["←", "→", "↑", "↓"]
|
||||
private static let arrowKeyCodes: Set<KeyCode> = [.leftArrow, .rightArrow, .upArrow, .downArrow]
|
||||
private static let vimKeyActions = [
|
||||
"h": "vimCycleLeft",
|
||||
"l": "vimCycleRight",
|
||||
@@ -92,7 +93,7 @@ class ControlsTab {
|
||||
static func initializePreferencesDependentState() {
|
||||
applyActiveShortcutPreferences()
|
||||
staticManagedShortcutPreferences.forEach { applyShortcutPreference($0) }
|
||||
applyArrowKeysPreference()
|
||||
applyArrowKeysPreferenceWithoutDialogs()
|
||||
applyVimKeysPreferenceWithoutDialogs()
|
||||
}
|
||||
|
||||
@@ -123,8 +124,8 @@ class ControlsTab {
|
||||
// An override key changed (e.g. user picked a different value, or remembered-restore wrote).
|
||||
refreshUnlinkButtons()
|
||||
AppearanceTab.refreshAllOverrideInfoLabels()
|
||||
case "arrowKeysEnabled":
|
||||
applyArrowKeysPreference()
|
||||
case "arrowKeysEnabled" where arrowKeysCheckbox == nil:
|
||||
applyArrowKeysPreferenceWithoutDialogs()
|
||||
case "vimKeysEnabled" where vimKeysCheckbox == nil:
|
||||
applyVimKeysPreferenceWithoutDialogs()
|
||||
default:
|
||||
@@ -1197,7 +1198,42 @@ class ControlsTab {
|
||||
}
|
||||
|
||||
@objc static func arrowKeysEnabledCallback(_ sender: NSControl) {
|
||||
applyArrowKeysPreference()
|
||||
if (sender as! Switch).state == .on {
|
||||
if isClearArrowKeysSuccessful() {
|
||||
arrowKeys.forEach { addShortcut(.down, .local, Shortcut(keyEquivalent: $0)!, $0, nil) }
|
||||
} else {
|
||||
(sender as! Switch).state = .off
|
||||
Preferences.set("arrowKeysEnabled", "false", false)
|
||||
}
|
||||
} else {
|
||||
arrowKeys.forEach { removeShortcutIfExists($0) }
|
||||
}
|
||||
}
|
||||
|
||||
private static func isClearArrowKeysSuccessful() -> Bool {
|
||||
var conflicts = [String: String]()
|
||||
shortcuts.forEach {
|
||||
guard arrowKeyCodes.contains($1.shortcut.keyCode) else { return }
|
||||
guard !arrowKeys.contains($1.id) else { return }
|
||||
if let label = conflictLabel($1.id) {
|
||||
conflicts[$1.id] = label
|
||||
}
|
||||
}
|
||||
if !conflicts.isEmpty {
|
||||
if SettingsWindow.shared == nil || !shouldClearConflictingShortcuts(conflicts.map { $0.value }, NSLocalizedString("Arrow keys already assigned to other actions:\n%@", comment: "")) {
|
||||
return false
|
||||
}
|
||||
conflicts.forEach {
|
||||
removeShortcutIfExists($0.key)
|
||||
let existing = shortcutControls[$0.key]
|
||||
if existing != nil {
|
||||
existing!.0.objectValue = nil
|
||||
shortcutChangedCallback(existing!.0)
|
||||
LabelAndControl.controlWasChanged(existing!.0, $0.key)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
@objc static func vimKeysEnabledCallback(_ sender: NSControl) {
|
||||
@@ -1226,7 +1262,7 @@ class ControlsTab {
|
||||
}
|
||||
}
|
||||
if !conflicts.isEmpty {
|
||||
if SettingsWindow.shared == nil || !shouldClearConflictingShortcuts(conflicts.map { $0.value }) {
|
||||
if SettingsWindow.shared == nil || !shouldClearConflictingShortcuts(conflicts.map { $0.value }, NSLocalizedString("Vim keys already assigned to other actions:\n%@", comment: "")) {
|
||||
return false
|
||||
}
|
||||
conflicts.forEach {
|
||||
@@ -1255,12 +1291,12 @@ class ControlsTab {
|
||||
return nil
|
||||
}
|
||||
|
||||
private static func shouldClearConflictingShortcuts(_ conflicts: [String]) -> Bool {
|
||||
private static func shouldClearConflictingShortcuts(_ conflicts: [String], _ messageFormat: String) -> Bool {
|
||||
let alert = NSAlert()
|
||||
alert.alertStyle = .warning
|
||||
alert.messageText = NSLocalizedString("Conflicting shortcut", comment: "")
|
||||
let informativeText = conflicts.map { "• " + $0 }.joined(separator: "\n")
|
||||
alert.informativeText = String(format: NSLocalizedString("Vim keys already assigned to other actions:\n%@", comment: ""), informativeText.replacingOccurrences(of: " ", with: "\u{00A0}"))
|
||||
alert.informativeText = String(format: messageFormat, informativeText.replacingOccurrences(of: " ", with: "\u{00A0}"))
|
||||
alert.addButton(withTitle: NSLocalizedString("Unassign existing shortcut and continue", comment: "")).setAccessibilityFocused(true)
|
||||
let cancelButton = alert.addButton(withTitle: NSLocalizedString("Cancel", comment: ""))
|
||||
cancelButton.keyEquivalent = "\u{1b}"
|
||||
@@ -1323,11 +1359,23 @@ class ControlsTab {
|
||||
return Shortcut(code: baseShortcut.keyCode, modifierFlags: [holdShortcut.modifierFlags, baseShortcut.modifierFlags], characters: baseShortcut.characters, charactersIgnoringModifiers: baseShortcut.charactersIgnoringModifiers)
|
||||
}
|
||||
|
||||
private static func applyArrowKeysPreference() {
|
||||
if Preferences.arrowKeysEnabled {
|
||||
arrowKeys.forEach { addShortcut(.down, .local, Shortcut(keyEquivalent: $0)!, $0, nil) }
|
||||
} else {
|
||||
private static func applyArrowKeysPreferenceWithoutDialogs() {
|
||||
guard Preferences.arrowKeysEnabled else {
|
||||
arrowKeys.forEach { removeShortcutIfExists($0) }
|
||||
return
|
||||
}
|
||||
if hasArrowKeysConflictWithoutUi() {
|
||||
arrowKeys.forEach { removeShortcutIfExists($0) }
|
||||
Preferences.set("arrowKeysEnabled", "false", false)
|
||||
return
|
||||
}
|
||||
arrowKeys.forEach { addShortcut(.down, .local, Shortcut(keyEquivalent: $0)!, $0, nil) }
|
||||
}
|
||||
|
||||
private static func hasArrowKeysConflictWithoutUi() -> Bool {
|
||||
return shortcuts.values.contains {
|
||||
guard arrowKeyCodes.contains($0.shortcut.keyCode) else { return false }
|
||||
return !arrowKeys.contains($0.id)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user