From 78aa3d3c71dbe8d22f44998d957099c706b39c00 Mon Sep 17 00:00:00 2001 From: tongtongstudio Date: Mon, 3 Aug 2026 11:09:37 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=94=AF=E6=8C=81=E6=8C=89=E9=94=AE?= =?UTF-8?q?=E5=88=86=E7=A6=BB=E4=BA=8B=E4=BB=B6=E4=B8=8E=E9=94=AE=E7=9B=98?= =?UTF-8?q?=E6=8D=95=E8=8E=B7=EF=BC=8C=E5=B9=B6=E4=BC=98=E5=8C=96UI?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 后端与前端新增 keyAction 参数,支持按键按下/抬起独立事件,保持向下兼容 - 前端控制栏支持 pointerdown/pointerup 长按,新增键盘捕获输入框,映射浏览器按键到 Android KeyEvent - 重构顶栏布局:用户区右置并添加在线指示器、状态文本省略,优化窄屏响应式表现 - 控制栏录制按钮组防拆行,分辨率/帧率选择器自适应收缩,全局样式增强 - 修复 AdminAuthFilter 中 doFilter 被异常捕获导致误返回 401 的问题 - 移除管理后台中用户 admin 角色及相关 UI 与 API - 更新信令前端环境代理地址,修正路由名称大小写 --- .../input/AccessibilityInputUtils.java | 2 +- .../controlled/input/InputCommandHandler.java | 9 +- .../ttstd/controlled/input/InputExecutor.java | 7 +- .../controlled/input/RootShellInputUtils.java | 2 +- .../controlled/input/ShellInputUtils.java | 2 +- .../controlled/input/SystemInputUtils.java | 26 ++- WebRTCControllerWeb/src/App.vue | 11 +- .../src/components/ControlBar.vue | 197 ++++++++++++++++-- .../src/services/WebRtcController.js | 5 +- .../src/store/controllerStore.js | 2 + WebRTCControllerWeb/src/style.css | 130 +++++++++++- .../signaling/config/AdminAuthFilter.java | 15 +- WebRTCSignalServerWeb/.env | 2 +- WebRTCSignalServerWeb/src/api/admin.ts | 8 - WebRTCSignalServerWeb/src/api/request.ts | 4 +- .../src/views/users/UserList.vue | 31 +-- 16 files changed, 374 insertions(+), 79 deletions(-) diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/AccessibilityInputUtils.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/AccessibilityInputUtils.java index c108df0..29ca8ec 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/AccessibilityInputUtils.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/AccessibilityInputUtils.java @@ -53,7 +53,7 @@ public class AccessibilityInputUtils implements InputExecutor { } @Override - public void injectKeyEvent(int keyCode) { + public void injectKeyEvent(int keyCode, int keyAction) { KeyboardAccessibilityService svc = getService(); if (svc == null) { Log.w(TAG, "Accessibility service not running, cannot inject key"); diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputCommandHandler.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputCommandHandler.java index b1c9fab..4016da2 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputCommandHandler.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputCommandHandler.java @@ -133,8 +133,13 @@ public class InputCommandHandler { private void handleKey(ControlMessage command) { int keyCode = command.getKeyCode(); - Log.d(TAG, "Key press: " + keyCode); - inputExecutor.injectKeyEvent(keyCode); + if (keyCode == 0) { + Log.w(TAG, "Ignoring KEY command with keyCode=0"); + return; + } + int keyAction = command.getKeyAction(); + Log.d(TAG, "Key press: keyCode=" + keyCode + ", keyAction=" + keyAction); + inputExecutor.injectKeyEvent(keyCode, keyAction); } private void handleSwipe(ControlMessage command) { diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputExecutor.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputExecutor.java index af26acb..603cb5a 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputExecutor.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/InputExecutor.java @@ -7,7 +7,12 @@ public interface InputExecutor { void injectTap(int x, int y); void injectLongPress(int x, int y); void injectSwipe(int x1, int y1, int x2, int y2, long duration); - void injectKeyEvent(int keyCode); + /** + * 注入按键事件。 + * @param keyCode Android KeyEvent 键值(如 KeyEvent.KEYCODE_A)。 + * @param keyAction 动作:0=ACTION_DOWN,1=ACTION_UP;传 -1 表示“按下并立即抬起”的一次性点击(兼容旧行为)。 + */ + void injectKeyEvent(int keyCode, int keyAction); void injectMotionEvent(int action, int x, int y); /** diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/RootShellInputUtils.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/RootShellInputUtils.java index 1da7f8e..c7d9c86 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/RootShellInputUtils.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/RootShellInputUtils.java @@ -31,7 +31,7 @@ public class RootShellInputUtils implements InputExecutor { } @Override - public void injectKeyEvent(int keyCode) { + public void injectKeyEvent(int keyCode, int keyAction) { executeRootCommand(String.format(Locale.US, "input keyevent %d", keyCode)); } diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/ShellInputUtils.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/ShellInputUtils.java index cbe1bca..85f8244 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/ShellInputUtils.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/ShellInputUtils.java @@ -25,7 +25,7 @@ public class ShellInputUtils implements InputExecutor { } @Override - public void injectKeyEvent(int keyCode) { + public void injectKeyEvent(int keyCode, int keyAction) { executeShellCommand(String.format(Locale.US, "input keyevent %d", keyCode)); } diff --git a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/SystemInputUtils.java b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/SystemInputUtils.java index d91d878..e24ea6a 100644 --- a/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/SystemInputUtils.java +++ b/WebRTCControlled/app/src/main/java/com/ttstd/controlled/input/SystemInputUtils.java @@ -2,6 +2,7 @@ package com.ttstd.controlled.input; import android.os.SystemClock; import android.util.Log; +import android.util.SparseLongArray; import android.view.InputDevice; import android.view.InputEvent; import android.view.KeyEvent; @@ -21,6 +22,7 @@ public class SystemInputUtils implements InputExecutor { private static final int INJECT_INPUT_EVENT_MODE_ASYNC = 0; private static final int INJECT_INPUT_EVENT_MODE_WAIT_FOR_FINISH = 2; private long mDownTime; + private final SparseLongArray mKeyDownTimes = new SparseLongArray(); public SystemInputUtils() { try { @@ -69,10 +71,28 @@ public class SystemInputUtils implements InputExecutor { } @Override - public void injectKeyEvent(int keyCode) { + public void injectKeyEvent(int keyCode, int keyAction) { + if (mInputManager == null || mInjectInputEventMethod == null) { + return; + } long now = SystemClock.uptimeMillis(); - injectKeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode); - injectKeyEvent(now, SystemClock.uptimeMillis(), KeyEvent.ACTION_UP, keyCode); + if (keyAction < 0) { + // 向后兼容:未指定动作时执行“按下并立即抬起”的一次性点击 + injectKeyEvent(now, now, KeyEvent.ACTION_DOWN, keyCode); + injectKeyEvent(now, now, KeyEvent.ACTION_UP, keyCode); + return; + } + int action = (keyAction == 0) ? KeyEvent.ACTION_DOWN : KeyEvent.ACTION_UP; + long downTime; + if (action == KeyEvent.ACTION_DOWN) { + downTime = now; + mKeyDownTimes.put(keyCode, downTime); + } else { + // 抬起时复用按下时刻,保证同一次按键周期内 downTime 一致(用于长按/组合键识别) + downTime = mKeyDownTimes.get(keyCode, now); + mKeyDownTimes.delete(keyCode); + } + injectKeyEvent(downTime, now, action, keyCode); } @Override diff --git a/WebRTCControllerWeb/src/App.vue b/WebRTCControllerWeb/src/App.vue index 409f8f7..8ae9b12 100644 --- a/WebRTCControllerWeb/src/App.vue +++ b/WebRTCControllerWeb/src/App.vue @@ -27,10 +27,7 @@ async function onLogout() {