feat: 完整的 macOS 原生截图和控制以及 MaaToolkit 的 DesktopWindow 支持#1116
feat: 完整的 macOS 原生截图和控制以及 MaaToolkit 的 DesktopWindow 支持#1116MistEO merged 61 commits intoMaaXYZ:mainfrom
Conversation
测试: mkdir -p source/binding/Python/maa/bin && cp build/bin/Debug/*.dylib source/binding/Python/maa/bin/ && pip install -e source/binding/Python/ python tools/ImageCropper/main.py 选择 2 | Win32Controller 将列出MacOS窗口列表
- 实现 `MaaMacOSControllerCreate` 函数,用于创建 macOS 控制器。 - 为 macOS 控制单元添加了 CMake 配置。 - 创建 `MacOSControlUnitAPI` 及其在 `MacOSControlUnitMgr` 中的实现。 - 新增 `GlobalEventInput`,用于处理 macOS 上的输入事件。 - 新增 `ScreenCaptureKitScreencap`,用于使用 ScreenCaptureKit 捕获屏幕内容。 - 为 macOS 控制器添加了 Python 绑定,包括屏幕截图和输入方法的枚举。 - 更新了 ControlUnit API,使其包含 macOS 特有的方法和类型。
ScreenCaptureKit 默认返回 BGRA ,现以在截图时进行转换
There was a problem hiding this comment.
Hey - 我发现了 5 个问题,并给出了一些总体反馈:
- 在
GlobalEventInput里,当构造函数传入的显式pid参数非 0 时会被忽略,而是直接用get_window_info的结果覆盖pid_;建议在pid非 0 时优先使用该值(仅在pid == 0时才回退到窗口获取到的 PID),并且更加稳健地处理get_window_info失败的情况,以避免出现pid_ = -1的状态。 - macOS 的版本检查不一致:
MacOSControlUnitMgr::connect只在macOS 12.3及以上进行保护,而ScreenCaptureKitScreencap::screencap要求@available(macOS 14.0, *);建议统一这些检查(以及公开 API 文档),让调用方能获得清晰且正确的 ScreenCaptureKit 截图功能的最低版本要求。 - 在
Interactor::select_controller中,当 macOS 控制器不受支持时会递归调用select_controller();可以考虑改为迭代循环,以避免递归无限增长,并让在多次无效选择时的控制流更容易理解。
给 AI Agent 的提示
请解决本次代码审查中的所有评论:
## 整体评论
- 在 `GlobalEventInput` 里,当构造函数传入的显式 `pid` 参数非 0 时会被忽略,而是直接用 `get_window_info` 的结果覆盖 `pid_`;建议在 `pid` 非 0 时优先使用该值(仅在 `pid == 0` 时才回退到窗口获取到的 PID),并且更加稳健地处理 `get_window_info` 失败的情况,以避免出现 `pid_ = -1` 的状态。
- macOS 的版本检查不一致:`MacOSControlUnitMgr::connect` 只在 `macOS 12.3` 及以上进行保护,而 `ScreenCaptureKitScreencap::screencap` 要求 `@available(macOS 14.0, *)`;建议统一这些检查(以及公开 API 文档),让调用方能获得清晰且正确的 ScreenCaptureKit 截图功能的最低版本要求。
- 在 `Interactor::select_controller` 中,当 macOS 控制器不受支持时会递归调用 `select_controller()`;可以考虑改为迭代循环,以避免递归无限增长,并让在多次无效选择时的控制流更容易理解。
## 逐条评论
### Comment 1
<location> `source/MaaMacOSControlUnit/Screencap/ScreenCaptureKitScreencap.mm:20-29` </location>
<code_context>
+ if (@available(macOS 14.0, *)) {
</code_context>
<issue_to_address>
**issue (bug_risk):** ScreenCaptureKit 的 macOS 版本要求与 manager 不一致,会在 12.3–13.x 上出问题。
MacOSControlUnitMgr::connect 只对 macOS 12.3+ 做了限制,但 ScreenCaptureKitScreencap::screencap 现在限制为 macOS 14.0+。在 12.3–13.x 上,connect() 会成功,而所有 screencap 调用都会记录错误日志并返回 std::nullopt。请:
- 要么将这里的可用性降低为 @available(macOS 12.3, *),
- 要么把 MacOSControlUnitMgr::connect 的要求提高到 14.0+,并相应更新错误提示信息。
这些检查需要保持一致,以避免出现这种部分可用但实际不可用的状态。
</issue_to_address>
### Comment 2
<location> `source/MaaMacOSControlUnit/Manager/MacOSControlUnitMgr.cpp:36-45` </location>
<code_context>
+ return false;
+ }
+
+ switch (screencap_method_) {
+ case MaaMacOSScreencapMethod_ScreenCaptureKit:
+ screencap_ = std::make_shared<ScreenCaptureKitScreencap>(window_id_);
+ break;
+
+ default:
+ LogError << "Unknown screencap method: " << static_cast<int>(screencap_method_);
+ break;
+ }
+
+ switch (input_method_) {
+ case MaaMacOSInputMethod_GlobalEvent:
+ input_ = std::make_shared<GlobalEventInput>(window_id_, pid_);
+ break;
+
+ default:
+ LogError << "Unknown input method: " << static_cast<int>(input_method_);
+ break;
+ }
+
+ connected_ = true;
+ return true;
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** 即使 screencap 或 input 初始化失败,connect() 也会报告成功。
对于未知的 screencap_method_ / input_method_,我们只是记录日志,并把 screencap_ / input_ 留在 nullptr,同时仍然设置 connected_ = true。调用者随后会在 nullptr 上出现运行时错误。建议仅在 screencap_ 和 input_ 都非空时才设置 connected_,并在创建失败时返回 false(或回退到默认实现),以便 "connected" 能真实地反映可用状态。
</issue_to_address>
### Comment 3
<location> `source/MaaPiCli/Impl/Configurator.cpp:239-248` </location>
<code_context>
std::cout << MAA_NS::utf8_to_crt(std::format("\t\t{}\n", format_win32_config(config_.configuration().win32)));
}
break;
+ case InterfaceData::Controller::Type::MacOS: {
+ const auto& macos = config_.configuration().macos;
+ std::cout << MAA_NS::utf8_to_crt(std::format(
</code_context>
<issue_to_address>
**suggestion (bug_risk):** 运行时 macOS screencap/input 方法忽略了 Configuration::macos 中用户选择的值。
这里的代码只使用来自 `interface.json` 的 `controller.macos.screencap_method` / `input_method`,并且仅在这些字符串为空或无效时才使用默认值。但 `Interactor::select_macos` 会把用户选择写入 `config_.configuration().macos.screencap_method` / `input_method`,而这里从未读取这些字段,因此 CLI/配置中的覆盖设置完全不起作用。
如果希望支持用户覆盖,可能需要在 `controller.macos.*` 和 `configuration().macos.*` 之间定义一个清晰的优先级(例如一个为空时回退到另一个),这样运行时行为才能体现用户的修改。
</issue_to_address>
### Comment 4
<location> `source/MaaMacOSControlUnit/Input/GlobalEventInput.mm:222-231` </location>
<code_context>
+ static std::map<char, CGKeyCode> key_map
</code_context>
<issue_to_address>
**issue (bug_risk):** input_text 没有正确处理需要 Shift 的标点符号,并且对大小写字母重复了映射。
目前字母的大小写都映射到相同的 key code,`need_shift` 通过 `isupper(c)` 推断,这只对字母有效。对于 `'!'`、`'@'` 这类标点,现在直接映射到数字键行的 key code,但没有设置 `need_shift`,因此 `'!'` 实际上会输入裸 `'1'`。
请修改映射,使其只存储基础(未按下 Shift 的)字符,并单独确定是否需要 Shift(例如 `'!' -> ('1', needs_shift=true)`,或者通过一个并行表实现)。这将修复标点输入问题,并避免在 `key_map` 中重复 A/a … Z/z 的条目。
</issue_to_address>
### Comment 5
<location> `sample/cpp/main.cpp:172` </location>
<code_context>
+ std::string window_name = MaaToolkitDesktopWindowGetWindowName(window_handle);
+
+ if (window_name.find("关于本机") != std::string::npos) {
+ window_id = reinterpret_cast<uintptr_t>(MaaToolkitDesktopWindowGetHandle(window_handle));
+ break;
+ }
</code_context>
<issue_to_address>
**nitpick (bug_risk):** 将 window handle 转换为 window_id 时存在潜在的窄化问题。
`MaaToolkitDesktopWindowGetHandle` 返回 `void*`,你先将其转换为 `uintptr_t`,再存入 `uint32_t`。在 64 位平台上,这是一次窄化转换,可能会截断句柄,即使 `CGWindowID` 当前是 32 位。从构建 `DesktopWindow` 开始就获取实际的 `CGWindowID` 会更安全,或者至少在这里直接转换为 `uint32_t`,并加上说明性的注释,说明底层 ID 按约定是 32 位的。
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据反馈改进后续的审查。
Original comment in English
Hey - I've found 5 issues, and left some high level feedback:
- In
GlobalEventInput, the constructor ignores the explicitpidparameter when it is non-zero and blindly overwritespid_fromget_window_info; consider honoring a non-zeropid(and only falling back to the window-derived PID whenpid == 0) and handling the failure case fromget_window_infomore robustly to avoid ending up withpid_ = -1. - The macOS version checks are inconsistent:
MacOSControlUnitMgr::connectonly guards onmacOS 12.3whileScreenCaptureKitScreencap::screencaprequires@available(macOS 14.0, *); consider aligning these checks (and the public API documentation) so callers get a clear and correct minimum-version requirement for ScreenCaptureKit-based capture. - In
Interactor::select_controller, the recursive call toselect_controller()when the macOS controller is unsupported could be replaced with an iterative loop to avoid unbounded recursion and to make the control flow easier to follow for repeated invalid selections.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In `GlobalEventInput`, the constructor ignores the explicit `pid` parameter when it is non-zero and blindly overwrites `pid_` from `get_window_info`; consider honoring a non-zero `pid` (and only falling back to the window-derived PID when `pid == 0`) and handling the failure case from `get_window_info` more robustly to avoid ending up with `pid_ = -1`.
- The macOS version checks are inconsistent: `MacOSControlUnitMgr::connect` only guards on `macOS 12.3` while `ScreenCaptureKitScreencap::screencap` requires `@available(macOS 14.0, *)`; consider aligning these checks (and the public API documentation) so callers get a clear and correct minimum-version requirement for ScreenCaptureKit-based capture.
- In `Interactor::select_controller`, the recursive call to `select_controller()` when the macOS controller is unsupported could be replaced with an iterative loop to avoid unbounded recursion and to make the control flow easier to follow for repeated invalid selections.
## Individual Comments
### Comment 1
<location> `source/MaaMacOSControlUnit/Screencap/ScreenCaptureKitScreencap.mm:20-29` </location>
<code_context>
+ if (@available(macOS 14.0, *)) {
</code_context>
<issue_to_address>
**issue (bug_risk):** macOS version requirements for ScreenCaptureKit are inconsistent with the manager and will break on 12.3–13.x.
MacOSControlUnitMgr::connect only gates on macOS 12.3+, but ScreenCaptureKitScreencap::screencap is now limited to macOS 14.0+. On 12.3–13.x, connect() will succeed while all screencap calls log an error and return std::nullopt. Please either:
- lower this availability to @available(macOS 12.3, *), or
- raise MacOSControlUnitMgr::connect to 14.0+ and update its error messaging accordingly.
These checks need to stay aligned to avoid this partial, non-functional state.
</issue_to_address>
### Comment 2
<location> `source/MaaMacOSControlUnit/Manager/MacOSControlUnitMgr.cpp:36-45` </location>
<code_context>
+ return false;
+ }
+
+ switch (screencap_method_) {
+ case MaaMacOSScreencapMethod_ScreenCaptureKit:
+ screencap_ = std::make_shared<ScreenCaptureKitScreencap>(window_id_);
+ break;
+
+ default:
+ LogError << "Unknown screencap method: " << static_cast<int>(screencap_method_);
+ break;
+ }
+
+ switch (input_method_) {
+ case MaaMacOSInputMethod_GlobalEvent:
+ input_ = std::make_shared<GlobalEventInput>(window_id_, pid_);
+ break;
+
+ default:
+ LogError << "Unknown input method: " << static_cast<int>(input_method_);
+ break;
+ }
+
+ connected_ = true;
+ return true;
+}
</code_context>
<issue_to_address>
**issue (bug_risk):** connect() reports success even when screencap or input initialization fails.
For unknown screencap_method_ / input_method_, we only log and leave screencap_ / input_ as nullptr, yet still set connected_ = true. Callers then hit runtime failures on nullptr. Consider only setting connected_ when both screencap_ and input_ are non-null, and returning false (or falling back to a default implementation) if creation fails so that "connected" reflects actual readiness for use.
</issue_to_address>
### Comment 3
<location> `source/MaaPiCli/Impl/Configurator.cpp:239-248` </location>
<code_context>
std::cout << MAA_NS::utf8_to_crt(std::format("\t\t{}\n", format_win32_config(config_.configuration().win32)));
}
break;
+ case InterfaceData::Controller::Type::MacOS: {
+ const auto& macos = config_.configuration().macos;
+ std::cout << MAA_NS::utf8_to_crt(std::format(
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Runtime macOS screencap/input methods ignore user-selected values in Configuration::macos.
This code only uses `controller.macos.screencap_method` / `input_method` from `interface.json`, defaulting them only when those strings are empty/invalid. But `Interactor::select_macos` writes the user’s choices into `config_.configuration().macos.screencap_method` / `input_method`, which are never read here, so CLI/config overrides have no effect.
If user overrides are intended, you likely want a clear precedence order between `controller.macos.*` and `configuration().macos.*` (e.g., one falling back to the other when empty) so runtime behavior reflects user edits.
</issue_to_address>
### Comment 4
<location> `source/MaaMacOSControlUnit/Input/GlobalEventInput.mm:222-231` </location>
<code_context>
+ static std::map<char, CGKeyCode> key_map
</code_context>
<issue_to_address>
**issue (bug_risk):** input_text doesn’t correctly handle shifted punctuation and duplicates mapping for upper/lowercase letters.
Currently both cases of a letter map to the same key code and `need_shift` is inferred via `isupper(c)`, which only works for letters. Punctuation like `'!'` and `'@'` are mapped directly to number-row key codes without marking `need_shift`, so `'!'` results in a bare `'1'`.
Please change the mapping to only store base (unshifted) characters and determine Shift separately (e.g., `'!' -> ('1', needs_shift=true)` or via a parallel table). This will fix punctuation input and avoid duplicating A/a … Z/z entries in `key_map`.
</issue_to_address>
### Comment 5
<location> `sample/cpp/main.cpp:172` </location>
<code_context>
+ std::string window_name = MaaToolkitDesktopWindowGetWindowName(window_handle);
+
+ if (window_name.find("关于本机") != std::string::npos) {
+ window_id = reinterpret_cast<uintptr_t>(MaaToolkitDesktopWindowGetHandle(window_handle));
+ break;
+ }
</code_context>
<issue_to_address>
**nitpick (bug_risk):** Potential narrowing when converting the window handle to window_id.
`MaaToolkitDesktopWindowGetHandle` returns a `void*`, which you cast to `uintptr_t` and then store in a `uint32_t`. On 64-bit platforms this is a narrowing conversion and could truncate the handle, even if `CGWindowID` is currently 32-bit. It would be safer to obtain the actual `CGWindowID` when building `DesktopWindow`, or at least cast directly to `uint32_t` here with a clarifying comment that the underlying ID is 32-bit by contract.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
source/MaaMacOSControlUnit/Screencap/ScreenCaptureKitScreencap.mm
Outdated
Show resolved
Hide resolved
|
🐂🍺 @neko-para 来瞅瞅 |
There was a problem hiding this comment.
Pull request overview
为 MaaFramework 引入 macOS 原生控制器能力(截图/输入/窗口枚举),并将其贯通到 MaaToolkit、CLI、Sample 与 Python 绑定中,以便在 macOS 上实现基于窗口的自动化控制与工具链支持。
Changes:
- 新增 macOS 控制单元动态库(MaaMacOSControlUnit),提供 ScreenCaptureKit 截图与全局事件输入注入能力,并通过
MaaMacOSControllerCreate暴露到 Framework API / Python 绑定。 - MaaToolkit 增加 macOS 窗口枚举实现(ScreenCaptureKit Shareable Content),并在 CLI / ImageCropper / C++ sample 中接入 macOS 选择窗口与运行。
- 构建系统增加
WITH_MACOS_CONTROLLER选项与 Objective-C++(.mm)编译/格式化支持。
Reviewed changes
Copilot reviewed 33 out of 33 changed files in this pull request and generated 11 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/ImageCropper/main.py | ImageCropper 增加 MacOSController 选项与窗口选择流程 |
| source/include/ProjectInterface/Types.h | ProjectInterface 配置/运行参数增加 macOS controller 类型与字段 |
| source/include/LibraryHolder/ControlUnit.h | LibraryHolder 增加 MaaMacOSControlUnit 动态库装载入口 |
| source/include/ControlUnit/MacOSControlUnitAPI.h | 新增 MaaMacOSControlUnit C API 声明 |
| source/include/ControlUnit/ControlUnitAPI.h | 增加 MacOSControlUnitAPI 类型与 handle typedef |
| source/binding/Python/maa/define.py | Python 绑定新增 macOS 截图/输入枚举 |
| source/binding/Python/maa/controller.py | Python 绑定新增 MacOSController 类与 ctypes 声明 |
| source/MaaToolkit/DesktopWindow/DesktopWindowMacOSFinder.mm | 实现 macOS 窗口枚举(ScreenCaptureKit) |
| source/MaaToolkit/DesktopWindow/DesktopWindowMacOSFinder.cpp | 删除旧的 macOS Finder 占位实现 |
| source/MaaToolkit/CMakeLists.txt | 工具库支持编译 .mm 并链接 ScreenCaptureKit 等框架 |
| source/MaaPiCli/Impl/Runner.cpp | CLI Runner 增加 macOS controller 创建分支 |
| source/MaaPiCli/Impl/Configurator.cpp | CLI 配置解析增加 macOS screencap/input method 映射与 runtime 生成 |
| source/MaaPiCli/CLI/interactor.h | CLI 交互器声明新增 macOS 选择流程 |
| source/MaaPiCli/CLI/interactor.cpp | CLI 交互增加 macOS 窗口选择(title regex)与配置写入 |
| source/MaaMacOSControlUnit/Screencap/ScreenCaptureKitScreencap.mm | macOS 截图实现(SCScreenshotManager) |
| source/MaaMacOSControlUnit/Screencap/ScreenCaptureKitScreencap.h | 截图类声明 |
| source/MaaMacOSControlUnit/Manager/MacOSControlUnitMgr.h | macOS 控制单元管理器声明(connect/screencap/input 等) |
| source/MaaMacOSControlUnit/Manager/MacOSControlUnitMgr.cpp | macOS 控制单元管理器实现(方法选择/路由) |
| source/MaaMacOSControlUnit/Input/GlobalEventInput.mm | 基于 CGEventPost 的全局事件输入注入实现 |
| source/MaaMacOSControlUnit/Input/GlobalEventInput.h | 输入类声明与窗口信息获取/偏移计算 |
| source/MaaMacOSControlUnit/CMakeLists.txt | MaaMacOSControlUnit 目标与 macOS frameworks 链接 |
| source/MaaMacOSControlUnit/Base/UnitBase.h | 控制单元输入/截图基类接口 |
| source/MaaMacOSControlUnit/API/MacOSControlUnitAPI.cpp | MaaMacOSControlUnit 导出函数实现(Create/Destroy/GetVersion) |
| source/MaaFramework/CMakeLists.txt | Framework 在启用 macOS controller 时增加依赖 |
| source/MaaFramework/API/MaaFramework.cpp | 新增 MaaMacOSControllerCreate Framework API 实现 |
| source/LibraryHolder/ControlUnit/ControlUnit.cpp | 实现 MacOSControlUnitLibraryHolder::create_control_unit |
| source/CMakeLists.txt | 顶层 source 增加 MaaMacOSControlUnit 子目录 |
| sample/interface.json | sample interface 增加 macOS controller 配置示例 |
| sample/cpp/main.cpp | C++ sample 增加 macOS controller 创建示例 |
| include/MaaFramework/MaaDef.h | 公共 API 增加 macOS screencap/input method 常量定义 |
| include/MaaFramework/Instance/MaaController.h | 公共 API 增加 MaaMacOSControllerCreate 声明与注释 |
| CMakeLists.txt | 新增 WITH_MACOS_CONTROLLER 选项并在非 macOS 自动禁用 |
| .clang-format | 增加 ObjC 格式化配置块 |
| connected_ = true; | ||
| return true; | ||
| } |
There was a problem hiding this comment.
connect() unconditionally sets connected_ = true and returns true even if input_/screencap_ were not created successfully. Only mark connected when initialization succeeds, and otherwise return false so callers don’t proceed with a broken controller.
source/MaaMacOSControlUnit/Screencap/ScreenCaptureKitScreencap.mm
Outdated
Show resolved
Hide resolved
| #include <AppKit/AppKit.h> | ||
| #include <ApplicationServices/ApplicationServices.h> | ||
| #include <CoreFoundation/CoreFoundation.h> | ||
| #include <tuple> |
There was a problem hiding this comment.
This file uses std::map, isupper/tolower, and usleep but does not include the corresponding headers (<map>, <cctype>, <unistd.h>). Relying on transitive includes is fragile and can break builds on different toolchains; add the missing includes explicitly.
| #include <tuple> | |
| #include <tuple> | |
| #include <map> | |
| #include <cctype> | |
| #include <unistd.h> |
|
输入能生效就行? 我反正之前截图很容易就搞出来了, 输入一直没发生效, 不知道啥情况 |
|
Windows build 有问题,test 不用管之前 main 就有问题) 然后再看下 AI 提的意见有没有要调整的 |
|
有测试过点击输入能生效吗? 按理说需要Accessibility的权限, 而这个东西应该是要打包成app, 配置entitlements才行? 目前的UI实现应该都还没支持这种, 要么是根本就没打app, 要么是entitlements随便写的 |
|
我之前考虑的方案是fw本身拉一个子app起来, 然后基于这个app去做权限申请啥的, 但是复杂度很高 |
是不是权限问题?我测试时候是给vscode了权限然后内嵌终端运行 我的系统是10.15 https://github.com/YJBeetle/MacOSScreenCaptureDemo |
我觉得打包app 这种事情不应该maafw去管 ,比如我是用qt做这个事情 , 然后如果不打算给打包的就给终端权限就好了 我明后天再测试一下重置权限后的权限申请行为 这句可以重置权限 注意列表会丢失 |
ok我注意到了AI的意见 我看完了确实有一些想法 等我再改改再合并 |
|
是, 给终端权限是可以, 虽然我感觉怪怪的( |
source/binding/NodeJS/src/apis/controller.cpp 中 Win32ControllerImpl::ctor 返回 nullptr 时,原来返回 info.Env().Null(),但 JS 的 new 操作符遇到非对象返回值会使用 this(一个空壳对象),导致 ctrl 非空。现在改为抛出 TypeError,使 try/catch 能正确捕获,test/nodejs/binding.ts 中 ctrl 保持 null,if (!ctrl || !target) 时跳过测试。
|
测试失败检查时,发现 NodeJS binding 中的一个错误 ,之前在 Controller 创建失败后会得到无内容的空壳对象 ,因此无法像 test/nodejs/binding.ts +231 中的那样 使用 |
|
目前我这里工作已经完成 @neko-para 来看看没问题的话应该也许可以合并了 |
之前就是设计的ctor总是能成功,比如destroy后也是空壳对象来着。不过现在确实不太方便判断,这个我想下有没有更好的办法 哦好像也确实不太一样, 就先这样吧 |
|
因为我这里设计上node的binding里面的抛的异常都是不正常的错误,比如参数传错了或者正常情况下不会失败的fw函数失败了。不是很想让业务逻辑掺杂进来。不过确实在错误的平台上创建不支持的控制器不太好说是不是不正常的( |
|
@MistEO 玛丽看看外围的东西呢, 我补了下 |
|
另外, 感觉可能最好还是在toolkit里面提供一些包括申请权限之类的工具函数, 方便binding用, 这个我晚点看看具体需要哪些. 各个ui会涉及到相关逻辑, 但是应该都不方便写oc |
那要这么说的话 其实是不是在Maa*ControllerCreate里throw出来更合适一些 不过这个得看整个项目的风格习惯 |
其实我也这么觉得 但是不知道放哪里合适 目前我在这里 test/macos_test/MacOSPermission.* 单独写了几个 你可以看看要不要诺去toolkit里 |
C函数里面肯定不throw, 说的是js侧的throw; 不过Create函数目前就是对应的构造函数, 所以现在这样也还可以 |
|
|
||
| // 将 UTF-8 转换为 UTF-16(UniChar),直接通过 CGEventKeyboardSetUnicodeString 注入, | ||
| // 无需 keycode 映射,支持任意 Unicode 字符(含中文、emoji 等) | ||
| NSString* ns_text = [NSString stringWithUTF8String:text.c_str()]; |
There was a problem hiding this comment.
MaaUtils/Encoding 里面有 to_u16 看看能不能用这个
There was a problem hiding this comment.
看了下MaaUtils/Encoding 的 to_u16 返回的是std::wstring , 苹果和linux上sizeof(wchar_t)是4,其实不是utf16 , 这边需要的其实是uint16数组
There was a problem hiding this comment.
所以目前MaaUtils/Encoding 的 to_u16 没法用 除非换掉wstring成std::u16string之类的
| { | ||
| // 将 UTF-8 转换为 UTF-16(UniChar),直接通过 CGEventKeyboardSetUnicodeString 注入, | ||
| // 无需 keycode 映射,支持任意 Unicode 字符(含中文、emoji 等) | ||
| NSString* ns_text = [NSString stringWithUTF8String:text.c_str()]; |
| bool PostToPidInput::scroll(int dx, int dy) | ||
| { | ||
| (void)dx; | ||
| (void)dy; |
There was a problem hiding this comment.
有的 修改了 (其实mm就是cpp 同时多了一些方言)
@MistEO 这个我看了下感觉可以加下, 我目前想的是加三个函数 查询授权, 触发获取授权, 打开设置 然后用枚举来提供具体的到底是截屏还是辅助功能 |
可以啊,toolkit 加几个接口,不过你打算设计成啥样的 |
#define MaaMacOSPermissionScreenCapture 1
#define MaaMacOSPermissionAccessibility 2
typedef int32_t MaaMacOSPermission;
MaaBool MaaToolkitMacOSCheckPermission(MaaMacOSPermission perm);
MaaBool MaaToolkitMacOSRequestPermission(MaaMacOSPermission perm);
MaaBool MaaToolkitMacOSRevealPermissionSettings(MaaMacOSPermission perm);大概这种? |
|
草, 点歪了( |
|
toolkit 单开一个 PR 讨论吧,这个要是没问题可以先合了? |
|
也行 |
|
🎉 |
本 PR 为 MaaFramework 引入了对 macOS 平台支持,实现了截图、输入、窗口枚举,并适配了相关 CLI 工具和 Python 绑定。
主要变更 (Key Changes)
截图 (Screencap): 基于 ScreenCaptureKit 实现屏幕采集。
输入 (Input): 实现 GlobalEventInput,支持全局事件模拟。
API 接入: 完成了 MaaMacOSControllerCreate 接口定义及其在 MacOSControlUnitMgr 中的实现。
窗口枚举: 实现了适配 macOS 12.3+ 的窗口枚举功能 (DesktopWindowMacOSFinder),支持通过窗口标题搜索 WindowID。
MaaPiCli: 为 CLI 工具添加了 macOS 控制器的配置选项与交互支持。
ImageCropper: 工具端适配,现在支持在 macOS 上进行窗口选择和截图切图。
Python Binding: 同步更新 Python 接口,支持 macOS 特有的截图和输入枚举类型。
CMake: 完善了 macOS 下的编译。
代码规范: 更新了 .clang-format 以支持 Objective-C 格式化。
测试情况
已在 macOS 环境下完成以下验证:
C++ Sample: 可通过窗口标题正常查找 WindowID 并启动任务,任务正常执行。
ImageCropper: 可正常枚举窗口并完成截图。
Summary by Sourcery
添加原生的 macOS 控制器支持,包括屏幕捕获、输入以及窗口枚举,并将其贯通到 CLI、框架 API、工具包、示例以及 Python 绑定中。
新特性:
MaaMacOSControllerCreateAPI。MacOSController类及相关枚举,并为 ImageCropper 工具和 C++ 示例添加 macOS 控制器支持。增强:
Original summary in English
Summary by Sourcery
Add native macOS controller support with screencap, input, and window enumeration, and wire it through CLI, framework API, toolkit, samples, and Python bindings.
New Features:
Enhancements: