Uses 1319K of libraries. Click here for Pure Java version (16630L/96K).
1 | !7 |
2 | |
3 | // TODO (rare case): send pending mouse up on disable |
4 | // TODO: move to machine-to-machine chat |
5 | |
6 | srecord MouseEvt(bool mouseDown, int button, DoublePt p) {
|
7 | long time = sysNow(); |
8 | } |
9 | |
10 | compact module MiniVNC > DynImageSurface {
|
11 | bool enabled, usePossiblyBrokenVersion = true, runInBackground; |
12 | S computerID; |
13 | int width = 512; |
14 | double videoInterval = 2, mouseInterval = 0.1; |
15 | |
16 | transient int discardEventsAfter = 10000; |
17 | transient int dummyWidth = 100000; |
18 | transient DoublePt mousePosition; |
19 | transient Set<Int> sentMouseButtons = syncSet(); |
20 | transient L<MouseEvt> events = syncList(); |
21 | transient DoublePt sentMousePosition; |
22 | transient Q sendQ; |
23 | |
24 | S switchableFields() { ret "usePossiblyBrokenVersion runInBackground"; }
|
25 | |
26 | start {
|
27 | dm_requireModule("#1016578/AllOnlineComputers");
|
28 | sendQ = dm_startQ(); |
29 | doEvery(videoInterval, r grab); |
30 | doEvery(mouseInterval, r moveMouse); |
31 | } |
32 | |
33 | visualize {
|
34 | JComponent c = super.visualize(); |
35 | enableDoubleBuffering(); |
36 | imageSurfaceOnMouseMoveOrDrag_double(imageSurface, voidfunc(DoublePt p) { mousePosition = p });
|
37 | disableImageSurfaceSelector(imageSurface); |
38 | setFocusable(imageSurface, true); |
39 | makePopupMenuConditional(imageSurface, func -> bool { enabled });
|
40 | |
41 | addKeyListener(imageSurface, new KeyAdapter {
|
42 | public void keyReleased(final KeyEvent evt) {
|
43 | print("key up (mod=" + evt.getModifiers() + "): " + evt);
|
44 | if (actuallyEnabled()) sendQ.add(r {
|
45 | dm_evalOnOtherMachine(computerID, "robot_keyPressAndReleaseWithModifiers(" + evt.getKeyCode() + ", " + evt.getModifiers() + ")")
|
46 | }); |
47 | } |
48 | }); |
49 | |
50 | addMouseListener(imageSurface, new MouseAdapter {
|
51 | public void mousePressed(MouseEvent evt) {
|
52 | imageSurface.grabFocus(); |
53 | impl(evt, true); |
54 | } |
55 | |
56 | void impl(MouseEvent evt, bool down) {
|
57 | if (!actuallyEnabled()) return; |
58 | int mask = mouseButtonMaskForRobot(evt.getButton()); |
59 | print("mask: " + mask);
|
60 | events.add(MouseEvt(down, mask, imageSurface_doublePtFromEvent(imageSurface, evt))); |
61 | } |
62 | |
63 | public void mouseReleased(MouseEvent evt) {
|
64 | impl(evt, false); |
65 | } |
66 | }); |
67 | |
68 | ret northAndCenterWithMargins(vstackWithSpacing( |
69 | centerAndEastWithMargins( |
70 | withLabel("Computer to control:", dm_onlineComputerSelectorComboBox(dm_fieldLiveValue('computerID))), dm_fieldCheckBox('enabled)),
|
71 | jRightAlignedLine(jLabel("Resize to width (pixels):"), jMinWidth(100, jLiveValueIntTextField(dm_fieldLiveValue('width))))),
|
72 | c); |
73 | } |
74 | |
75 | bool actuallyEnabled() {
|
76 | ret enabled && possibleComputerID(computerID) && dm_isVisible(); |
77 | } |
78 | |
79 | bool actuallyEnabledAndInFocus() {
|
80 | ret actuallyEnabled() && (runInBackground || dm_osInForeground()); |
81 | } |
82 | |
83 | void grab enter {
|
84 | if (!actuallyEnabledAndInFocus()) ret; |
85 | time "Get Screenshot" {
|
86 | setImage(dm_scaledDownScreenshotFromOtherMachine(computerID, width, +usePossiblyBrokenVersion)); |
87 | } |
88 | } |
89 | |
90 | void moveMouse enter {
|
91 | if (!actuallyEnabled()) {
|
92 | sentMousePosition = null; sentMouseButtons.clear(); ret; |
93 | } |
94 | LinkedList<MouseEvt> events = cloneAndClearAsLinkedList(this.events); |
95 | |
96 | final double scale = doubleRatio(dummyWidth, width); |
97 | |
98 | // drop old events (if network was down) |
99 | new Set<Int> sendMouseUp; |
100 | while (nempty(events) && elapsedMS(first(events).time) >= discardEventsAfter) {
|
101 | if (!first(events).mouseDown) sendMouseUp.add(first(events).button); // don't drop that |
102 | popFirst(events); |
103 | } |
104 | for (int button : sendMouseUp) |
105 | dm_evalOnOtherMachine(computerID, "robot_mouseUp(" + button + ")");
|
106 | |
107 | // send mouse click/release events |
108 | for (MouseEvt e : events) {
|
109 | dm_evalOnOtherMachine(computerID, |
110 | "robot_mouseButtonPressOrRelease_scaled(" + e.mouseDown + ", " + e.button + ", " + scaleInt(e.p.x, scale) + ", " + scaleInt(e.p.y, scale) + ", " + dummyWidth + ")");
|
111 | sentMousePosition = e.p; |
112 | addOrRemove(sentMouseButtons, e.button, e.mouseDown); |
113 | } |
114 | |
115 | // send mouse position |
116 | DoublePt p = mousePosition; |
117 | if (neq(p, sentMousePosition)) {
|
118 | sentMousePosition = p; |
119 | if (p != null) {
|
120 | time "Move Mouse On Other Machine" {
|
121 | dm_evalOnOtherMachine(computerID, "dm_moveMouseImmediate_direct_scaled(" + scaleInt(p.x, scale) + ", " + scaleInt(p.y, scale) + ", " + dummyWidth + ")");
|
122 | } |
123 | } |
124 | } |
125 | } |
126 | |
127 | enhanceFrame {
|
128 | dm_doubleFieldMenuItem(f, 'videoInterval, formTitle := "Update image every n seconds", onSet := rThread dm_reload); |
129 | } |
130 | } |
download show line numbers debug dex old transpilations
Travelled to 9 computer(s): bhatertpkbcr, cfunsshuasjs, gwrvuhgaqvyk, irmadwmeruwu, mqqgnosmbjvj, pyentgdyhuwx, pzhvpgtvlbxg, tvejysmllsmz, vouqrxazstgt
No comments. add comment
| Snippet ID: | #1019894 |
| Snippet name: | Mini VNC [Dyn Module, control other computer's mouse & keyboard] |
| Eternal ID of this version: | #1019894/69 |
| Text MD5: | dca888f01a2eacaa81c5b255427115cb |
| Transpilation MD5: | 2db594d1fc1c7a9e421ee8521b1e352c |
| Author: | stefan |
| Category: | javax / stefan's os |
| Type: | JavaX source code (Dynamic Module) |
| Public (visible to everyone): | Yes |
| Archived (hidden from active list): | No |
| Created/modified: | 2019-01-10 01:27:38 |
| Source code size: | 4693 bytes / 130 lines |
| Pitched / IR pitched: | No / No |
| Views / Downloads: | 745 / 4286 |
| Version history: | 68 change(s) |
| Referenced in: | [show references] |