/* Copyright (c) 2017, Sikuli.org, sikulix.com * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this software; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, * USA. */ package org.sikuli.vnc; import org.sikuli.basics.Debug; import org.sikuli.basics.Settings; import org.sikuli.script.*; import org.sikuli.util.OverlayCapturePrompt; import org.sikuli.util.ScreenHighlighter; import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; import java.util.List; public class VNCScreen extends Region implements IScreen, Closeable { private final VNCClient client; private volatile boolean closed; private final IRobot robot; private ScreenImage lastScreenImage; private static List<VNCScreen> screens = new ArrayList<>(); public static VNCScreen start(String theIP, int thePort, String password, int cTimeout, int timeout) throws IOException { VNCScreen scr = new VNCScreen(VNCClient.connect(theIP, thePort, password, true)); screens.add(scr); return scr; } public static VNCScreen start(String theIP, int thePort, int cTimeout, int timeout) throws IOException { VNCScreen scr = new VNCScreen(VNCClient.connect(theIP, thePort, null, true)); screens.add(scr); return scr; } public void stop() { try { close(); } catch (IOException e) { Debug.error("VNCScreen: stop: %s", e.getMessage()); } screens.remove(this); } public static void stopAll() { for (VNCScreen scr : screens) { try { scr.close(); } catch (IOException e) { Debug.error("VNCScreen: stopAll: %s", e.getMessage()); } } } private VNCScreen(final VNCClient client) { this.client = client; this.robot = new VNCRobot(this); setOtherScreen(this); setRect(getBounds()); initScreen(this); new Thread(new Runnable() { @Override public void run() { try { client.processMessages(); } catch (RuntimeException e) { if (!closed) { throw e; } } } }).start(); client.refreshFramebuffer(); //RunTime.get().pause(5); } @Override public void close() throws IOException { closed = true; client.close(); screens.clear(); } @Override public IRobot getRobot() { return robot; } @Override public Rectangle getBounds() { return client.getBounds(); } @Override public ScreenImage capture() { return capture(getBounds()); } @Override public ScreenImage capture(Region reg) { return capture(reg.x, reg.y, reg.w, reg.h); } @Override public ScreenImage capture(Rectangle rect) { return capture(rect.x, rect.y, rect.width, rect.height); } @Override public ScreenImage capture(int x, int y, int w, int h) { BufferedImage image = client.getFrameBuffer(x, y, w, h); ScreenImage img = new ScreenImage( new Rectangle(x, y, w, h), image ); lastScreenImage = img; return img; } public void showTarget(Location loc) { showTarget(loc, Settings.SlowMotionDelay); } protected void showTarget(Location loc, double secs) { if (Settings.isShowActions()) { ScreenHighlighter overlay = new ScreenHighlighter(this, null); overlay.showTarget(loc, (float) secs); } } @Override public int getID() { return 0; } @Override public int getIdFromPoint(int srcx, int srcy) { return 0; } @Override protected <PSIMRL> Location getLocationFromTarget(PSIMRL target) throws FindFailed { Location location = super.getLocationFromTarget(target); if (location != null) { location.setOtherScreen(this); } return location; } @Override public ScreenImage getLastScreenImageFromScreen() { return lastScreenImage; } @Override public ScreenImage userCapture(final String msg) { if (robot == null) { return null; } final OverlayCapturePrompt prompt = new OverlayCapturePrompt(this); Thread th = new Thread() { @Override public void run() { prompt.prompt(msg); } }; th.start(); boolean hasShot = false; ScreenImage simg = null; int count = 0; while (!hasShot) { this.wait(0.1f); if (count++ > 300) { break; } if (prompt == null) { continue; } if (prompt.isComplete()) { simg = prompt.getSelection(); if (simg != null) { lastScreenImage = simg; hasShot = true; } prompt.close(); } } prompt.close(); return simg; } public VNCClient getClient() { return client; } }