Not logged in.  Login/Logout/Register | List snippets | | Create snippet | Upload image | Upload data

167
LINES

< > BotCompany Repo | #1005819 // MouseMover - robot-move mouse, abort when user interferes

JavaX fragment (include) [tags: use-pretranspiled]

Uses 408K of libraries. Click here for Pure Java version (3830L/24K).

sclass MouseMover {
  Pt cur, last;
  Robot robot;
  java.util.Timer timer;
  int interferenceMinDistance = 100;
  int mouseCheckInterval = 50;
  int blockTimeAfterInterference = 5000; // ms
  bool endAfterInterference = true;
  volatile bool interference;
  bool forceActive;
  long blockUntil;
  new HashSet<Int> buttonsToRelease;
  sbool listenToGlobalKeyPresses;
  IF0<AutoCloseable> enter;
  bool verbose;
  
  // TODO: fix this logic...
  synchronized bool enabled() { ret timer != null; }
  synchronized bool hasInterference() { ret interference; }
  bool active() { ret enabled() && (forceActive || !hasInterference()); }
  bool active2() { ret enabled() && !blocked(); }
  
  synchronized MouseMover enable() ctex {
    if (robot == null) robot = new Robot;
    if (timer == null) {
      interference = false;
      cur = new Pt(mouseLocation());
      timer = doEvery(mouseCheckInterval, r checkMouse);
      
      if (listenToGlobalKeyPresses)
        onGlobalKeyPress(r {
          temp callF(enter);
          if (verbose) print("Key press detected");
          haveInterference();
        });
      // TODO: on global mouse click
      
      if (verbose) print("Mouse automation started");
    }
    ret this;
  }
  
  bool farAway(Pt a, Pt b) {
    ret pointDistance(a, b) >= interferenceMinDistance;
  }
  
  synchronized void checkMouse() {
    temp callF(enter);
    if (!enabled()) ret;
    blocked(); // trigger resume
    Pt p = new Pt(mouseLocation());
    if (farAway(p, cur) && neq(p, last)) {
      if (verbose) print("Mouse movement detected: " + nPixels(iround(ptDistance(p, cur))));
      haveInterference();
    }
  }
  
  void haveInterference() {
    temp callF(enter);
    //printStackTrace("haveInterference");
    if (!enabled()) ret;
    interference = true;
    if (endAfterInterference) {
      if (verbose) print("User interference detected, stopping automation");
      disable();
    } else {
      bool blockedAlready = blocked();
      blockUntil = now()+blockTimeAfterInterference;
      if (!blockedAlready)
        if (verbose) print("Mouse automation blocked for at least " + blockTimeAfterInterference + " ms");
      releaseButtons();
      cur = new Pt(mouseLocation());
      if (verbose) print("Set cur to " + cur);
      last = null;
    }
  }
  
  synchronized void disable() {
    releaseButtons();
    if (timer != null) {
      timer.cancel();
      timer = null;
      /*if (!interference)
        if (verbose) print("Mouse automation ended without interference");*/
    }
  }
  
  synchronized void moveMouseImmediate(Pt p) {
    checkMouse();
    if (!enabled() || blocked()) ret;
    p = normalizePointToScreen(p);
    if (neq(cur, p)) {
      if (neq(new Pt(mouseLocation()), last))
        last = cur;
      cur = p;
      robot.mouseMove(p.x, p.y);
    }
  }
  
  synchronized bool blocked() {
    if (!enabled() || blockUntil == 0) false;
    if (now() < blockUntil) true;
    blockUntil = 0;
    cur = new Pt(mouseLocation());
    last = null;
    if (verbose) print(prefix() + "Mouse automation resumes");
    false;
  }
  
  void moveMouse(Pt pdest) {
    if (pdest == null) ret;
    print("Moving mouse to " + pdest);
    Point p = getMouseLocation();
    //int steps = 20, delay = 40; // slow
    //int steps = 20, delay = 20; // fast
    int steps = 20, delay = 30; // medium
    for (int i = 1; i <= steps; i++) {
      if (blocked()) break;
      Point p2 = blendPoints(p, pdest.getPoint(), ((double) i) / steps);
      moveMouseImmediate(new Pt(p2));
      if (i != steps)
        sleep(delay);
    }
  }
  
  void click() {
    temp callF(enter);
    if (active2()) {
      print(prefix() + "CLICKING");
      mouseClick();
    } else print(prefix() + "Not clicking, have interference: " + hasInterference());
  }
  
  S prefix() { ret systemHashCode(this) + ": "; }
  
  void pressButton() {
    robot.mousePress(addAndReturn(buttonsToRelease, InputEvent.BUTTON1_DOWN_MASK));
  }
  
  void releaseButton() {
    robot.mouseRelease(removeAndReturn(buttonsToRelease, InputEvent.BUTTON1_DOWN_MASK));
  }
  
  void click(Pt p) {
    moveMouse(p);
    click();
  }
  
  void click(int x, int y) {
    click(new Pt(x, y));
  }
  
  void cleanMeUp() {
    disable();
    releaseButtons();
  }
  
  void releaseButtons() {
    for (int btn : getAndClearList(buttonsToRelease))
      robot.mouseRelease(btn);
  }
  
  // e.g. when user presses a button that is perform an automation
  void unblock() {
    blockUntil = 0;
  }
}

download  show line numbers  debug dex  old transpilations   

Travelled to 15 computer(s): aoiabmzegqzx, bhatertpkbcr, cbybwowwnfue, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, ishqpsrjomds, lpdgvwnxivlt, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, sawdedvomwva, tslmcundralx, tvejysmllsmz, vouqrxazstgt

No comments. add comment

Snippet ID: #1005819
Snippet name: MouseMover - robot-move mouse, abort when user interferes
Eternal ID of this version: #1005819/46
Text MD5: d8c50ca179273c16fac1531ed26523cf
Transpilation MD5: ff5bfd6b432dd43fb7a16e0ca84d3e73
Author: stefan
Category: javax / automation
Type: JavaX fragment (include)
Public (visible to everyone): Yes
Archived (hidden from active list): No
Created/modified: 2019-10-03 09:20:34
Source code size: 4662 bytes / 167 lines
Pitched / IR pitched: No / No
Views / Downloads: 678 / 1474
Version history: 45 change(s)
Referenced in: [show references]