From f0fe9e66dc537b2f31f92fb12a9d71f2adceb890 Mon Sep 17 00:00:00 2001 From: lava114514 <2697345722@qq.com> Date: Fri, 19 Jun 2026 22:43:09 +0800 Subject: [PATCH 1/4] =?UTF-8?q?feat(kwin):python=E7=BB=91=E5=AE=9A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/binding/Python/maa/controller.py | 52 ++++++++++++++ test/python/binding_test.py | 91 ++++++++++++++++++------- 2 files changed, 119 insertions(+), 24 deletions(-) diff --git a/source/binding/Python/maa/controller.py b/source/binding/Python/maa/controller.py index 4d228bd551..7b3f9b0ea8 100644 --- a/source/binding/Python/maa/controller.py +++ b/source/binding/Python/maa/controller.py @@ -23,6 +23,7 @@ "RecordController", "PlayCoverController", "Win32Controller", + "KWinController", "GamepadController", "WlRootsController", "AndroidNativeController", @@ -1059,6 +1060,57 @@ def _set_wlroots_api_properties(self): ] +class KWinController(Controller): + """KWin 控制器 (Linux Wayland) / KWin controller (Linux Wayland) + + 通过 PipeWire / xdg-desktop-portal 截图,通过 /dev/uinput 模拟输入。 + Screencap via PipeWire / xdg-desktop-portal, input via /dev/uinput. + """ + + def __init__( + self, + device_node: str, + screen_width: int, + screen_height: int, + use_win32_vk_code: bool = False, + ): + """创建 KWin 控制器 / Create KWin controller + + Args: + device_node: uinput 设备节点路径 (如 "/dev/uinput") / uinput device node path + screen_width: 屏幕宽度(像素) / Screen width in pixels + screen_height: 屏幕高度(像素) / Screen height in pixels + use_win32_vk_code: 为 True 时按键被视为 Win32 VK 键码并转换为 Linux evdev 码; + 默认 False,按原始 evdev 码处理 + / When True, key codes are interpreted as Win32 Virtual-Key codes and translated + to Linux evdev codes internally; default False passes raw evdev codes through + + Raises: + RuntimeError: 如果创建失败 + """ + super().__init__() + self._set_kwin_api_properties() + + self._handle = Library.framework().MaaKWinControllerCreate( + device_node.encode(), + screen_width, + screen_height, + MaaBool(use_win32_vk_code), + ) + + if not self._handle: + raise RuntimeError("Failed to create KWin controller.") + + def _set_kwin_api_properties(self): + Library.framework().MaaKWinControllerCreate.restype = MaaControllerHandle + Library.framework().MaaKWinControllerCreate.argtypes = [ + ctypes.c_char_p, + ctypes.c_int32, + ctypes.c_int32, + MaaBool, + ] + + class DbgController(Controller): """调试控制器,轮播图片截图,基本输入操作直接返回成功 diff --git a/test/python/binding_test.py b/test/python/binding_test.py index 7e7225dfd1..78b10dea46 100644 --- a/test/python/binding_test.py +++ b/test/python/binding_test.py @@ -40,7 +40,7 @@ from maa.library import Library from maa.resource import Resource, ResourceEventSink -from maa.controller import DbgController, CustomController, Win32Controller, ControllerEventSink +from maa.controller import DbgController, CustomController, Win32Controller, KWinController, ControllerEventSink from maa.tasker import Tasker, TaskerEventSink from maa.toolkit import Toolkit from maa.custom_action import CustomAction @@ -835,38 +835,81 @@ def test_win32_relative_move(): print(" PASS: win32 relative_move") -# ============================================================================ -# 主入口 -# ============================================================================ +def test_kwin_controller_create(): + print("\n=== test_kwin_controller_create ===") + # KWinController 仅在 Linux 上可用,且需要 MaaKWinControllerCreate API 存在 + try: + controller = KWinController( + device_node="/dev/uinput", + screen_width=1920, + screen_height=1080, + use_win32_vk_code=False, + ) + print(f" KWinController created: {controller}") -if __name__ == "__main__": - print(f"MaaFw Version: {Library.version()}") + # 检查连接前状态 + print(f" connected: {controller.connected}") + print(f" uuid: {controller.uuid}") + print(f" info: {controller.info}") - Toolkit.init_option(install_dir / "bin") + # 验证 info 中的类型 + info = controller.info + assert isinstance(info, dict), "info should be a dict" + assert "type" in info, "info should contain 'type'" + assert info["type"] == "KWin", "KWin controller type should be 'KWin'" - # 测试各模块 API - resource = test_resource_api() - controller = test_controller_api() - test_buffer_api() - tasker = test_tasker_api(resource, controller) + # 测试 post_inactive (空操作,应总是成功) + controller.post_inactive().wait() - # 验证自定义识别和动作被调用 - if not analyzed or not runned: - print("FAIL: custom recognition or action not called") - raise RuntimeError("custom recognition or action not called") + print(" PASS: KWinController creation") - # 测试 CustomController - test_custom_controller() + except AttributeError as e: + if "MaaKWinControllerCreate" in str(e): + print(" SKIP: MaaKWinControllerCreate not available in this build") + else: + raise - # 测试 Toolkit - test_toolkit() + except RuntimeError as e: + # KWin 控制器创建可能因缺少 /dev/uinput 权限等环境问题失败 + print(f" SKIP: KWinController not available in this environment ({e})") - # 测试 BackgroundManagedKeys 选项 - test_background_managed_keys_api() - # 测试 Win32 relative_move 正路径 - test_win32_relative_move() +# ============================================================================ +# 主入口 +# ============================================================================ + + +if __name__ == "__main__": + print(f"MaaFw Version: {Library.version()}") + + Toolkit.init_option(install_dir / "bin") + # + # # 测试各模块 API + # resource = test_resource_api() + # controller = test_controller_api() + # test_buffer_api() + # tasker = test_tasker_api(resource, controller) + # + # # 验证自定义识别和动作被调用 + # if not analyzed or not runned: + # print("FAIL: custom recognition or action not called") + # raise RuntimeError("custom recognition or action not called") + # + # # 测试 CustomController + # test_custom_controller() + # + # # 测试 Toolkit + # test_toolkit() + # + # # 测试 BackgroundManagedKeys 选项 + # test_background_managed_keys_api() + # + # # 测试 Win32 relative_move 正路径 + # test_win32_relative_move() + + # 测试 KWinController 创建 + test_kwin_controller_create() print("\n" + "=" * 50) print("All binding tests passed!") From 54756d0634535c6fd37f8c4ac8d13d3ec3f68ce6 Mon Sep 17 00:00:00 2001 From: lava114514 <2697345722@qq.com> Date: Sat, 20 Jun 2026 16:20:50 +0800 Subject: [PATCH 2/4] =?UTF-8?q?fix(kwin):=E5=8F=96=E6=B6=88=E9=94=99?= =?UTF-8?q?=E8=AF=AF=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/python/binding_test.py | 50 ++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/test/python/binding_test.py b/test/python/binding_test.py index 78b10dea46..73f3fe4e0b 100644 --- a/test/python/binding_test.py +++ b/test/python/binding_test.py @@ -884,31 +884,31 @@ def test_kwin_controller_create(): print(f"MaaFw Version: {Library.version()}") Toolkit.init_option(install_dir / "bin") - # - # # 测试各模块 API - # resource = test_resource_api() - # controller = test_controller_api() - # test_buffer_api() - # tasker = test_tasker_api(resource, controller) - # - # # 验证自定义识别和动作被调用 - # if not analyzed or not runned: - # print("FAIL: custom recognition or action not called") - # raise RuntimeError("custom recognition or action not called") - # - # # 测试 CustomController - # test_custom_controller() - # - # # 测试 Toolkit - # test_toolkit() - # - # # 测试 BackgroundManagedKeys 选项 - # test_background_managed_keys_api() - # - # # 测试 Win32 relative_move 正路径 - # test_win32_relative_move() - - # 测试 KWinController 创建 + + # 测试各模块 API + resource = test_resource_api() + controller = test_controller_api() + test_buffer_api() + tasker = test_tasker_api(resource, controller) + + # 验证自定义识别和动作被调用 + if not analyzed or not runned: + print("FAIL: custom recognition or action not called") + raise RuntimeError("custom recognition or action not called") + + # 测试 CustomController + test_custom_controller() + + # 测试 Toolkit + test_toolkit() + + # 测试 BackgroundManagedKeys 选项 + test_background_managed_keys_api() + + # 测试 Win32 relative_move 正路径 + test_win32_relative_move() + + 测试 KWinController 创建 test_kwin_controller_create() print("\n" + "=" * 50) From 1d13b6157a720bc285129abf010dfe58c7766b18 Mon Sep 17 00:00:00 2001 From: lava114514 <2697345722@qq.com> Date: Sat, 20 Jun 2026 16:23:49 +0800 Subject: [PATCH 3/4] =?UTF-8?q?fix(kwin):=E4=BF=AE=E5=A4=8D=E9=80=BB?= =?UTF-8?q?=E8=BE=91=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- source/binding/Python/maa/controller.py | 7 ++++++- test/python/binding_test.py | 8 +------- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/source/binding/Python/maa/controller.py b/source/binding/Python/maa/controller.py index 7b3f9b0ea8..635de29de4 100644 --- a/source/binding/Python/maa/controller.py +++ b/source/binding/Python/maa/controller.py @@ -1091,8 +1091,13 @@ def __init__( super().__init__() self._set_kwin_api_properties() + if not hasattr(Library.framework(), "MaaKWinControllerCreate"): + raise RuntimeError( + "MaaKWinControllerCreate API is not available in the current build." + ) + self._handle = Library.framework().MaaKWinControllerCreate( - device_node.encode(), + os.fsencode(os.fspath(device_node)), screen_width, screen_height, MaaBool(use_win32_vk_code), diff --git a/test/python/binding_test.py b/test/python/binding_test.py index 73f3fe4e0b..f8daa3e5e2 100644 --- a/test/python/binding_test.py +++ b/test/python/binding_test.py @@ -864,14 +864,8 @@ def test_kwin_controller_create(): print(" PASS: KWinController creation") - except AttributeError as e: - if "MaaKWinControllerCreate" in str(e): - print(" SKIP: MaaKWinControllerCreate not available in this build") - else: - raise - except RuntimeError as e: - # KWin 控制器创建可能因缺少 /dev/uinput 权限等环境问题失败 + # KWin 控制器创建可能因 API 缺失或缺少 /dev/uinput 权限等环境问题失败 print(f" SKIP: KWinController not available in this environment ({e})") From 098b48d2a51fd3d24d9cd3e2ecd2463778620785 Mon Sep 17 00:00:00 2001 From: lava114514 <2697345722@qq.com> Date: Sat, 20 Jun 2026 16:39:54 +0800 Subject: [PATCH 4/4] =?UTF-8?q?fix(kwin):=E4=BF=AE=E5=A4=8D=E5=A1=AB?= =?UTF-8?q?=E9=94=99=E7=9A=84=E6=B3=A8=E9=87=8A?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- test/python/binding_test.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/python/binding_test.py b/test/python/binding_test.py index f8daa3e5e2..975cb5f40e 100644 --- a/test/python/binding_test.py +++ b/test/python/binding_test.py @@ -902,7 +902,7 @@ def test_kwin_controller_create(): # 测试 Win32 relative_move 正路径 test_win32_relative_move() - 测试 KWinController 创建 + # 测试 KWinController 创建 test_kwin_controller_create() print("\n" + "=" * 50)