菜单

屏幕和输入管理

相关源文件

概述

scrcpy 中的屏幕和输入管理子系统负责在主机上显示 Android 设备屏幕并捕获用户输入以控制设备。本文档详细介绍了客户端应用程序如何管理屏幕渲染、处理窗口操作、处理输入事件,以及将它们转换为适当的消息发送给 Android 设备。有关设备如何处理这些消息的信息,请参阅 设备控制

架构

屏幕和输入管理子系统由两个主要组件组成,它们紧密协作

  1. 屏幕管理:处理窗口创建、帧渲染、方向、全屏模式和其他显示相关功能
  2. 输入管理:处理键盘、鼠标、触摸屏和游戏手柄输入,实现快捷方式并将控制消息发送到设备

主要组件图

来源: app/src/screen.h25-73 app/src/input_manager.h18-47

事件流图

来源: app/src/screen.c802-872 app/src/input_manager.c1013-1085

屏幕管理

屏幕管理组件负责处理与在主机上显示 Android 设备屏幕相关的所有事宜。它负责创建和管理窗口、渲染视频帧、处理窗口事件(大小调整、全屏切换等),并维护正确的方向和缩放。

结构和初始化

屏幕管理系统的核心是 sc_screen 结构,该结构维护显示窗口及相关组件的状态。它实现了 sc_frame_sink 接口以接收解码后的视频帧。

来源: app/src/screen.c325-485 app/src/screen.c488-511

屏幕以默认参数初始化,但保持隐藏状态,直到收到第一个视频帧。届时,窗口将调整为合适的尺寸并显示。初始化过程设置所需的数据结构,创建 SDL 窗口,并为帧渲染做好准备。

帧处理和渲染

当新的视频帧到达时,会发生以下过程:

  1. 帧被推送到帧缓冲区
  2. 触发一个事件,在 SDL 事件循环中进行处理
  3. 事件被处理时,帧被消耗
  4. 纹理使用新帧数据进行更新
  5. 帧被渲染到屏幕

渲染过程负责将内容正确缩放到适合窗口,同时保持纵横比。

来源: app/src/screen.c299-323 app/src/screen.c208-226 app/src/screen.c684-706

窗口管理

屏幕组件提供了几个函数来管理窗口状态:

功能描述
sc_screen_toggle_fullscreen()在窗口模式和全屏模式之间切换
sc_screen_resize_to_fit()将窗口调整到最佳尺寸(去除黑色边框)
sc_screen_resize_to_pixel_perfect()将窗口调整为精确的 1:1 像素映射
sc_screen_set_orientation()更改显示方向
sc_screen_set_paused()暂停/恢复显示更新

来源: app/src/screen.c736-914

方向和缩放

屏幕组件处理不同的显示方向(0°、90°、180°、270°)和翻转方向。当方向更改时,内容尺寸会相应更新,并在需要时调整窗口大小。

缩放的处理是为了保持正确的纵横比,如果需要,窗口会显示黑边。内容矩形(screen->rect)表示窗口内可见的内容部分。

来源: app/src/screen.c16-27 app/src/screen.c586-604 app/src/screen.c165-202

输入管理

输入管理组件处理来自各种来源(键盘、鼠标、触摸屏、游戏手柄)的用户输入,并将它们转换为适当的控制消息发送到 Android 设备。

结构和初始化

sc_input_manager 结构维护所有输入相关功能的状态。它引用用于不同输入类型(按键、鼠标、游戏手柄)的处理器,这些处理器实际处理事件。

来源: app/src/input_manager.h18-47 app/src/input_manager.c15-49

事件处理

当接收到 SDL 事件时,它会通过 sc_input_manager_handle_event() 函数转发给输入管理器。该函数确定事件类型并将其委托给相应的处理函数:

事件类型处理函数
键盘sc_input_manager_process_key()
文本输入sc_input_manager_process_text_input()
鼠标移动sc_input_manager_process_mouse_motion()
鼠标按钮sc_input_manager_process_mouse_button()
鼠标滚轮sc_input_manager_process_mouse_wheel()
触摸sc_input_manager_process_touch()
游戏手柄各种游戏手柄处理函数

来源: app/src/input_manager.c1013-1085

快捷键处理

输入管理器实现了各种键盘快捷键,用于控制客户端应用程序和 Android 设备

快捷键操作
MOD+f切换全屏
MOD+g调整到像素完美(1:1)
MOD+i切换 FPS 计数器
MOD+h发送 HOME 键
MOD+b发送 BACK 键
MOD+s发送 APP_SWITCH 键
MOD+m发送 MENU 键
MOD+下/上控制音量
MOD+p发送 POWER 键
MOD+o打开/关闭屏幕
MOD+左/右更改方向
MOD+c/x/v复制/剪切/粘贴
MOD+n展开通知面板
MOD+Shift+n折叠面板
MOD+Ctrl+r旋转设备屏幕

MOD 键是可配置的,但在大多数系统上默认为 Alt。

来源: app/src/input_manager.c370-558

坐标转换

输入管理的一个关键方面是处理鼠标和触摸事件时,将窗口坐标转换为帧坐标。此转换考虑了:

  1. 窗口内内容的缩放和黑色边框
  2. 显示器的当前方向(旋转)
  3. 系统上的高 DPI(HiDPI)缩放

来源: app/src/screen.c874-946 app/src/input_manager.c615-630

特殊输入功能

输入管理系统实现了一些特殊功能,以增强设备控制

  1. 虚拟手指:模拟第二个触摸点,用于捏合缩放、旋转和倾斜手势。按住 Ctrl 键并单击时,会在相对于屏幕中心反转的位置创建第二个虚拟触摸点。

  2. 鼠标绑定:可配置的鼠标按钮操作,允许不同的鼠标按钮触发 BACK、HOME、APP_SWITCH 等操作。

  3. 剪贴板同步:处理计算机和 Android 设备之间的文本复制和粘贴。

  4. 游戏手柄支持:处理游戏手柄输入并将其转发给设备。

来源: app/src/input_manager.c334-367 app/src/input_manager.c697-881

集成和交互

屏幕和输入的集成

屏幕和输入组件紧密集成,屏幕包含输入管理器的实例,输入管理器引用屏幕。这种双向关系允许:

  1. 输入事件访问屏幕属性以进行坐标转换
  2. 通过输入快捷键触发屏幕操作
  3. 根据屏幕状态启用/禁用鼠标捕获

来源: app/src/screen.h25-73 app/src/input_manager.h18-47

SDL 事件循环集成

两个组件都与 SDL 事件循环集成

  1. 屏幕处理 SC_EVENT_NEW_FRAME 和 SC_EVENT_SCREEN_INIT_SIZE 自定义事件
  2. 输入管理器处理标准的 SDL 输入事件
  3. 两个组件都使用相同的事件处理函数(sc_screen_handle_event

来源: app/src/screen.c802-872

关键数据结构

sc_screen 结构

屏幕管理的核心结构是 sc_screen,它包含:

成员描述
frame_sink用于接收帧的接口实现
display显示状态(渲染器、纹理)
im输入管理器实例
mc鼠标捕获实例(用于相对模式)
fb用于传入帧的帧缓冲区
fps_counterFPS 计数器
windowSDL 窗口
frame_size原始视频帧的大小
content_size旋转后的尺寸
orientation当前方向
rect窗口内内容的矩形
frame当前正在显示的 AVFrame
fullscreen是否处于全屏模式
maximized/minimized窗口状态
paused显示更新是否已暂停

来源: app/src/screen.h25-73

sc_input_manager 结构

输入管理的核心结构是 sc_input_manager,它包含

成员描述
controller将消息发送到设备的控制器
screen屏幕的引用
kp/mp/gp键盘/鼠标/游戏手柄处理器
mouse_bindings鼠标按钮操作的配置
sdl_shortcut_modsSDL 快捷键修饰符的表示
vfinger_down虚拟手指是否激活
mouse_buttons_state鼠标按钮的当前状态
key_repeat跟踪重复的按键操作
next_sequence用于剪贴板同步

来源: app/src/input_manager.h18-47

总结

屏幕和输入管理子系统是 scrcpy 的关键部分,负责显示设备屏幕和处理用户输入。它使用 SDL 进行窗口管理和事件处理,实现了多种功能来增强设备控制,并在不同的坐标系统之间进行转换,以确保无论屏幕方向或缩放如何,都能准确地处理输入。

主要方面包括

  • 窗口创建和管理
  • 帧渲染和缩放
  • 方向处理
  • 输入处理和快捷键
  • 用于精确输入定位的坐标转换
  • 虚拟手指等特殊功能,用于手势操作
  • 与 SDL 事件循环集成