Skip to content

Commit

Permalink
RaiMan#473 Add initial support for Scrcpy library
Browse files Browse the repository at this point in the history
  • Loading branch information
TeofilisMartisius committed Sep 19, 2021
1 parent 2d68303 commit 6800233
Show file tree
Hide file tree
Showing 5 changed files with 429 additions and 1 deletion.
5 changes: 5 additions & 0 deletions API/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,11 @@
<version>0.10.9.1</version>
<!--License The New BSD License (https://www.py4j.org) -->
</dependency>
<dependency>
<artifactId>scrcpy</artifactId>
<groupId>org.scrcpy</groupId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>

<profiles>
Expand Down
199 changes: 199 additions & 0 deletions API/src/main/java/org/sikuli/script/ScrcpyRobot.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
package org.sikuli.script;

import org.scrcpy.IScrcpy;
import org.sikuli.script.support.IRobot;
import org.sikuli.script.support.IScreen;

import java.awt.*;

public class ScrcpyRobot implements IRobot {
final static int MAX_DELAY = 60000;

private final ScrcpyScreen screen;
private final IScrcpy scrcpy;
protected final Dimension dimension;
private Point mouse = new Point(0, 0);
private int autoDelay = 0;

public ScrcpyRobot(ScrcpyScreen screen, IScrcpy scrcpy, Dimension dimension) {
this.screen = screen;
this.scrcpy = scrcpy;
this.dimension = dimension;
}

private void autoDelay() {
delay(autoDelay);
}

private void afterEvent() {
// TODO: autoWaitForIdle();
autoDelay();
}

@Override
public void keyDown(String keys) {

}

@Override
public void keyUp(String keys) {

}

@Override
public void keyDown(int code) {

}

@Override
public void keyUp(int code) {

}

@Override
public void keyUp() {

}

@Override
public void pressModifiers(int modifiers) {

}

@Override
public void releaseModifiers(int modifiers) {

}

@Override
public void typeChar(char character, KeyMode mode) {

}

@Override
public void typeKey(int key) {

}

@Override
public void typeStarts() {

}

@Override
public void typeEnds() {

}

@Override
public void mouseMove(int x, int y) {
// TODO: Actually move mouse on Android device
mouse.x = x;
mouse.y = y;
}

@Override
public void mouseDown(int buttons) {
scrcpy.mouseDown(mouse, buttons);
afterEvent();
}

@Override
public int mouseUp(int buttons) {
scrcpy.mouseUp(mouse, buttons);
// TODO: Return buttons that are held
afterEvent();
return 0;
}

@Override
public void mouseReset() {
// TODO: set held buttons to 0
}

@Override
public void clickStarts() {
// no-op on RobotDesktop
}

@Override
public void clickEnds() {
// no-op on RobotDesktop
}

@Override
public void smoothMove(Location dest) {

}

@Override
public void smoothMove(Location src, Location dest, long ms) {

}

@Override
public void mouseWheel(int wheelAmt) {

}

@Override
public ScreenImage captureScreen(Rectangle screenRect) {
return screen.capture(screenRect);
}

@Override
public void waitForIdle() {

}

private void robotDelay(long ms) {
Thread thread = Thread.currentThread();
if (!thread.isInterrupted()) {
try {
Thread.sleep(ms);
} catch (final InterruptedException ignored) {
thread.interrupt(); // Preserve interrupt status
}
}
}

@Override
public void delay(int ms) {
if (ms < 0) {
return;
}
while (ms > MAX_DELAY) {
robotDelay(MAX_DELAY);
ms -= MAX_DELAY;
}
robotDelay(ms);
}

@Override
public void setAutoDelay(int ms) {
this.autoDelay = ms;
}

@Override
public Color getColorAt(int x, int y) {
ScreenImage img = screen.getLastScreenImageFromScreen();
int rgb = img.getImage().getRGB(x, y);
Color c = new Color(rgb);
return c;
}

@Override
public void cleanup() {

}

@Override
public boolean isRemote() {
return true;
}

@Override
public IScreen getScreen() {
return screen;
}
}
176 changes: 176 additions & 0 deletions API/src/main/java/org/sikuli/script/ScrcpyScreen.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
package org.sikuli.script;

import org.scrcpy.IScrcpy;
import org.sikuli.script.support.IRobot;
import org.sikuli.script.support.IScreen;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;

public class ScrcpyScreen implements IScreen {
private final IScrcpy scrcpy;
protected final int id;
protected final Dimension dimension;
protected BufferedImage img = null;

public ScrcpyScreen(int id, Dimension dimension, IScrcpy scrcpy) {
this.id = id;
this.scrcpy = scrcpy;
this.dimension = dimension;
this.scrcpy.registerScreenListener(dimension,
bufferedImage -> ScrcpyScreen.this.img = bufferedImage);
}
@Override
public int getID() {
return id;
}

@Override
public int getIdFromPoint(int srcx, int srcy) {
return id;
}

@Override
public String getIDString() {
return Integer.toString(this.id);
}

@Override
public IRobot getRobot() {
return new ScrcpyRobot(this, scrcpy, dimension);
}

ScreenImage toImage(Rectangle roi) {
if (this.img == null) {
BufferedImage img = new BufferedImage(this.dimension.width, this.dimension.height,
BufferedImage.TYPE_INT_RGB);
return new ScreenImage(roi, img);
} else {
return new ScreenImage(roi, this.img);
}
}
private Rectangle dimensionRectangle() {
return new Rectangle(0, 0, this.dimension.width, this.dimension.height);
}

@Override
public ScreenImage capture() {
return toImage(dimensionRectangle());
}

@Override
public ScreenImage capture(int x, int y, int w, int h) {
return toImage(new Rectangle(x, y, w, h));
}

@Override
public ScreenImage capture(Rectangle rect) {
return toImage(rect);
}

@Override
public ScreenImage capture(Region reg) {
Rectangle rect = new Rectangle(reg.x, reg.y, reg.w, reg.h);
return toImage(rect);
}

@Override
public ScreenImage userCapture(String string) {
throw new IllegalStateException("Not implemented: userCapture");
}

@Override
public ScreenImage getLastScreenImageFromScreen() {
return toImage(dimensionRectangle());
}

@Override
public String getLastScreenImageFile(String path, String name) throws IOException {
throw new IllegalStateException("Not implemented: getLastScreenImageFile");
}

@Override
public int getX() {
return 0;
}

@Override
public int getW() {
return dimension.width;
}

@Override
public int getY() {
return 0;
}

@Override
public int getH() {
return dimension.height;
}

@Override
public Rectangle getBounds() {
return dimensionRectangle();
}

@Override
public Rectangle getRect() {
return dimensionRectangle();
}

@Override
public boolean isOtherScreen() {
return true;
}

@Override
public Region setOther(Region element) {
return element.setOtherScreen(this);
}

@Override
public Location setOther(Location element) {
return element.setOtherScreen(this);
}

@Override
public Location newLocation(int x, int y) {
return new Location(x, y).setOtherScreen(this);
}

@Override
public Location newLocation(Location loc) {
return (new Location(loc)).copyTo(this);
}

@Override
public Region newRegion(int x, int y, int w, int h) {
Location loc = new Location(x, y);
loc.setOtherScreen(this);
return newRegion(loc, w, h);
}

@Override
public Region newRegion(Location loc, int width, int height) {
Location loc2 = loc.copyTo(this);
loc2.setOtherScreen(this);
return Region.create(loc2, width, height);
}

@Override
public Region newRegion(Region reg) {
throw new IllegalStateException("Not implemented: newRegion");
}

@Override
public void waitAfterAction() {

}

@Override
public Object action(String action, Object... args) {
return null;
}
}
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
libJXGrabKey.so
/nu/pattern/opencv/linux/x86_64/libopencv_java430[email protected]
/nu/pattern/opencv/linux/x86_64/libopencv_java451[email protected]
Loading

0 comments on commit 6800233

Please sign in to comment.