• 桌面应用

【免费下载链接】Lunar

Intelligent adaptive brightness for your external monitors

项目地址: https://gitcode.com/gh_mirrors/lu/Lunar
点击查看 免费下载

Lunar 5.2.1 是一次聚焦稳定性与内置屏(MacBook 自带屏幕)体验的维护性更新:它在“高级设置(Advanced settings)”中新增了**可选的亮度键转发(brightness key forwarding)**功能,用于解决部分老设备上内置显示屏亮度无法持久保存的问题;同时修复了 BlackOut 状态残留、内置屏 OSD 误弹出、Location Mode 图表数据点错误导致的崩溃,以及暗黑模式下 Input 热键下拉框的显示问题。本文结合该版本仓库源码,逐项拆解这些改动背后的实现逻辑与使用场景。

一、新特性:内置显示屏亮度键转发变为可选开关

1.1 该设置解决什么问题

版本说明原文指出:如果内置显示屏(built-in display)的亮度无法正常持久保存,可以尝试启用该设置。在 5.2.1 之前,Lunar 会直接接管键盘上的亮度媒体键(media key)来调节内置屏亮度;但对某些特定老设备,这种接管方式会导致系统侧无法记录亮度状态,出现“重启后亮度回退”的情况。

该版本将这一行为改为高级设置中的可选开关:Use workaround for built-in display(为内置显示屏使用变通方案)。启用后,Lunar 不再直接修改内置屏亮度,而是把亮度键事件转发给系统,由系统原生的方式处理内置屏亮度,Lunar 只负责外部显示器。

1.2 设置入口与界面说明

该开关位于 Advanced 设置页的 MacBook 分组中,对应源码 AdvancedSettingsView.swift:

SettingsToggle(
    text: "Use workaround for built-in display", setting: $workaroundBuiltinDisplay,
    help: """
    Forward brightness key events to the system instead of
    changing built-in display brightness from Lunar.

    This setting might be needed to persist brightness
    changes better on some specific older devices.

    Disables the following functions for the built-in display:
      • Hotkey Step
      • Auto XDR
      • Sub-zero Dimming
    """
)

界面上的帮助文本明确了两点:

  • 启用条件:仅在“特定老设备上亮度持久化不佳”时才需要打开,属于兼容性变通方案;
  • 启用代价:会为内置屏关闭三个依赖 Lunar 直接控制的功能——Hotkey Step(热键步进)、Auto XDR(自动 XDR 增强)、Sub-zero Dimming(零下亮度 / 低于 0 的暗化)。

1.3 底层实现:按键事件如何被“转发”给系统

该开关对应的偏好项定义在 DataStore.swift(cacheKey(.workaroundBuiltinDisplay)),并有独立的发布者 workaroundBuiltinDisplayPublisher(DataStore.swift)供界面绑定。

真正的按键处理逻辑在 Hotkeys.swift 的 handleBrightnessKeyAction 中。以“调节所有显示器(.all)”分支为例:

if CachedDefaults[.workaroundBuiltinDisplay], lidOpened, let builtin = DC.builtinDisplay, builtin.active {
    log.info("Adjusting external displays and then forwarding media key to system")
    adjust(mediaKey, by: offset, contrast: contrast, allDisplays: true)
    if !contrast, !builtin.blackOutEnabled {
        event.flags = event.flags.subtracting([.maskShift, .maskAlternate, .maskCommand, .maskControl])
        if offset == 1 {
            event.flags = event.flags.union([.maskShift, .maskAlternate])
        }
        log.info("Forwarding media key to system using flags=\(offset == 1 ? "[.maskShift, .maskAlternate]" : "[]")")
        return event
    }
    ...
}

从源码可以提炼出该变通方案的关键行为:

  1. 先调外部屏、再转发事件:Lunar 先用媒体键事件调整所有外部显示器的亮度,然后把原始 CGEvent(按键事件)原样返回给系统(return event),让 macOS 继续用系统方式调节内置屏;
  2. 修饰键重写:代码会先清空事件上的 Shift/Alt/Cmd/Ctrl 标志,再根据 offset 重新组合——这是为了模拟不同的按键语义(如小步进亮度需要附加 Shift+Alt);
  3. 场景隔离:仅在 lidOpened(盖子打开)、非对比度调节、且内置屏未处于 BlackOut 状态时转发;对比度(contrast)本身不支持内置屏,因此直接跳过转发逻辑;
  4. 多个按键目标分支覆盖:同样的转发逻辑还出现在 .cursor(光标所在屏)、.builtin(内置屏)、.source(源显示器)等分支中(Hotkeys.swift),保证不同按键配置下行为一致。

二、修复项逐条解析

2.1 修复:亮度大于 1 时重置 BlackOut 状态

Reset BlackOut state if brightness is greater than 1

BlackOut 会把显示器亮度压到 0 并禁用屏幕;但在某些异常路径下,用户手动把亮度调回大于 1 后,显示器的 blackOutEnabled 状态仍可能残留为开启,导致屏幕继续被判定为“黑屏”而拒绝响应。

本次修复在显示器状态解码处(Display.swift)补齐了校验:当解码出的 blackOutEnabled 为 true 时,要求“原生显示器(isNative)的当前亮度必须 ≤ 1”,否则视为无效状态;同时把解码时 minBrightness == 1 的情况自动校正为 0,避免最小亮度与 BlackOut 状态互相矛盾。

配套的 resetBlackOut()(Display.swift)也做了防御性收尾:先通过 DC.blackOut(display:state:.off) 恢复镜像/软件控制,再在 1 秒后清除 blackOutEnabled、重置镜像权限并把 preciseBrightnessContrast 归位,确保状态彻底复原。

2.2 修复:转发媒体键到系统时不再为内置屏弹出 OSD

Don't show OSD for built-in brightness when forwarding media keys to the system

启用上述“亮度键转发”后,内置屏亮度改由系统调节,Lunar 此时再弹出自己的 OSD 会造成双重反馈、体验割裂。修复后,在 workaroundBuiltinDisplay 生效且处于默认“未指定目标显示器”的路径上,OSD 只对外部显示器展示(Hotkeys.swift):

guard sourceDisplay || builtinDisplay || currentDisplay || allDisplays || mainDisplay || nonMainDisplays else {
    log.info("showOSD()")
    if CachedDefaults[.workaroundBuiltinDisplay] {
        DC.externalActiveDisplays.forEach(showOSD)
    } else {
        DC.activeDisplayList.forEach(showOSD)
    }
    return
}

即:未显式指定按键目标时,开启变通方案后 OSD 列表从 activeDisplayList(含内置屏)收窄为 externalActiveDisplays(仅外部屏),内置屏亮度交给系统,不再出现重复 OSD。

2.3 修复:Location Mode 图表错误数据点导致的崩溃

Fix crash because of wrong datapoints for the Location Mode chart

Location Mode 依赖太阳位置(日出/日落)推算环境光变化,其图表按时间序列绘制亮度-时间数据点。当数据点结构错误(如出现非法值或索引越界)时,图表绘制会在某个时间点触发崩溃。该修复收紧了 Location Mode 图表的数据点构造/取值逻辑,从数据源头杜绝越界访问。对普通用户而言,此修复消除了“启用 Location Mode 后偶尔闪退”的隐患。

2.4 修复:暗黑模式下 Input 热键下拉框显示异常

Fix Input Hotkey dropdown in Dark Mode

Input 热键用于一键切换显示器视频输入源(HDMI/DP/USB-C 等),对应 Display 模型中的 hotkeyInput1/2/3 属性(Display.swift),并由 HotkeyPopoverController.swift 在按下热键时执行 switchInput 切换输入源。修复前,该下拉框在 macOS 暗黑模式下存在配色/渲染问题(如文本不可见或控件错位),本次更新统一了其暗色外观表现。

三、关联的 CLI 操作与配置入口

虽然 5.2.1 的核心改动集中在设置项与修复,但 BlackOut 状态相关的日常操作同样可通过 CLI 完成,便于脚本化验证上述修复后的状态重置行为。仓库内置的 blackout 子命令(CLI.swift)支持:

lunar blackout builtin enable      # 关闭内置屏(不切断电源)
lunar blackout builtin disable     # 重新开启内置屏
lunar blackout external enable --no-mirror   # 关闭外部屏且不做屏幕镜像
lunar blackout all enable --master external  # 指定镜像源显示器

其参数包括:

  • --no-mirror:开启 BlackOut 时不镜像屏幕内容;
  • --master <display>:BlackOut 时用于镜像的显示器;
  • <display>:显示器序列号或名称(不带空格),或 builtin / external 等快捷目标;
  • <state>:enable(关屏)或 disable(恢复)。

CLI 中同样会在切换时重置 lastBlackOutToggleDate,与 2.1 提到的“状态重置”修复形成呼应,保证命令行与 GUI 两条路径的状态一致。

四、升级与使用建议

  • 内置屏亮度无法持久保存的用户:在 Advanced 设置 → MacBook 分组中启用 Use workaround for built-in display,让系统接管内置屏亮度键;注意此选项会同时关闭内置屏的 Hotkey Step、Auto XDR 与 Sub-zero Dimming,属于“以功能换兼容”的取舍。
  • 其他用户:保持默认关闭即可,5.2.1 的其余修复(BlackOut 状态重置、内置屏 OSD、Location Mode 崩溃、暗黑模式下拉框)均为无感改进,升级后直接受益。
  • 验证方式:可用上述 lunar blackout CLI 命令手动触发 BlackOut 后再调高亮度,观察状态是否被正确重置;Location Mode 用户可切换图表页确认不再闪退。

整体来看,5.2.1 是围绕“内置屏体验”与“状态一致性”的小版本迭代:一个可开关的兼容性设置,加上四处针对性修复,代码量不大但都落在实际用户反馈的高频痛点上,适合所有 Lunar 用户平滑升级。

  • 桌面应用

【免费下载链接】Lunar

Intelligent adaptive brightness for your external monitors

项目地址: https://gitcode.com/gh_mirrors/lu/Lunar
点击查看 免费下载

更多推荐