Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

添加文本输入支持以及key event修改 #5

Merged
merged 5 commits into from
Mar 7, 2024
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,5 @@

# Ignore Gradle build output directory
build

local.properties
3 changes: 2 additions & 1 deletion app/src/main/java/com/shxyke/MaaTouch/App.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,14 @@

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.nio.charset.StandardCharsets;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;


public class App {

private static final BufferedReader STDIN = new BufferedReader(new InputStreamReader(System.in));
private static final BufferedReader STDIN = new BufferedReader(new InputStreamReader(System.in, StandardCharsets.UTF_8));
private static final ServiceManager SERVICE_MANAGER = new ServiceManager();
private static final Controller CONTROLLER = new Controller(SERVICE_MANAGER);
private static final DisplayManager DISPLAY_MANAGER = SERVICE_MANAGER.getDisplayManager();
Expand Down
18 changes: 18 additions & 0 deletions app/src/main/java/com/shxyke/MaaTouch/ControlMessage.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ public final class ControlMessage {
public static final int TYPE_EVENT_TOUCH_RESET = 4;
public static final int TYPE_EVENT_KEY_DOWN = 5;
public static final int TYPE_EVENT_KEY_UP = 6;
public static final int TYPE_EVENT_TEXT = 7;
public static final int TYPE_EVENT_KEY = 8;

private int type;
private long pointerId;
Expand All @@ -21,18 +23,31 @@ public final class ControlMessage {
private int keycode;
private int repeat;
private int metaState;
private String text;

private ControlMessage(int type) {
this.type = type;
}

public static ControlMessage createTextEvent(String text) {
ControlMessage msg = new ControlMessage(TYPE_EVENT_TEXT);
msg.text = text;
return msg;
}
public static ControlMessage createKeyDownEvent(int keycode, int repeat, int metaState) {
ControlMessage msg = new ControlMessage(TYPE_EVENT_KEY_DOWN);
msg.keycode = keycode;
msg.repeat = repeat;
msg.metaState = metaState;
return msg;
}
public static ControlMessage createKeyEvent(int keycode) {
ControlMessage msg = new ControlMessage(TYPE_EVENT_KEY);
msg.keycode = keycode;
msg.repeat = 0;
msg.metaState = 0;
return msg;
}

public static ControlMessage createKeyUpEvent(int keycode, int repeat, int metaState) {
ControlMessage msg = new ControlMessage(TYPE_EVENT_KEY_UP);
Expand Down Expand Up @@ -103,6 +118,9 @@ public int getMetaState() {
public int getKeycode() {
return keycode;
}
public String getText() {
return text;
}

public int getRepeat() {
return repeat;
Expand Down
31 changes: 29 additions & 2 deletions app/src/main/java/com/shxyke/MaaTouch/ControlThread.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,37 @@
package com.shxyke.MaaTouch;

import java.util.HashMap;
import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue;

public class ControlThread {

private final LinkedBlockingQueue<Queue<ControlMessage>> queue;
private final Controller controller;
private final HashMap<Integer,KeyThread> KeyThreads;

public ControlThread(LinkedBlockingQueue<Queue<ControlMessage>> queue, Controller controller) {
this.queue = queue;
this.controller = controller;
KeyThreads = new HashMap<>();
}
public void KeyDown(int key)
{
if(!KeyThreads.containsKey(key))
{
KeyThread thread = new KeyThread(this.controller,key);
thread.start();
KeyThreads.put(key,thread);
}
}
public void KeyUp(int key)
{
if(KeyThreads.containsKey(key))
{
KeyThread thread = KeyThreads.get(key);
thread.stopThread();
KeyThreads.remove(key);
}
}

public void handleMessage(ControlMessage msg) {
Expand All @@ -28,10 +49,16 @@ public void handleMessage(ControlMessage msg) {
controller.injectTouchUp(msg.getPointerId());
break;
case ControlMessage.TYPE_EVENT_KEY_DOWN:
controller.injectKeyDown(msg.getKeycode(), msg.getRepeat(), msg.getMetaState());
KeyDown(msg.getKeycode());
break;
case ControlMessage.TYPE_EVENT_KEY_UP:
controller.injectKeyUp(msg.getKeycode(), msg.getRepeat(), msg.getMetaState());
KeyUp(msg.getKeycode());
break;
case ControlMessage.TYPE_EVENT_KEY:
controller.pressReleaseKeycode(msg.getKeycode());
break;
case ControlMessage.TYPE_EVENT_TEXT:
controller.setClipboard(msg.getText());
break;
case ControlMessage.TYPE_EVENT_WAIT:
try {
Expand Down
37 changes: 37 additions & 0 deletions app/src/main/java/com/shxyke/MaaTouch/Controller.java
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.shxyke.MaaTouch;

import com.shxyke.MaaTouch.wrappers.ClipboardManager;
import com.shxyke.MaaTouch.wrappers.InputManager;
import com.shxyke.MaaTouch.wrappers.ServiceManager;

import android.os.Build;
import android.os.SystemClock;
import android.view.InputDevice;
import android.view.InputEvent;
Expand Down Expand Up @@ -53,6 +55,41 @@ public void resetAll() {
}
}

public String getClipboardText() {
ClipboardManager clipboardManager = serviceManager.getClipboardManager();
if (clipboardManager == null) {
return null;
}
CharSequence s = clipboardManager.getText();
if (s == null) {
return null;
}
return s.toString();
}
public boolean setClipboardText(String text) {
ClipboardManager clipboardManager = serviceManager.getClipboardManager();
if (clipboardManager == null) {
return false;
}

String currentClipboard = getClipboardText();
if (currentClipboard != null && currentClipboard.equals(text)) {
return false;
}
return clipboardManager.setText(text);
}
public boolean pressReleaseKeycode(int keyCode) {
return injectKeyEvent(KeyEvent.ACTION_DOWN, keyCode, 0, 0)
&& injectKeyEvent(KeyEvent.ACTION_UP, keyCode, 0, 0);
}
public boolean setClipboard(String text) {
boolean ok = setClipboardText(text);
if (ok && Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
pressReleaseKeycode(KeyEvent.KEYCODE_PASTE);
}
return ok;
}

public boolean injectKeyDown(int keyCode, int repeat, int metaState) {
return injectKeyEvent(MotionEvent.ACTION_DOWN, keyCode, repeat, metaState);
}
Expand Down
16 changes: 15 additions & 1 deletion app/src/main/java/com/shxyke/MaaTouch/InputThread.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,12 @@ public class InputThread extends Thread {

private static final Pattern DOWN_PATTERN = Pattern.compile("d\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)");
private static final Pattern MOVE_PATTERN = Pattern.compile("m\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)\\s+(\\d+)");
private static final Pattern KEY_PATTERN = Pattern.compile("k\\s+(\\d+)\\s+([du])");
private static final Pattern KEY_PATTERN = Pattern.compile("k\\s+(\\d+)\\s+([duo])");
private static final Pattern WAIT_PATTERN = Pattern.compile("w\\s+(\\d+)");
private static final Pattern UP_PATTERN = Pattern.compile("u\\s+(\\d+)");
private static final Pattern COMMIT_PATTERN = Pattern.compile("c");
private static final Pattern RESET_PATTERN = Pattern.compile("r");
private static final Pattern TEXT_PATTERN = Pattern.compile("t\\s+(.+)");

private Queue<ControlMessage> subqueue = new LinkedList<>();

Expand All @@ -38,6 +39,9 @@ private void parseKey(String s) {
while (!subqueue.offer(ControlMessage.createKeyUpEvent(keycode, 0, 0)));
} else if (m.group(2).equals("d")) {
while (!subqueue.offer(ControlMessage.createKeyDownEvent(keycode, 0, 0)));
}else
{
while (!subqueue.offer(ControlMessage.createKeyEvent(keycode)));
}
}
}
Expand Down Expand Up @@ -104,6 +108,13 @@ private void parseTouchReset(String s) {
commitSubqueue();
}
}
private void parseText(String s) {
Matcher m = TEXT_PATTERN.matcher(s);
if (m.find()) {
String text = m.group(1);
while (!subqueue.offer(ControlMessage.createTextEvent(text)));
}
}

private void parseInput(String s) {
switch (s.charAt(0)) {
Expand All @@ -128,6 +139,9 @@ private void parseInput(String s) {
case 'k':
parseKey(s);
break;
case 't':
parseText(s);
break;
default:
break;
}
Expand Down
27 changes: 27 additions & 0 deletions app/src/main/java/com/shxyke/MaaTouch/KeyThread.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.shxyke.MaaTouch;

public class KeyThread extends Thread {
private boolean isRunning = true;
private final Controller controller;
private int keyCode;
private int repeat = 0;
public KeyThread(Controller controller,int keyCode) {
this.controller = controller;
this.keyCode = keyCode;
}
@Override
public void run() {
do {
controller.injectKeyDown(keyCode,repeat++,0);
try {
Thread.sleep(1000 / 20);
} catch (InterruptedException e) {
e.printStackTrace();
}
}while(this.isRunning);
controller.injectKeyUp(keyCode,0,0);
}
public void stopThread() {
this.isRunning = false;
}
}
12 changes: 11 additions & 1 deletion app/src/main/java/com/shxyke/MaaTouch/Ln.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import android.util.Log;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
* Log both to Android logger (so that logs are visible in "adb logcat") and standard output/error (so that they are visible in the terminal
* directly).
Expand Down Expand Up @@ -53,7 +56,14 @@ public static void d(String message) {
public static void i(String message) {
if (isEnabled(Level.INFO)) {
Log.i(TAG, message);
System.out.println(PREFIX + "INFO: " + message);
String info = "INFO: ";
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
LocalDateTime now = LocalDateTime.now();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss ");
String formattedDateTime = now.format(formatter);
info = formattedDateTime + info;
}
System.out.println(PREFIX + info + message);
}
}

Expand Down
103 changes: 103 additions & 0 deletions app/src/main/java/com/shxyke/MaaTouch/wrappers/ClipboardManager.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.shxyke.MaaTouch.wrappers;

import android.content.ClipData;
import android.os.Build;
import android.os.IInterface;

import com.shxyke.MaaTouch.Ln;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class ClipboardManager {
private final IInterface manager;
private Method getPrimaryClipMethod;
private Method setPrimaryClipMethod;
private boolean alternativeGetMethod;
private boolean alternativeSetMethod;

public ClipboardManager(IInterface manager) {
this.manager = manager;
}

private Method getGetPrimaryClipMethod() throws NoSuchMethodException {
if (getPrimaryClipMethod == null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class);
} else {
try {
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, int.class);
} catch (NoSuchMethodException e) {
getPrimaryClipMethod = manager.getClass().getMethod("getPrimaryClip", String.class, String.class, int.class);
alternativeGetMethod = true;
}
}
}
return getPrimaryClipMethod;
}

private Method getSetPrimaryClipMethod() throws NoSuchMethodException {
if (setPrimaryClipMethod == null) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class);
} else {
try {
setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, int.class);
} catch (NoSuchMethodException e) {
setPrimaryClipMethod = manager.getClass().getMethod("setPrimaryClip", ClipData.class, String.class, String.class, int.class);
alternativeSetMethod = true;
}
}
}
return setPrimaryClipMethod;
}

private static ClipData getPrimaryClip(Method method, boolean alternativeMethod, IInterface manager)
throws InvocationTargetException, IllegalAccessException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME);
}
if (alternativeMethod) {
return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, null, ServiceManager.USER_ID);
}
return (ClipData) method.invoke(manager, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
}

private static void setPrimaryClip(Method method, boolean alternativeMethod, IInterface manager, ClipData clipData)
throws InvocationTargetException, IllegalAccessException {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME);
} else if (alternativeMethod) {
method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, null, ServiceManager.USER_ID);
} else {
method.invoke(manager, clipData, ServiceManager.PACKAGE_NAME, ServiceManager.USER_ID);
}
}

public CharSequence getText() {
try {
Method method = getGetPrimaryClipMethod();
ClipData clipData = getPrimaryClip(method, alternativeGetMethod, manager);
if (clipData == null || clipData.getItemCount() == 0) {
return null;
}
return clipData.getItemAt(0).getText();
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
Ln.e("Could not invoke method", e);
return null;
}
}

public boolean setText(CharSequence text) {
try {
Method method = getSetPrimaryClipMethod();
ClipData clipData = ClipData.newPlainText(null, text);
setPrimaryClip(method, alternativeSetMethod, manager, clipData);
return true;
} catch (InvocationTargetException | IllegalAccessException | NoSuchMethodException e) {
Ln.e("Could not invoke method", e);
return false;
}
}

}
Loading
Loading