bare-pointer 0.1.0 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.js CHANGED
@@ -14,10 +14,14 @@ module.exports = class Pointer {
14
14
  async down(view, x, y) {
15
15
  if (this._view !== null) throw new Error('Pointer is already down')
16
16
 
17
- this._backend.down(view, ...this._point(view, x, y))
17
+ const point = this._point(view, x, y)
18
+
19
+ await this._reach(view, point)
20
+
21
+ this._backend.down(view, ...point)
18
22
  this._view = view
19
23
 
20
- await frame(view)
24
+ await this._frame(view)
21
25
  }
22
26
 
23
27
  async move(view, x, y) {
@@ -25,7 +29,7 @@ module.exports = class Pointer {
25
29
 
26
30
  this._backend.move(view, ...this._point(view, x, y))
27
31
 
28
- await frame(view)
32
+ await this._frame(view)
29
33
  }
30
34
 
31
35
  async up() {
@@ -36,7 +40,7 @@ module.exports = class Pointer {
36
40
  this._backend.up()
37
41
  this._view = null
38
42
 
39
- await frame(view)
43
+ await this._frame(view)
40
44
  }
41
45
 
42
46
  async tap(view, x, y) {
@@ -44,18 +48,20 @@ module.exports = class Pointer {
44
48
 
45
49
  const point = this._point(view, x, y)
46
50
 
51
+ await this._reach(view, point)
52
+
47
53
  if (this._backend.tap) {
48
54
  this._backend.tap(view, ...point)
49
55
  } else {
50
56
  this._backend.down(view, ...point)
51
57
 
52
58
  // UIKit controls only see a press that lasts past a frame.
53
- await frame(view)
59
+ await this._frame(view)
54
60
 
55
61
  this._backend.up()
56
62
  }
57
63
 
58
- await frame(view)
64
+ await this._frame(view)
59
65
  }
60
66
 
61
67
  destroy() {
@@ -65,6 +71,51 @@ module.exports = class Pointer {
65
71
  this._backend.destroy()
66
72
  }
67
73
 
74
+ async _reach(view, point) {
75
+ if (this._backend.covered !== undefined) {
76
+ for (let frames = 0; this._backend.covered(view, ...point); frames++) {
77
+ if (frames === 60) throw new Error('The view is covered at the point')
78
+
79
+ await this._frame(view)
80
+ }
81
+ }
82
+
83
+ if (this._backend.hover !== undefined) {
84
+ this._backend.hover(view, ...point)
85
+
86
+ await this._frame(view)
87
+ }
88
+ }
89
+
90
+ _frame(view) {
91
+ const provider = new AnimationFrameProvider(view)
92
+
93
+ if (this._backend.watch === undefined) return provider.afterAnimationFrame()
94
+
95
+ return new Promise((resolve) => {
96
+ let ended = false
97
+ let unwatch = null
98
+
99
+ const request = provider.afterAnimationFrame(done)
100
+
101
+ unwatch = this._backend.watch(view, done)
102
+
103
+ if (ended) unwatch()
104
+
105
+ function done() {
106
+ if (ended) return
107
+
108
+ ended = true
109
+
110
+ request.cancel()
111
+
112
+ if (unwatch !== null) unwatch()
113
+
114
+ resolve()
115
+ }
116
+ })
117
+ }
118
+
68
119
  _point(view, x, y) {
69
120
  if (x !== undefined && y !== undefined) return [x, y]
70
121
 
@@ -73,7 +124,3 @@ module.exports = class Pointer {
73
124
  return [x === undefined ? width / 2 : x, y === undefined ? height / 2 : y]
74
125
  }
75
126
  }
76
-
77
- function frame(view) {
78
- return new AnimationFrameProvider(view).afterAnimationFrame()
79
- }
package/lib/android.js CHANGED
@@ -30,8 +30,6 @@ module.exports = class AndroidPointer {
30
30
 
31
31
  destroy() {}
32
32
 
33
- // The root is not always at the origin of the window, so the view is placed
34
- // by its offset from the root.
35
33
  _dispatch(action, view, x, y) {
36
34
  const root = view.rootView
37
35
  const here = view.locationInWindow
package/lib/darwin.js CHANGED
@@ -1,3 +1,4 @@
1
+ const AnimationFrameProvider = require('bare-animation-frame')
1
2
  const AppKitApplication = require('bare-app-kit/application')
2
3
  const AppKitEvent = require('bare-app-kit/event')
3
4
 
@@ -15,6 +16,23 @@ module.exports = class DarwinPointer {
15
16
  return [width, height]
16
17
  }
17
18
 
19
+ watch(view, onhidden) {
20
+ let request = null
21
+
22
+ check()
23
+
24
+ function check() {
25
+ const window = view.window
26
+
27
+ if (window === null || !window.visible) onhidden()
28
+ else request = AnimationFrameProvider.requestAnimationFrame(check)
29
+ }
30
+
31
+ return () => {
32
+ if (request !== null) request.cancel()
33
+ }
34
+ }
35
+
18
36
  down(view, x, y) {
19
37
  this._send(TYPE.LEFT_MOUSE_DOWN, view, x, y)
20
38
  }
@@ -27,15 +45,12 @@ module.exports = class DarwinPointer {
27
45
  this._window.sendEvent(this._event(TYPE.LEFT_MOUSE_UP, this._window, this._point))
28
46
  }
29
47
 
30
- // A control tracks the mouse by reading the event queue until it is released,
31
- // so the release has to be waiting there before the press is sent.
32
48
  tap(view, x, y) {
33
49
  const window = view.window
34
50
  const point = view.convertPointToView(x, y, null)
35
51
 
52
+ AppKitApplication.postEvent(this._event(TYPE.LEFT_MOUSE_DOWN, window, point))
36
53
  AppKitApplication.postEvent(this._event(TYPE.LEFT_MOUSE_UP, window, point))
37
-
38
- window.sendEvent(this._event(TYPE.LEFT_MOUSE_DOWN, window, point))
39
54
  }
40
55
 
41
56
  destroy() {}
package/lib/linux.js CHANGED
@@ -10,6 +10,20 @@ module.exports = class LinuxPointer {
10
10
  return [view.width, view.height]
11
11
  }
12
12
 
13
+ watch(view, onhidden) {
14
+ const window = view.native
15
+
16
+ if (window === null || !window.visible) {
17
+ onhidden()
18
+
19
+ return () => {}
20
+ }
21
+
22
+ window.on('hide', onhidden)
23
+
24
+ return () => window.off('hide', onhidden)
25
+ }
26
+
13
27
  down(view, x, y) {
14
28
  this._move(view, x, y)
15
29
 
@@ -40,9 +54,6 @@ module.exports = class LinuxPointer {
40
54
  xtest.fakeMotionEvent(this._display, xtest.CURRENT_SCREEN, point.x, point.y)
41
55
  }
42
56
 
43
- // A point in the widget becomes one in its native, then in the surface of
44
- // that, which is drawn in device pixels on an X11 window that the server can
45
- // place on the root.
46
57
  _point(view, x, y) {
47
58
  const native = view.native
48
59
  const surface = native.surface
package/lib/win32.js CHANGED
@@ -2,6 +2,7 @@ const Win32Interop = require('bare-win-ui/win32-interop')
2
2
  const user32 = require('bare-user32')
3
3
 
4
4
  const {
5
+ GA_ROOT,
5
6
  SM_XVIRTUALSCREEN,
6
7
  SM_YVIRTUALSCREEN,
7
8
  SM_CXVIRTUALSCREEN,
@@ -23,13 +24,28 @@ module.exports = class Win32Pointer {
23
24
  return [view.actualWidth, view.actualHeight]
24
25
  }
25
26
 
26
- down(view, x, y) {
27
- this._point = locate(view, x, y)
27
+ covered(view, x, y) {
28
+ const { window, screen } = locate(view, x, y)
29
+ const top = user32.windowFromPoint(screen.x, screen.y)
30
+
31
+ if (top !== null && user32.getAncestor(top, GA_ROOT) === window) return false
32
+
33
+ user32.setForegroundWindow(window)
34
+
35
+ return true
36
+ }
37
+
38
+ hover(view, x, y) {
39
+ this._point = normalize(locate(view, x, y).screen)
40
+ this._send(0)
41
+ }
42
+
43
+ down() {
28
44
  this._send(MOUSEEVENTF_LEFTDOWN)
29
45
  }
30
46
 
31
47
  move(view, x, y) {
32
- this._point = locate(view, x, y)
48
+ this._point = normalize(locate(view, x, y).screen)
33
49
  this._send(0)
34
50
  }
35
51
 
@@ -54,8 +70,6 @@ module.exports = class Win32Pointer {
54
70
  }
55
71
  }
56
72
 
57
- // An element is placed in DIPs from the XAML root, which fills the client area
58
- // of its window. Absolute input divides the virtual screen into 65536 steps.
59
73
  function locate(view, x, y) {
60
74
  const root = view.xamlRoot
61
75
  const scale = root.rasterizationScale
@@ -68,13 +82,17 @@ function locate(view, x, y) {
68
82
  Math.round(point.y * scale)
69
83
  )
70
84
 
85
+ return { window, screen }
86
+ }
87
+
88
+ function normalize(screen) {
71
89
  const left = user32.getSystemMetrics(SM_XVIRTUALSCREEN)
72
90
  const top = user32.getSystemMetrics(SM_YVIRTUALSCREEN)
73
91
  const width = user32.getSystemMetrics(SM_CXVIRTUALSCREEN)
74
92
  const height = user32.getSystemMetrics(SM_CYVIRTUALSCREEN)
75
93
 
76
94
  return {
77
- dx: Math.round(((screen.x - left) * 65536) / width),
78
- dy: Math.round(((screen.y - top) * 65536) / height)
95
+ dx: Math.round(((screen.x - left + 0.5) * 65536) / width),
96
+ dy: Math.round(((screen.y - top + 0.5) * 65536) / height)
79
97
  }
80
98
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bare-pointer",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Simulated pointer input for testing Bare apps",
5
5
  "exports": {
6
6
  "./package": "./package.json",
@@ -51,13 +51,13 @@
51
51
  "bare-app-kit": "^0.3.1",
52
52
  "bare-ndk": "^0.3.4",
53
53
  "bare-ui-kit-touch": "^0.1.0",
54
- "bare-user32": "^0.1.0",
54
+ "bare-user32": "^0.1.1",
55
55
  "bare-win-ui": "^0.3.7",
56
56
  "bare-x11": "^0.1.0",
57
57
  "bare-x11-xtest": "^0.1.0"
58
58
  },
59
59
  "devDependencies": {
60
- "bare-gtk": "^0.4.1",
60
+ "bare-gtk": "^0.4.2",
61
61
  "bare-native-test": "^0.1.3",
62
62
  "bare-tap": "^1.1.0",
63
63
  "bare-ui-kit": "^0.3.1",