Refactor force-capture into a dropdown option instead of a separate checkbox

Replace the separate "Force capture standard volume and mute keys" checkbox
with a new "Standard keys (force capture)" option in the existing Volume
control dropdown (KeyboardVolume.mediaForce, tag=4). This integrates the
feature more naturally into the existing UI, avoids removing the helpful
"audio device name override" hint text, and eliminates the forceStandardVolumeMediaKeys
preference key in favor of the enum-based approach.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
shuntagami 2026-03-22 17:58:34 +09:00
parent f41b3b966a
commit 622cfb481b
5 changed files with 16 additions and 35 deletions

View file

@ -78,9 +78,6 @@ enum PrefKey: String {
// Use fine OSD scale for volume
case useFineScaleVolume
// Always capture standard volume media keys even when macOS output volume is controllable
case forceStandardVolumeMediaKeys
// Use smoothBrightness
case disableSmoothBrightness
@ -215,4 +212,5 @@ enum KeyboardVolume: Int {
case custom = 1
case both = 2
case disabled = 3
case mediaForce = 4
}

View file

@ -150,7 +150,7 @@ class MediaKeyTapManager: MediaKeyTapDelegate {
if [KeyboardBrightness.media.rawValue, KeyboardBrightness.both.rawValue].contains(prefs.integer(forKey: PrefKey.keyboardBrightness.rawValue)) {
keys.append(contentsOf: [.brightnessUp, .brightnessDown])
}
if [KeyboardVolume.media.rawValue, KeyboardVolume.both.rawValue].contains(prefs.integer(forKey: PrefKey.keyboardVolume.rawValue)) {
if [KeyboardVolume.media.rawValue, KeyboardVolume.both.rawValue, KeyboardVolume.mediaForce.rawValue].contains(prefs.integer(forKey: PrefKey.keyboardVolume.rawValue)) {
keys.append(contentsOf: [.mute, .volumeUp, .volumeDown])
}
// Remove brightness keys if no external displays are connected, but only if brightness fine control is not active
@ -166,8 +166,8 @@ class MediaKeyTapManager: MediaKeyTapDelegate {
let keysToDelete: [MediaKey] = [.brightnessUp, .brightnessDown]
keys.removeAll { keysToDelete.contains($0) }
}
// Remove volume related keys if audio device is controllable unless the user opted into force-capturing them.
if !prefs.bool(forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue), let defaultAudioDevice = app.coreAudio.defaultOutputDevice {
// Remove volume related keys if audio device is controllable (skip when user chose force-capture mode)
if prefs.integer(forKey: PrefKey.keyboardVolume.rawValue) != KeyboardVolume.mediaForce.rawValue, let defaultAudioDevice = app.coreAudio.defaultOutputDevice {
let keysToDelete: [MediaKey] = [.volumeUp, .volumeDown, .mute]
if prefs.integer(forKey: PrefKey.multiKeyboardVolume.rawValue) == MultiKeyboardVolume.audioDeviceNameMatching.rawValue {
if DisplayManager.shared.updateAudioControlTargetDisplays(deviceName: defaultAudioDevice.name) == 0 {

View file

@ -1004,6 +1004,7 @@
<menu key="menu" id="LhY-cM-Msq">
<items>
<menuItem title="Standard keyboard volume and mute keys" state="on" id="1sy-Kd-WL5"/>
<menuItem title="Standard keys (force capture)" tag="4" id="fVk-mR-9Xp"/>
<menuItem title="Custom keyboard shortcuts" tag="1" id="4CG-0I-anB"/>
<menuItem title="Both standard and custom shortcuts" tag="2" id="QDG-SA-mRX">
<modifierMask key="keyEquivalentModifierMask"/>
@ -1129,16 +1130,14 @@
</gridCell>
<gridCell row="73k-Ho-qxa" column="ZC2-Ja-sIb" id="auW-Op-Sd7"/>
<gridCell row="73k-Ho-qxa" column="EiG-65-CTv" id="zDs-rB-tfY">
<button key="contentView" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5mr-B4-1IW">
<rect key="frame" x="218" y="24" width="472" height="18"/>
<buttonCell key="cell" type="check" title="Force capture standard volume and mute keys" bezelStyle="regularSquare" imagePosition="left" inset="2" id="5V3-gQ-jWm">
<behavior key="behavior" changeContents="YES" doesNotDimImage="YES" lightByContents="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<action selector="forceStandardVolumeMediaKeysClicked:" target="eJ2-Cv-Vfp" id="w6y-tu-CZn"/>
</connections>
</button>
<textField key="contentView" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" preferredMaxLayoutWidth="400" translatesAutoresizingMaskIntoConstraints="NO" id="1lU-Y6-hCU">
<rect key="frame" x="218" y="26" width="474" height="14"/>
<textFieldCell key="cell" controlSize="small" title="You can override audio device name under Displays (advanced) if needed." id="Dha-Tm-cDM">
<font key="font" metaFont="smallSystem"/>
<color key="textColor" name="secondaryLabelColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</gridCell>
<gridCell row="fUL-yd-WWe" column="ZC2-Ja-sIb" xPlacement="trailing" yPlacement="center" id="Wh1-8h-lvf">
<textField key="contentView" focusRingType="none" horizontalHuggingPriority="251" verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="GO6-iW-7qg">
@ -1182,7 +1181,6 @@
<outlet property="customVolumeDown" destination="cag-2Q-I9P" id="AuB-3g-Pwa"/>
<outlet property="customVolumeUp" destination="rFx-DX-nFb" id="DpG-Xm-lRB"/>
<outlet property="disableAltBrightnessKeys" destination="EJp-ld-K4l" id="WzJ-1Q-YT4"/>
<outlet property="forceStandardVolumeMediaKeys" destination="5mr-B4-1IW" id="dbq-cm-WVC"/>
<outlet property="keyboardBrightness" destination="2NF-gh-JBU" id="3Cw-ob-T06"/>
<outlet property="keyboardVolume" destination="9oZ-JM-bxD" id="IJ6-6m-q0x"/>
<outlet property="multiKeyboardBrightness" destination="led-AW-u5j" id="14B-uk-v7Z"/>

View file

@ -415,8 +415,8 @@
/* Class = "NSButtonCell"; title = "Show percentages"; ObjectID = "ZUu-MR-XwA"; */
"ZUu-MR-XwA.title" = "Show percentages";
/* Class = "NSButtonCell"; title = "Force capture standard volume and mute keys"; ObjectID = "5V3-gQ-jWm"; */
"5V3-gQ-jWm.title" = "Force capture standard volume and mute keys";
/* Class = "NSMenuItem"; title = "Standard keys (force capture)"; ObjectID = "fVk-mR-9Xp"; */
"fVk-mR-9Xp.title" = "Standard keys (force capture)";
/* Class = "NSTextFieldCell"; title = "Combined dimming switchover point:"; ObjectID = "zv8-pZ-OPy"; */
"zv8-pZ-OPy.title" = "Combined dimming switchover point:";

View file

@ -33,7 +33,6 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane {
@IBOutlet var multiKeyboardVolume: NSPopUpButton!
@IBOutlet var useFineScale: NSButton!
@IBOutlet var useFineScaleVolume: NSButton!
@IBOutlet var forceStandardVolumeMediaKeys: NSButton!
@IBOutlet var separateCombinedScale: NSButton!
@IBOutlet var rowKeyboardBrightnessPopUp: NSGridRow!
@ -93,11 +92,9 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane {
if self.keyboardVolume.selectedTag() == KeyboardVolume.disabled.rawValue {
self.multiKeyboardVolume.isEnabled = false
self.useFineScaleVolume.isEnabled = false
self.forceStandardVolumeMediaKeys.isEnabled = false
} else {
self.multiKeyboardVolume.isEnabled = true
self.useFineScaleVolume.isEnabled = true
self.forceStandardVolumeMediaKeys.isEnabled = true
}
if self.multiKeyboardBrightness.selectedTag() == MultiKeyboardBrightness.focusInsteadOfMouse.rawValue {
@ -112,7 +109,7 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane {
self.rowUseAudioNameText.isHidden = false
self.rowUseAudioMouseText.isHidden = true
} else {
self.rowUseAudioNameText.isHidden = false
self.rowUseAudioNameText.isHidden = true
self.rowUseAudioMouseText.isHidden = false
}
}
@ -155,7 +152,6 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane {
self.multiKeyboardVolume.selectItem(withTag: prefs.integer(forKey: PrefKey.multiKeyboardVolume.rawValue))
self.useFineScale.state = prefs.bool(forKey: PrefKey.useFineScaleBrightness.rawValue) ? .on : .off
self.useFineScaleVolume.state = prefs.bool(forKey: PrefKey.useFineScaleVolume.rawValue) ? .on : .off
self.forceStandardVolumeMediaKeys.state = prefs.bool(forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue) ? .on : .off
self.separateCombinedScale.state = prefs.bool(forKey: PrefKey.separateCombinedScale.rawValue) ? .on : .off
self.updateGridLayout()
}
@ -193,17 +189,6 @@ class KeyboardPrefsViewController: NSViewController, SettingsPane {
}
}
@IBAction func forceStandardVolumeMediaKeysClicked(_ sender: NSButton) {
switch sender.state {
case .on:
prefs.set(true, forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue)
case .off:
prefs.set(false, forKey: PrefKey.forceStandardVolumeMediaKeys.rawValue)
default: break
}
app.updateMediaKeyTap()
}
@IBAction func separateCombinedScale(_ sender: NSButton) {
switch sender.state {
case .on: