Cinnamon 屏幕保护程序
程序入口
主入口是从 /usr/bin/cinnamon-screensaver 到 cinnamon-screensaver-main.py,它 启动一个 dbus 服务 (org.cinnamon.Screensaver)
service.py 启动 ScreensaverManager (manager.py),它是此处所有事务的核心命令,同时也是一个 会话代理,用于监听来自 cinnamon-session 的空闲状态变化,以及 logind 或 consolekit 代理。
运行
此时我们处于监听状态,等待用户发送的命令(例如通过 cinnamon-screensaver-command)或来自 其中一个代理的命令。
锁定(激活)
一旦收到锁定命令,管理器会生成一个主窗口(stage.py 中的 Stage),它覆盖整个 Gdk 屏幕 尺寸(一个包含所有显示器的虚拟矩形)。
将此覆盖层视为一个非常基础的窗口管理器。 在此覆盖层中放置:
- MonitorViews (monitorView.py) - 每个显示器一个,使用用户的背景绘制,放置在 每个窗口的确切位置。
- 一个时钟小部件,它在所有显示器周围大致随机地弹跳
- 一个解锁小部件,初始状态下是隐藏的
此时我们也已准备好接收用户事件,如按钮和按键按下,以及运动事件。 这由 GrabHelper 和 EventHandler 辅助,确保只允许我们想要的按键,并阻止 muffin 处理全局键绑定。
- 任何运动都是唤醒事件(如果未锁定,则显示解锁小部件或终止舞台)
- 任何点击都是唤醒事件(同上)
- 按键首先经过过滤 - 检查媒体键,音量、亮度控制等 不会触发解锁对话框(目前,仅当它们是简单的按键组合时 - 带有修饰键的复杂组合 仍会触发)
- 字符的按键将转发到对话框 - 如果您在空白的屏幕保护程序屏幕上开始输入密码, 它将被转发到密码输入框。
解锁
一旦用户输入密码并按下回车键或点击解锁,我们通过 cinnamon-desktop 中的 pam 辅助程序进行身份验证。
如果身份验证成功,所有小部件将被销毁,所有抓取被释放,我们回到 空闲监听状态。
文件:
application.css: 应用程序优先级的 css,用于使解锁对话框、时钟小部件在 不同背景下看起来正常
cinnamon-screensaver-command.py: 通过命令行向屏幕保护程序发送命令
cinnamon-screensaver-main.py: 程序的主入口点,处理几个参数,添加我们的 css 提供程序,启动 ScreensaverService。
baseWindow.py: 时钟和解锁小部件实现的一个基础揭示器类 - 任何将在舞台上移动的小部件都应实现此接口(monitorViews 除外) - 揭示器基类允许您执行简单的淡入和淡出。
cinnamonProxy.py:连接到 Cinnamon 的 dbus 接口,要求 Cinnamon 确保 expo 或 overview 已关闭(因为它们会创建一个服务器抓取,我们无法从中夺取焦点,从而阻止屏幕保护程序激活)。
clock.py(继承自 BaseWindow):在屏幕上弹跳的时钟小部件,其中包含所有这些内容。 定位是通过定时器上的随机化器完成的,该随机器会调整垂直和水平对齐属性(start、center 或 end 之一)以及当前监视器,Stage 定位函数使用这些信息来告知它应放置 Clock 小部件的位置。
config.py.in(编译为 config.py):包含各种文件在此处使用的系统特定文件位置。
consoleKitProxy.py:通过 dbus 监听来自 consolekit 的命令
constants.py:一个仅包含各种文件在此处使用的硬编码屏幕/值列表的文件。
eventHandler.py:接收并处理来自各种源的所有转发事件。 除运动事件外,不进行传播。
fader.py:Stage 的一个辅助工具,使用帧滴答回调在特定时间段内淡入或淡出 stage。 由于它使用帧时钟而非 GSource,时间保持一致,并且只绘制有时间允许的帧数(1 秒的动画将持续 1 秒,但可能不会看到所有 60 帧的绘制)
focusNavigator.py: 一个用于在解锁屏幕上导航焦点并对可导航小部件执行激活操作的辅助工具。 由于我们严格地汇聚事件,并且不执行任何传播(以防止窗口管理器或桌面快捷键被触发),我们必须自行管理焦点,并在按下回车键或空格键时对获得焦点的小部件执行激活操作。
grabHelper.py: 一个用于实现独占鼠标和键盘抓取,以及在适当时候隐藏鼠标指针的辅助工具。
keybindings.py: 从 EventHandler 接收键盘事件,并决定是否对其进行处理 - 允许某些媒体键,处理 escape、enter、space 事件。
logindProxy.py: 监听来自 logind 通过 dbus 发送的命令
manager.py: 这是核心,是主脑,是头号人物。 它生成 GrabHelper、FocusNavigator,以及 session 和 logind/ck 代理。 它处理从这些组件接收到的命令,以及我们自己的 dbus 服务(ScreensaverService)的命令。 它管理 status.py 中的所有标志,生成和销毁 stage。
monitorView.py: 这是一个放置在 stage 中的小部件,提供背景或屏幕保护程序插件视图。 每个显示器有一个,它们由 Stage 定位函数直接定位在每个显示器的位置。 它处理背景之间的过渡(在幻灯片放映期间)以及插件和壁纸之间的过渡。
service.py: 这是我们对 dbus 服务 "org.cinnamon.Screensaver" 的实现 - 通过此接口接收的命令会被发送到 manager 以获取响应和执行操作。 这会生成 manager。
sessionProxy.py: 监听 cinnamon-session 的空闲状态变化,并在其变化时通知 manager。
settings.py: 保存我们的 GSettings 实例,以及每个不同键的 getter。 还负责我们的 CinnamonDesktop BG 实例,并在设置更改时更新它。
stage.py: 这是我们的顶层窗口,一个 GtkWindow。 其大小被设置为 GdkScreen 的大小(一个恰好包含所有显示器的理论矩形)。 其核心是一个 GtkOverlay,我们将其用作类似窗口管理器的角色。 position_overlay_child 回调用于定位我们的子元素(Clock、UnlockWidget、MonitorView)。 可以通过 overlay.queue_resize() 强制调用此定位函数。 尽管该类被 manager 反复生成和销毁(当屏幕保护程序激活/去激活时),但它与 manager 进行较为自由的通信。
status.py: 一个全局状态跟踪器,被许多 widget 使用 - Active 表示屏幕保护程序 stage 存在,并且我们正在显示壁纸或类似内容。 Locked 表示我们需要输入密码才能解锁。 Awake 表示解锁对话框当前已显示。 focusChain 是应存储可聚焦 widget 列表的位置,tab 键将在这些 widget 之间导航。(目前这仅在 UnlockDialog 中实现)
trackers.py:用于轻松跟踪计时器和信号连接的实用工具。它基本上会为您执行任何清理工作,通常无需跟踪源 ID 或信号 ID。
unlock.py:提供解锁对话框,包括用户图像、名称、密码输入框和按钮
utils.py:各种似乎最好集中在一处的实用工具。
x11.py:X11 特定的焦点辅助函数 - 可选,python3-xlib 尚未在所有地方存在。