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: