diff --git a/nbproject/build-impl.xml b/nbproject/build-impl.xml index 0aa92bc..8fdd3eb 100644 --- a/nbproject/build-impl.xml +++ b/nbproject/build-impl.xml @@ -826,7 +826,7 @@ is divided into following sections: - + diff --git a/nbproject/genfiles.properties b/nbproject/genfiles.properties index cabd327..a140f92 100644 --- a/nbproject/genfiles.properties +++ b/nbproject/genfiles.properties @@ -4,5 +4,5 @@ build.xml.stylesheet.CRC32=8064a381@1.63.0.46 # This file is used by a NetBeans-based IDE to track changes in generated files such as build-impl.xml. # Do not edit this file. You may delete it but then the IDE will never regenerate such files for you. nbproject/build-impl.xml.data.CRC32=b5a554e2 -nbproject/build-impl.xml.script.CRC32=85fc706a -nbproject/build-impl.xml.stylesheet.CRC32=4e931b40@1.63.0.46 +nbproject/build-impl.xml.script.CRC32=824194f0 +nbproject/build-impl.xml.stylesheet.CRC32=cdba79fa@1.67.0.46 diff --git a/src/com/annimon/socketfiletransfer/Main.java b/src/com/annimon/socketfiletransfer/Main.java index e5d1270..cb9b548 100644 --- a/src/com/annimon/socketfiletransfer/Main.java +++ b/src/com/annimon/socketfiletransfer/Main.java @@ -38,6 +38,8 @@ public class Main { } else if (args[0].equalsIgnoreCase("message")) { String message = args[1]; client.getManager().sendMessage(message); + } else if (args[0].equalsIgnoreCase("cursor")) { + client.getManager().startCursorControl(); } client.close(); } catch (IOException ex) { diff --git a/src/com/annimon/socketfiletransfer/OperationListener.java b/src/com/annimon/socketfiletransfer/OperationListener.java index 183ac9e..99f0cf4 100644 --- a/src/com/annimon/socketfiletransfer/OperationListener.java +++ b/src/com/annimon/socketfiletransfer/OperationListener.java @@ -1,5 +1,9 @@ package com.annimon.socketfiletransfer; +import com.annimon.socketfiletransfer.operations.CursorOperation; +import com.annimon.socketfiletransfer.operations.MessageOperation; +import com.annimon.socketfiletransfer.operations.FileOperation; +import com.annimon.socketfiletransfer.operations.Operation; import com.annimon.socketfiletransfer.util.ExceptionHandler; import java.io.DataInputStream; import java.io.DataOutputStream; @@ -12,9 +16,10 @@ import java.net.Socket; */ public class OperationListener { - protected static final int + public static final int MODE_FILE_TRANSFER = 1, - MODE_MESSAGE_TRANSFER = 2; + MODE_MESSAGE_TRANSFER = 2, + MODE_CURSOR_CONTROL = 3; protected DataInputStream dis; protected DataOutputStream dos; @@ -38,6 +43,9 @@ public class OperationListener { case MODE_MESSAGE_TRANSFER: operation = new MessageOperation(dis); break; + case MODE_CURSOR_CONTROL: + operation = new CursorOperation(dis); + break; default: return; } diff --git a/src/com/annimon/socketfiletransfer/OperationManager.java b/src/com/annimon/socketfiletransfer/OperationManager.java index b3d9326..45e03d7 100644 --- a/src/com/annimon/socketfiletransfer/OperationManager.java +++ b/src/com/annimon/socketfiletransfer/OperationManager.java @@ -1,6 +1,13 @@ package com.annimon.socketfiletransfer; +import com.annimon.socketfiletransfer.operations.CursorOperation; +import com.annimon.socketfiletransfer.operations.MessageOperation; +import com.annimon.socketfiletransfer.operations.FileOperation; +import com.annimon.socketfiletransfer.operations.Operation; +import java.awt.Dimension; import java.io.File; +import javax.swing.JDialog; +import javax.swing.JPanel; /** * Менеджер операций с данными. @@ -17,5 +24,18 @@ public class OperationManager extends OperationListener { Operation operation = new MessageOperation(dos); operation.startClientSide(message); } + + public void startCursorControl() throws Exception { + JPanel panel = new JPanel(); + panel.setPreferredSize(new Dimension(100, 100)); + + JDialog dialog = new JDialog(); + dialog.add(panel); + dialog.pack(); + dialog.setVisible(true); + + Operation operation = new CursorOperation(dos); + operation.startClientSide(panel); + } } diff --git a/src/com/annimon/socketfiletransfer/operations/CursorOperation.java b/src/com/annimon/socketfiletransfer/operations/CursorOperation.java new file mode 100644 index 0000000..8b29483 --- /dev/null +++ b/src/com/annimon/socketfiletransfer/operations/CursorOperation.java @@ -0,0 +1,130 @@ +package com.annimon.socketfiletransfer.operations; + +import com.annimon.socketfiletransfer.OperationManager; +import com.annimon.socketfiletransfer.util.ExceptionHandler; +import com.annimon.socketfiletransfer.util.RobotUtils; +import java.awt.AWTException; +import java.awt.Point; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.io.DataInputStream; +import java.io.DataOutputStream; +import java.io.IOException; +import javax.swing.JPanel; + +/** + * Управление курсором. + * @author aNNiMON + */ +public class CursorOperation implements Operation { + + private static final int + NONE = -1, + TYPE_MOVE = 1, + TYPE_CLICK = 2, + STOP = 10; + + private DataInputStream dis; + private DataOutputStream dos; + + private RobotUtils robot; + private int currentX, currentY, currentMode; + + private CursorOperation() { + try { + robot = new RobotUtils(); + } catch (AWTException ex) { + ExceptionHandler.handle(ex); + } + } + + public CursorOperation(DataInputStream dis) { + this(); + this.dis = dis; + } + + public CursorOperation(DataOutputStream dos) { + this(); + this.dos = dos; + } + + @Override + public void startServerSide() throws IOException { + int type = NONE; + do { + type = dis.readInt(); + if (type == TYPE_MOVE) { + int dx = dis.readInt(); + int dy = dis.readInt(); + robot.moveCursor(dx, dy); + } else if (type == TYPE_CLICK) { + System.out.println("Click"); + robot.clickPoint(robot.getCursorPosition()); + } + } while (type != STOP); + } + + @Override + public void startClientSide(Object... params) throws Exception { + JPanel panel = (JPanel) params[0]; + + Point cursor = robot.getCursorPosition(); + System.out.println("Start tracking cursor. Now: " + cursor.toString()); + dos.writeInt(OperationManager.MODE_CURSOR_CONTROL); + MouseTracker tracker = new MouseTracker(); + panel.addMouseListener(tracker); + panel.addMouseMotionListener(tracker); + while (tracker.running) { + Thread.sleep(10); + } + /*while (true) { + dos.writeInt(NONE); + if (cursor.distance(robot.getCursorPosition()) > 0.5) { + Point newPosition = robot.getCursorPosition(); + int dx = newPosition.x - cursor.x; + int dy = newPosition.y - cursor.y; + cursor = newPosition; + dos.writeInt(TYPE_MOVE); + dos.writeInt(dx); + dos.writeInt(dy); + } + if ( (cursor.x == 0) && (cursor.y == 0) ) break; + }*/ + //System.out.println("Operation stopped"); + } + + public class MouseTracker extends MouseAdapter { + + boolean running = true; + + @Override + public void mouseMoved(MouseEvent e) { + int x = e.getX(); + int y = e.getY(); + + try { + dos.writeInt(TYPE_MOVE); + dos.writeInt(x - currentX); + dos.writeInt(y - currentY); + } catch (IOException ex) { } + + currentX = x; + currentY = y; + } + + @Override + public void mouseClicked(MouseEvent e) { + try { + dos.writeInt(TYPE_CLICK); + dos.writeInt(currentX); + dos.writeInt(currentY); + } catch (IOException ex) { } + + if ( (e.getX() == 0) && (e.getY() == 0) ) { + running = false; + } + } + + } + +} diff --git a/src/com/annimon/socketfiletransfer/FileOperation.java b/src/com/annimon/socketfiletransfer/operations/FileOperation.java similarity index 91% rename from src/com/annimon/socketfiletransfer/FileOperation.java rename to src/com/annimon/socketfiletransfer/operations/FileOperation.java index 5dbcfe3..8276178 100644 --- a/src/com/annimon/socketfiletransfer/FileOperation.java +++ b/src/com/annimon/socketfiletransfer/operations/FileOperation.java @@ -1,5 +1,6 @@ -package com.annimon.socketfiletransfer; +package com.annimon.socketfiletransfer.operations; +import com.annimon.socketfiletransfer.OperationManager; import com.annimon.socketfiletransfer.util.Config; import com.annimon.socketfiletransfer.util.ExceptionHandler; import java.io.DataInputStream; diff --git a/src/com/annimon/socketfiletransfer/MessageOperation.java b/src/com/annimon/socketfiletransfer/operations/MessageOperation.java similarity index 80% rename from src/com/annimon/socketfiletransfer/MessageOperation.java rename to src/com/annimon/socketfiletransfer/operations/MessageOperation.java index c41a413..cedd161 100644 --- a/src/com/annimon/socketfiletransfer/MessageOperation.java +++ b/src/com/annimon/socketfiletransfer/operations/MessageOperation.java @@ -1,5 +1,7 @@ -package com.annimon.socketfiletransfer; +package com.annimon.socketfiletransfer.operations; +import com.annimon.socketfiletransfer.util.MessageHistory; +import com.annimon.socketfiletransfer.OperationManager; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; diff --git a/src/com/annimon/socketfiletransfer/Operation.java b/src/com/annimon/socketfiletransfer/operations/Operation.java similarity index 73% rename from src/com/annimon/socketfiletransfer/Operation.java rename to src/com/annimon/socketfiletransfer/operations/Operation.java index 8508980..09afb04 100644 --- a/src/com/annimon/socketfiletransfer/Operation.java +++ b/src/com/annimon/socketfiletransfer/operations/Operation.java @@ -1,4 +1,4 @@ -package com.annimon.socketfiletransfer; +package com.annimon.socketfiletransfer.operations; /** * diff --git a/src/com/annimon/socketfiletransfer/MessageHistory.java b/src/com/annimon/socketfiletransfer/util/MessageHistory.java similarity index 87% rename from src/com/annimon/socketfiletransfer/MessageHistory.java rename to src/com/annimon/socketfiletransfer/util/MessageHistory.java index 9063941..0745c63 100644 --- a/src/com/annimon/socketfiletransfer/MessageHistory.java +++ b/src/com/annimon/socketfiletransfer/util/MessageHistory.java @@ -1,4 +1,4 @@ -package com.annimon.socketfiletransfer; +package com.annimon.socketfiletransfer.util; /** * diff --git a/src/com/annimon/socketfiletransfer/util/RobotUtils.java b/src/com/annimon/socketfiletransfer/util/RobotUtils.java new file mode 100644 index 0000000..086d815 --- /dev/null +++ b/src/com/annimon/socketfiletransfer/util/RobotUtils.java @@ -0,0 +1,91 @@ +package com.annimon.socketfiletransfer.util; + +import java.awt.AWTException; +import java.awt.MouseInfo; +import java.awt.Point; +import java.awt.PointerInfo; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Toolkit; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; +import java.awt.image.BufferedImage; + +/** + * Работа с классом Robot. + * @author aNNiMON + */ +public class RobotUtils { + + private static final int CLICK_DELAY = 300; + private final Robot robot; + + public RobotUtils() throws AWTException { + robot = new Robot(); + } + + /** + * Кликнуть в нужную точку + * @param click точка по которой нужно кликнуть + */ + public void clickPoint(Point click) { + robot.mouseMove(click.x, click.y); + robot.mousePress(InputEvent.BUTTON1_MASK); + robot.delay(CLICK_DELAY); + robot.mouseRelease(InputEvent.BUTTON1_MASK); + } + + /** + * Получить позицию курсора. + * @return текущая позиция курсора + */ + public Point getCursorPosition() { + PointerInfo pointerInfo = MouseInfo.getPointerInfo(); + return pointerInfo.getLocation(); + } + + /** + * Передвинуть курсор. + * @param dx на сколько сдвинуть по-горизонтали + * @param dy на сколько сдвинуть по-вертикали + */ + public void moveCursor(int dx, int dy) { + System.out.println(dx + " - " + dy); + Point cursorPoint = getCursorPosition(); + cursorPoint.translate(dx, dy); + + robot.mouseMove(cursorPoint.x, cursorPoint.y); + } + + /** + * Автоматическое написание сообщения + * @param text "печатаемый" текст + */ + public void writeMessage(String text) { + for (char symbol : text.toCharArray()) { + boolean needShiftPress = Character.isUpperCase(symbol) && Character.isLetter(symbol); + if(needShiftPress) { + robot.keyPress(KeyEvent.VK_SHIFT); + } + int event = KeyEvent.getExtendedKeyCodeForChar(symbol); + try { + robot.keyPress(event); + } catch (Exception e) {} + if(needShiftPress) { + robot.keyRelease(KeyEvent.VK_SHIFT); + } + } + } + + /* + * Получение картинки размером [width x height] с экрана с позиции [x, y] + * Если width или height равны -1, то возвращаем весь экран. + */ + public BufferedImage getImage(int x, int y, int width, int height) { + Rectangle area; + if ((width == -1) || (height == -1)) { + area = new Rectangle(Toolkit.getDefaultToolkit().getScreenSize()); + } else area = new Rectangle(x, y, width, height); + return robot.createScreenCapture(area); + } +} diff --git a/src/config.ini b/src/config.ini index 66e2472..3057007 100644 --- a/src/config.ini +++ b/src/config.ini @@ -1,3 +1,2 @@ -TYPE=server PORT=7119 TRANSFER_DIR=E: