mirror of
https://github.com/moonlight-stream/moonlight-android.git
synced 2025-07-20 11:33:06 +00:00
Raw mouse input is working
This commit is contained in:
parent
124037ce27
commit
3e017625a9
@ -1,7 +1,7 @@
|
||||
package com.limelight.binding.input.evdev;
|
||||
|
||||
public class EvdevEvent {
|
||||
public static final int EVDEV_MIN_EVENT_SIZE = 18;
|
||||
public static final int EVDEV_MIN_EVENT_SIZE = 16;
|
||||
public static final int EVDEV_MAX_EVENT_SIZE = 24;
|
||||
|
||||
/* Event types */
|
||||
|
@ -1,6 +1,7 @@
|
||||
package com.limelight.binding.input.evdev;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.ByteOrder;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
|
||||
@ -17,13 +18,6 @@ public class EvdevHandler {
|
||||
// but it's important that we get this right to avoid causing
|
||||
// system-wide input problems.
|
||||
|
||||
// Modify permissions to allow us access
|
||||
if (!EvdevReader.setPermissions(absolutePath, 0666)) {
|
||||
LimeLog.warning("Unable to chmod "+absolutePath);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Open the /dev/input/eventX file
|
||||
int fd = EvdevReader.open(absolutePath);
|
||||
if (fd == -1) {
|
||||
@ -46,9 +40,12 @@ public class EvdevHandler {
|
||||
|
||||
LimeLog.info("Grabbed device for raw mouse input: "+absolutePath);
|
||||
|
||||
ByteBuffer buffer = ByteBuffer.allocate(EvdevEvent.EVDEV_MAX_EVENT_SIZE);
|
||||
ByteBuffer buffer = ByteBuffer.allocate(EvdevEvent.EVDEV_MAX_EVENT_SIZE).order(ByteOrder.nativeOrder());
|
||||
|
||||
try {
|
||||
int deltaX = 0;
|
||||
int deltaY = 0;
|
||||
|
||||
while (!isInterrupted() && !shutdown) {
|
||||
EvdevEvent event = EvdevReader.read(fd, buffer);
|
||||
if (event == null) {
|
||||
@ -58,17 +55,20 @@ public class EvdevHandler {
|
||||
switch (event.type)
|
||||
{
|
||||
case EvdevEvent.EV_SYN:
|
||||
// Do nothing
|
||||
if (deltaX != 0 || deltaY != 0) {
|
||||
listener.mouseMove(deltaX, deltaY);
|
||||
deltaX = deltaY = 0;
|
||||
}
|
||||
break;
|
||||
|
||||
case EvdevEvent.EV_REL:
|
||||
switch (event.code)
|
||||
{
|
||||
case EvdevEvent.REL_X:
|
||||
listener.mouseMove(event.value, 0);
|
||||
deltaX = event.value;
|
||||
break;
|
||||
case EvdevEvent.REL_Y:
|
||||
listener.mouseMove(0, event.value);
|
||||
deltaY = event.value;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
@ -99,10 +99,6 @@ public class EvdevHandler {
|
||||
// Close the file
|
||||
EvdevReader.close(fd);
|
||||
}
|
||||
} finally {
|
||||
// Set permissions back
|
||||
EvdevReader.setPermissions(absolutePath, 0066);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
package com.limelight.binding.input.evdev;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import com.limelight.LimeLog;
|
||||
@ -10,7 +12,29 @@ public class EvdevReader {
|
||||
}
|
||||
|
||||
// Requires root to chmod /dev/input/eventX
|
||||
public static native boolean setPermissions(String fileName, int octalPermissions);
|
||||
public static boolean setPermissions(int octalPermissions) {
|
||||
String chmodString = String.format("chmod %o /dev/input/*\n", octalPermissions);
|
||||
|
||||
ProcessBuilder builder = new ProcessBuilder("su");
|
||||
|
||||
try {
|
||||
Process p = builder.start();
|
||||
|
||||
OutputStream stdin = p.getOutputStream();
|
||||
stdin.write(chmodString.getBytes("UTF-8"));
|
||||
stdin.write("exit\n".getBytes("UTF-8"));
|
||||
stdin.flush();
|
||||
|
||||
p.waitFor();
|
||||
p.destroy();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Returns the fd to be passed to other function or -1 on error
|
||||
public static native int open(String fileName);
|
||||
|
@ -13,7 +13,9 @@ public class EvdevWatcher {
|
||||
|
||||
private HashMap<String, EvdevHandler> handlers = new HashMap<String, EvdevHandler>();
|
||||
private boolean shutdown = false;
|
||||
private boolean init = false;
|
||||
private EvdevListener listener;
|
||||
private Thread startThread;
|
||||
|
||||
private FileObserver observer = new FileObserver(PATH, FileObserver.CREATE | FileObserver.DELETE) {
|
||||
@Override
|
||||
@ -34,6 +36,11 @@ public class EvdevWatcher {
|
||||
if ((event & FileObserver.CREATE) != 0) {
|
||||
LimeLog.info("Starting evdev handler for "+fileName);
|
||||
|
||||
if (!init) {
|
||||
// If this a real new device, update permissions again so we can read it
|
||||
EvdevReader.setPermissions(0666);
|
||||
}
|
||||
|
||||
EvdevHandler handler = new EvdevHandler(PATH + "/" + fileName, listener);
|
||||
handler.start();
|
||||
|
||||
@ -43,7 +50,7 @@ public class EvdevWatcher {
|
||||
if ((event & FileObserver.DELETE) != 0) {
|
||||
LimeLog.info("Halting evdev handler for "+fileName);
|
||||
|
||||
EvdevHandler handler = handlers.get(fileName);
|
||||
EvdevHandler handler = handlers.remove(fileName);
|
||||
if (handler != null) {
|
||||
handler.notifyDeleted();
|
||||
}
|
||||
@ -57,8 +64,12 @@ public class EvdevWatcher {
|
||||
}
|
||||
|
||||
public void start() {
|
||||
// Start watching for new files
|
||||
observer.startWatching();
|
||||
startThread = new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
// Get permissions to read the eventX files
|
||||
EvdevReader.setPermissions(0666);
|
||||
init = true;
|
||||
|
||||
// Rundown existing files and generate synthetic events
|
||||
File devInputDir = new File(PATH);
|
||||
@ -66,9 +77,33 @@ public class EvdevWatcher {
|
||||
for (File f : files) {
|
||||
observer.onEvent(FileObserver.CREATE, f.getName());
|
||||
}
|
||||
|
||||
// Done with initial onEvent calls
|
||||
init = false;
|
||||
|
||||
// Start watching for new files
|
||||
observer.startWatching();
|
||||
|
||||
synchronized (startThread) {
|
||||
// Wait to be awoken again by shutdown()
|
||||
try {
|
||||
startThread.wait();
|
||||
} catch (InterruptedException e) {}
|
||||
}
|
||||
|
||||
// Giveup eventX permissions
|
||||
EvdevReader.setPermissions(0066);
|
||||
}
|
||||
};
|
||||
startThread.start();
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
// Let start thread cleanup on it's own sweet time
|
||||
synchronized (startThread) {
|
||||
startThread.notify();
|
||||
}
|
||||
|
||||
// Stop the observer
|
||||
observer.stopWatching();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user