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).

1  
sclass MouseMover {
2  
  Pt cur, last;
3  
  Robot robot;
4  
  java.util.Timer timer;
5  
  int interferenceMinDistance = 100;
6  
  int mouseCheckInterval = 50;
7  
  int blockTimeAfterInterference = 5000; // ms
8  
  bool endAfterInterference = true;
9  
  volatile bool interference;
10  
  bool forceActive;
11  
  long blockUntil;
12  
  new HashSet<Int> buttonsToRelease;
13  
  sbool listenToGlobalKeyPresses;
14  
  IF0<AutoCloseable> enter;
15  
  bool verbose;
16  
  
17  
  // TODO: fix this logic...
18  
  synchronized bool enabled() { ret timer != null; }
19  
  synchronized bool hasInterference() { ret interference; }
20  
  bool active() { ret enabled() && (forceActive || !hasInterference()); }
21  
  bool active2() { ret enabled() && !blocked(); }
22  
  
23  
  synchronized MouseMover enable() ctex {
24  
    if (robot == null) robot = new Robot;
25  
    if (timer == null) {
26  
      interference = false;
27  
      cur = new Pt(mouseLocation());
28  
      timer = doEvery(mouseCheckInterval, r checkMouse);
29  
      
30  
      if (listenToGlobalKeyPresses)
31  
        onGlobalKeyPress(r {
32  
          temp callF(enter);
33  
          if (verbose) print("Key press detected");
34  
          haveInterference();
35  
        });
36  
      // TODO: on global mouse click
37  
      
38  
      if (verbose) print("Mouse automation started");
39  
    }
40  
    ret this;
41  
  }
42  
  
43  
  bool farAway(Pt a, Pt b) {
44  
    ret pointDistance(a, b) >= interferenceMinDistance;
45  
  }
46  
  
47  
  synchronized void checkMouse() {
48  
    temp callF(enter);
49  
    if (!enabled()) ret;
50  
    blocked(); // trigger resume
51  
    Pt p = new Pt(mouseLocation());
52  
    if (farAway(p, cur) && neq(p, last)) {
53  
      if (verbose) print("Mouse movement detected: " + nPixels(iround(ptDistance(p, cur))));
54  
      haveInterference();
55  
    }
56  
  }
57  
  
58  
  void haveInterference() {
59  
    temp callF(enter);
60  
    //printStackTrace("haveInterference");
61  
    if (!enabled()) ret;
62  
    interference = true;
63  
    if (endAfterInterference) {
64  
      if (verbose) print("User interference detected, stopping automation");
65  
      disable();
66  
    } else {
67  
      bool blockedAlready = blocked();
68  
      blockUntil = now()+blockTimeAfterInterference;
69  
      if (!blockedAlready)
70  
        if (verbose) print("Mouse automation blocked for at least " + blockTimeAfterInterference + " ms");
71  
      releaseButtons();
72  
      cur = new Pt(mouseLocation());
73  
      if (verbose) print("Set cur to " + cur);
74  
      last = null;
75  
    }
76  
  }
77  
  
78  
  synchronized void disable() {
79  
    releaseButtons();
80  
    if (timer != null) {
81  
      timer.cancel();
82  
      timer = null;
83  
      /*if (!interference)
84  
        if (verbose) print("Mouse automation ended without interference");*/
85  
    }
86  
  }
87  
  
88  
  synchronized void moveMouseImmediate(Pt p) {
89  
    checkMouse();
90  
    if (!enabled() || blocked()) ret;
91  
    p = normalizePointToScreen(p);
92  
    if (neq(cur, p)) {
93  
      if (neq(new Pt(mouseLocation()), last))
94  
        last = cur;
95  
      cur = p;
96  
      robot.mouseMove(p.x, p.y);
97  
    }
98  
  }
99  
  
100  
  synchronized bool blocked() {
101  
    if (!enabled() || blockUntil == 0) false;
102  
    if (now() < blockUntil) true;
103  
    blockUntil = 0;
104  
    cur = new Pt(mouseLocation());
105  
    last = null;
106  
    if (verbose) print(prefix() + "Mouse automation resumes");
107  
    false;
108  
  }
109  
  
110  
  void moveMouse(Pt pdest) {
111  
    if (pdest == null) ret;
112  
    print("Moving mouse to " + pdest);
113  
    Point p = getMouseLocation();
114  
    //int steps = 20, delay = 40; // slow
115  
    //int steps = 20, delay = 20; // fast
116  
    int steps = 20, delay = 30; // medium
117  
    for (int i = 1; i <= steps; i++) {
118  
      if (blocked()) break;
119  
      Point p2 = blendPoints(p, pdest.getPoint(), ((double) i) / steps);
120  
      moveMouseImmediate(new Pt(p2));
121  
      if (i != steps)
122  
        sleep(delay);
123  
    }
124  
  }
125  
  
126  
  void click() {
127  
    temp callF(enter);
128  
    if (active2()) {
129  
      print(prefix() + "CLICKING");
130  
      mouseClick();
131  
    } else print(prefix() + "Not clicking, have interference: " + hasInterference());
132  
  }
133  
  
134  
  S prefix() { ret systemHashCode(this) + ": "; }
135  
  
136  
  void pressButton() {
137  
    robot.mousePress(addAndReturn(buttonsToRelease, InputEvent.BUTTON1_DOWN_MASK));
138  
  }
139  
  
140  
  void releaseButton() {
141  
    robot.mouseRelease(removeAndReturn(buttonsToRelease, InputEvent.BUTTON1_DOWN_MASK));
142  
  }
143  
  
144  
  void click(Pt p) {
145  
    moveMouse(p);
146  
    click();
147  
  }
148  
  
149  
  void click(int x, int y) {
150  
    click(new Pt(x, y));
151  
  }
152  
  
153  
  void cleanMeUp() {
154  
    disable();
155  
    releaseButtons();
156  
  }
157  
  
158  
  void releaseButtons() {
159  
    for (int btn : getAndClearList(buttonsToRelease))
160  
      robot.mouseRelease(btn);
161  
  }
162  
  
163  
  // e.g. when user presses a button that is perform an automation
164  
  void unblock() {
165  
    blockUntil = 0;
166  
  }
167  
}

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: 610 / 1378
Version history: 45 change(s)
Referenced in: [show references]