@flighthq/screen 0.5.1-next.704.19c91ec → 0.5.1-next.730.f29a5aa

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/README.md CHANGED
@@ -13,5 +13,5 @@ Import the supported application-facing API from `@flighthq/screen`. The `@fligh
13
13
  This package is part of the locked-version Flight SDK graph. Applications may instead install and import `@flighthq/sdk` when package-level tree shaking is sufficient.
14
14
 
15
15
  - [Flight project](https://github.com/flighthq/flight)
16
- - [Source for @flighthq/screen@0.5.1-next.704.19c91ec](https://github.com/flighthq/flight/tree/19c91ec3e569d6b3b471682726465a79fba9f8cb/packages/screen)
17
- - [License](https://github.com/flighthq/flight/blob/19c91ec3e569d6b3b471682726465a79fba9f8cb/LICENSE.md)
16
+ - [Source for @flighthq/screen@0.5.1-next.730.f29a5aa](https://github.com/flighthq/flight/tree/f29a5aab5db192284ce5cadf08ffae2649a598ea/packages/screen)
17
+ - [License](https://github.com/flighthq/flight/blob/f29a5aab5db192284ce5cadf08ffae2649a598ea/LICENSE.md)
package/dist/screen.js CHANGED
@@ -1,4 +1,4 @@
1
- import { createEntity } from '@flighthq/entity/contract';
1
+ import { createEntity, stripEntityRuntime } from '@flighthq/entity/contract';
2
2
  import { clearSignal, createSignal, emitSignal } from '@flighthq/signals/contract';
3
3
  export function attachScreenPermissionChange(host, permissionChange) {
4
4
  detachScreenPermissionChange(permissionChange);
@@ -217,7 +217,7 @@ const _permissionSubscriptions = new WeakMap();
217
217
  const _signalSubscriptions = new WeakMap();
218
218
  const _scratchPoint = { x: 0, y: 0 };
219
219
  function copyScreenInfo(src, dst) {
220
- Object.assign(dst, src);
220
+ Object.assign(dst, stripEntityRuntime(src));
221
221
  }
222
222
  function fillDefaultScreenInfo(out) {
223
223
  copyScreenInfo(createScreenInfo(), out);
@@ -1 +1 @@
1
- {"version":3,"file":"screen.js","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"screen.js","sourceRoot":"","sources":["../src/screen.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flighthq/screen",
3
- "version": "0.5.1-next.704.19c91ec",
3
+ "version": "0.5.1-next.730.f29a5aa",
4
4
  "author": "Joshua Granick and other contributors",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -38,9 +38,9 @@
38
38
  "clean:dist": "tsx ../../scripts/clean-package-dist.ts"
39
39
  },
40
40
  "dependencies": {
41
- "@flighthq/entity": "0.5.1-next.704.19c91ec",
42
- "@flighthq/signals": "0.5.1-next.704.19c91ec",
43
- "@flighthq/types": "0.5.1-next.704.19c91ec"
41
+ "@flighthq/entity": "0.5.1-next.730.f29a5aa",
42
+ "@flighthq/signals": "0.5.1-next.730.f29a5aa",
43
+ "@flighthq/types": "0.5.1-next.730.f29a5aa"
44
44
  },
45
45
  "devDependencies": {
46
46
  "typescript": "^5.3.0"
@@ -1,166 +1,620 @@
1
+ import { attachEntityBinding, createEntity, getEntityBinding } from '@flighthq/entity/contract';
1
2
  import { connectSignal } from '@flighthq/signals/contract';
3
+ import type { HasScreenQuery, ScreenChangeEvent, ScreenInfo, ScreenPermissionState } from '@flighthq/types/contract';
2
4
  import { EntityRuntimeKey } from '@flighthq/types/contract';
3
5
  import { describe, expect, it, vi } from 'vitest';
4
6
 
5
- import * as screenContract from './screen';
6
7
  import {
8
+ attachScreenPermissionChange,
7
9
  attachScreenSignals,
8
10
  createScreenInfo,
9
11
  createScreenMode,
10
12
  createScreenPermissionChange,
11
13
  createScreenSignals,
14
+ detachScreenPermissionChange,
12
15
  detachScreenSignals,
16
+ dipToScreenPoint,
17
+ dipToScreenRect,
13
18
  disposeScreenPermissionChange,
14
19
  disposeScreenSignals,
20
+ getPrimaryScreen,
21
+ getScreenBounds,
22
+ getScreenById,
23
+ getScreenContainingRect,
15
24
  getScreenCurrentMode,
25
+ getScreenCursorPosition,
26
+ getScreenCursorScreen,
27
+ getScreenDetailPermission,
28
+ getScreenNearestPoint,
29
+ getScreenNearestRect,
16
30
  getScreens,
31
+ getScreenWorkArea,
32
+ requestScreenDetails,
33
+ screenToDipPoint,
34
+ screenToDipRect,
17
35
  } from './screen';
18
36
 
19
37
  describe('attachScreenPermissionChange', () => {
20
- it('is exported', () => expect(screenContract.attachScreenPermissionChange).toBeTypeOf('function'));
38
+ it('forwards permission states from the supplied host', () => {
39
+ const harness = createPermissionChangeHarness();
40
+ const permissionChange = createScreenPermissionChange();
41
+ const listener = vi.fn();
42
+ connectSignal(permissionChange.onChange, listener);
43
+
44
+ attachScreenPermissionChange(harness.host, permissionChange);
45
+ harness.emit('granted');
46
+
47
+ expect(listener).toHaveBeenCalledWith('granted');
48
+ });
21
49
  });
50
+
22
51
  describe('attachScreenSignals', () => {
23
- it('is exported', () => expect(screenContract.attachScreenSignals).toBeTypeOf('function'));
52
+ it('routes added, removed, and metrics events to their matching signals', () => {
53
+ const harness = createScreenChangeHarness();
54
+ const signals = createScreenSignals();
55
+ const added = vi.fn();
56
+ const metricsChanged = vi.fn();
57
+ const removed = vi.fn();
58
+ connectSignal(signals.onScreenAdded, added);
59
+ connectSignal(signals.onScreenMetricsChanged, metricsChanged);
60
+ connectSignal(signals.onScreenRemoved, removed);
61
+ const screen = createTestScreen(7, 100, 200, 800, 600);
62
+ const metricsEvent: ScreenChangeEvent = {
63
+ kind: 'ScreenMetricsChanged',
64
+ screen,
65
+ changedMetrics: { bounds: true, orientation: false, scaleFactor: true, workArea: false },
66
+ };
67
+
68
+ attachScreenSignals(harness.host, signals);
69
+ harness.emit({ kind: 'ScreenAdded', screen, changedMetrics: null });
70
+ harness.emit({ kind: 'ScreenRemoved', screen, changedMetrics: null });
71
+ harness.emit(metricsEvent);
72
+
73
+ expect(added).toHaveBeenCalledWith(screen);
74
+ expect(removed).toHaveBeenCalledWith(screen);
75
+ expect(metricsChanged).toHaveBeenCalledWith(metricsEvent);
76
+ });
24
77
  });
78
+
25
79
  describe('createScreenInfo', () => {
26
- it('is exported', () => expect(screenContract.createScreenInfo).toBeTypeOf('function'));
80
+ it('creates an entity with documented defaults and sentinels', () => {
81
+ const screen = createScreenInfo();
82
+
83
+ expect(EntityRuntimeKey in screen).toBe(true);
84
+ expect(Object.keys(screen)).toHaveLength(25);
85
+ expect(screen).toMatchObject({
86
+ id: 0,
87
+ x: 0,
88
+ y: 0,
89
+ width: 0,
90
+ height: 0,
91
+ workWidth: 0,
92
+ workHeight: 0,
93
+ scaleFactor: 1,
94
+ isPrimary: false,
95
+ rotation: -1,
96
+ orientation: 'Landscape',
97
+ refreshRate: -1,
98
+ colorDepth: -1,
99
+ pixelDepth: -1,
100
+ physicalWidth: -1,
101
+ physicalHeight: -1,
102
+ isHdr: false,
103
+ colorSpace: 'srgb',
104
+ maxLuminance: -1,
105
+ depthPerComponent: -1,
106
+ dpi: -1,
107
+ label: '',
108
+ internal: false,
109
+ touchSupport: 'unknown',
110
+ monochrome: false,
111
+ });
112
+ });
27
113
  });
114
+
28
115
  describe('createScreenMode', () => {
29
- it('is exported', () => expect(screenContract.createScreenMode).toBeTypeOf('function'));
116
+ it('creates an entity with unknown mode sentinels', () => {
117
+ const mode = createScreenMode();
118
+
119
+ expect(EntityRuntimeKey in mode).toBe(true);
120
+ expect(mode).toMatchObject({ width: 0, height: 0, refreshRate: -1, colorDepth: -1, pixelFormat: '' });
121
+ });
30
122
  });
123
+
31
124
  describe('createScreenPermissionChange', () => {
32
- it('is exported', () => expect(screenContract.createScreenPermissionChange).toBeTypeOf('function'));
125
+ it('creates an entity with an empty permission signal', () => {
126
+ const permissionChange = createScreenPermissionChange();
127
+
128
+ expect(EntityRuntimeKey in permissionChange).toBe(true);
129
+ expect(permissionChange.onChange.data).toBeNull();
130
+ });
33
131
  });
132
+
34
133
  describe('createScreenSignals', () => {
35
- it('is exported', () => expect(screenContract.createScreenSignals).toBeTypeOf('function'));
134
+ it('creates an entity with three independent empty signals', () => {
135
+ const signals = createScreenSignals();
136
+
137
+ expect(EntityRuntimeKey in signals).toBe(true);
138
+ expect(signals.onScreenAdded).not.toBe(signals.onScreenRemoved);
139
+ expect(signals.onScreenAdded.data).toBeNull();
140
+ expect(signals.onScreenMetricsChanged.data).toBeNull();
141
+ expect(signals.onScreenRemoved.data).toBeNull();
142
+ });
36
143
  });
144
+
37
145
  describe('detachScreenPermissionChange', () => {
38
- it('is exported', () => expect(screenContract.detachScreenPermissionChange).toBeTypeOf('function'));
146
+ it('unsubscribes an attachment once and remains repeatable', () => {
147
+ const harness = createPermissionChangeHarness();
148
+ const permissionChange = createScreenPermissionChange();
149
+ attachScreenPermissionChange(harness.host, permissionChange);
150
+
151
+ detachScreenPermissionChange(permissionChange);
152
+ detachScreenPermissionChange(permissionChange);
153
+
154
+ expect(harness.unsubscribe).toHaveBeenCalledOnce();
155
+ });
39
156
  });
157
+
40
158
  describe('detachScreenSignals', () => {
41
- it('is exported', () => expect(screenContract.detachScreenSignals).toBeTypeOf('function'));
159
+ it('unsubscribes an attachment once and remains repeatable', () => {
160
+ const harness = createScreenChangeHarness();
161
+ const signals = createScreenSignals();
162
+ attachScreenSignals(harness.host, signals);
163
+
164
+ detachScreenSignals(signals);
165
+ detachScreenSignals(signals);
166
+
167
+ expect(harness.unsubscribe).toHaveBeenCalledOnce();
168
+ });
42
169
  });
170
+
43
171
  describe('dipToScreenPoint', () => {
44
- it('is exported', () => expect(screenContract.dipToScreenPoint).toBeTypeOf('function'));
172
+ it('converts from desktop DIPs to screen-local pixels and returns out', () => {
173
+ const screen = createTestScreen(1, 100, 50, 800, 600, { scaleFactor: 2 });
174
+ const out = { x: -1, y: -1 };
175
+
176
+ expect(dipToScreenPoint(screen, { x: 112, y: 73 }, out)).toBe(out);
177
+ expect(out).toEqual({ x: 24, y: 46 });
178
+ });
179
+
180
+ it('is safe when out aliases the input point', () => {
181
+ const screen = createTestScreen(1, 100, 50, 800, 600, { scaleFactor: 2 });
182
+ const point = { x: 112, y: 73 };
183
+
184
+ dipToScreenPoint(screen, point, point);
185
+
186
+ expect(point).toEqual({ x: 24, y: 46 });
187
+ });
45
188
  });
189
+
46
190
  describe('dipToScreenRect', () => {
47
- it('is exported', () => expect(screenContract.dipToScreenRect).toBeTypeOf('function'));
191
+ it('converts position and extent to screen-local pixels and returns out', () => {
192
+ const screen = createTestScreen(1, 100, 50, 800, 600, { scaleFactor: 2 });
193
+ const out = { x: -1, y: -1, width: -1, height: -1 };
194
+
195
+ expect(dipToScreenRect(screen, { x: 112, y: 73, width: 30, height: 40 }, out)).toBe(out);
196
+ expect(out).toEqual({ x: 24, y: 46, width: 60, height: 80 });
197
+ });
198
+
199
+ it('is safe when out aliases the input rectangle', () => {
200
+ const screen = createTestScreen(1, 100, 50, 800, 600, { scaleFactor: 2 });
201
+ const rect = { x: 112, y: 73, width: 30, height: 40 };
202
+
203
+ dipToScreenRect(screen, rect, rect);
204
+
205
+ expect(rect).toEqual({ x: 24, y: 46, width: 60, height: 80 });
206
+ });
48
207
  });
208
+
49
209
  describe('disposeScreenPermissionChange', () => {
50
- it('is exported', () => expect(screenContract.disposeScreenPermissionChange).toBeTypeOf('function'));
210
+ it('detaches the host and clears the signal', () => {
211
+ const harness = createPermissionChangeHarness();
212
+ const permissionChange = createScreenPermissionChange();
213
+ connectSignal(permissionChange.onChange, vi.fn());
214
+ attachScreenPermissionChange(harness.host, permissionChange);
215
+
216
+ disposeScreenPermissionChange(permissionChange);
217
+
218
+ expect(harness.unsubscribe).toHaveBeenCalledOnce();
219
+ expect(permissionChange.onChange.data).toBeNull();
220
+ });
51
221
  });
222
+
52
223
  describe('disposeScreenSignals', () => {
53
- it('is exported', () => expect(screenContract.disposeScreenSignals).toBeTypeOf('function'));
224
+ it('detaches the host and clears every signal', () => {
225
+ const harness = createScreenChangeHarness();
226
+ const signals = createScreenSignals();
227
+ connectSignal(signals.onScreenAdded, vi.fn());
228
+ connectSignal(signals.onScreenMetricsChanged, vi.fn());
229
+ connectSignal(signals.onScreenRemoved, vi.fn());
230
+ attachScreenSignals(harness.host, signals);
231
+
232
+ disposeScreenSignals(signals);
233
+
234
+ expect(harness.unsubscribe).toHaveBeenCalledOnce();
235
+ expect(signals.onScreenAdded.data).toBeNull();
236
+ expect(signals.onScreenMetricsChanged.data).toBeNull();
237
+ expect(signals.onScreenRemoved.data).toBeNull();
238
+ });
54
239
  });
240
+
55
241
  describe('getPrimaryScreen', () => {
56
- it('is exported', () => expect(screenContract.getPrimaryScreen).toBeTypeOf('function'));
242
+ it('delegates to the host with the caller-owned output', () => {
243
+ const primary = createTestScreen(3, 10, 20, 1920, 1080, { isPrimary: true });
244
+ const host = createScreenQueryHost([primary]);
245
+ const out = createScreenInfo();
246
+
247
+ expect(getPrimaryScreen(host, out)).toBe(out);
248
+ expect(host.screen.query.getPrimaryScreen).toHaveBeenCalledWith(out);
249
+ expect(out).toMatchObject({ id: 3, x: 10, y: 20, width: 1920, height: 1080, isPrimary: true });
250
+ });
57
251
  });
252
+
58
253
  describe('getScreenBounds', () => {
59
- it('is exported', () => expect(screenContract.getScreenBounds).toBeTypeOf('function'));
254
+ it('extracts desktop bounds into and returns the supplied output', () => {
255
+ const screen = createTestScreen(1, -1280, 120, 1280, 720);
256
+ const out = { x: 0, y: 0, width: 0, height: 0 };
257
+
258
+ expect(getScreenBounds(screen, out)).toBe(out);
259
+ expect(out).toEqual({ x: -1280, y: 120, width: 1280, height: 720 });
260
+ });
60
261
  });
262
+
61
263
  describe('getScreenById', () => {
62
- it('is exported', () => expect(screenContract.getScreenById).toBeTypeOf('function'));
264
+ it('copies a matching screen into out and returns null without a match', () => {
265
+ const first = createTestScreen(10, 0, 0, 100, 100);
266
+ const second = createTestScreen(20, 300, 0, 200, 150, { label: 'external', scaleFactor: 2 });
267
+ const host = createScreenQueryHost([first, second]);
268
+ const out = createScreenInfo();
269
+
270
+ expect(getScreenById(host, 20, out)).toBe(out);
271
+ expect(Object.entries(out)).toEqual(Object.entries(second));
272
+ expect(getScreenById(host, 99, out)).toBeNull();
273
+ });
274
+
275
+ it('preserves the destination runtime while copying public screen data', () => {
276
+ const source = createTestScreen(20, 300, 40, 200, 150, { label: 'source' });
277
+ const out = createTestScreen(99, 0, 0, 1, 1, { label: 'out' });
278
+ const sourceBinding = { owner: 'source' };
279
+ const outBinding = { owner: 'out' };
280
+ attachEntityBinding(source, sourceBinding);
281
+ attachEntityBinding(out, outBinding);
282
+ const sourceRuntime = source[EntityRuntimeKey];
283
+ const outRuntime = out[EntityRuntimeKey];
284
+
285
+ expect(getScreenById(createScreenQueryHost([source]), source.id, out)).toBe(out);
286
+
287
+ expect(Object.entries(out)).toEqual(Object.entries(source));
288
+ expect(out[EntityRuntimeKey]).toBe(outRuntime);
289
+ expect(out[EntityRuntimeKey]).not.toBe(sourceRuntime);
290
+ expect(getEntityBinding(out)).toBe(outBinding);
291
+ expect(getEntityBinding(source)).toBe(sourceBinding);
292
+ });
63
293
  });
294
+
64
295
  describe('getScreenContainingRect', () => {
65
- it('is exported', () => expect(screenContract.getScreenContainingRect).toBeTypeOf('function'));
296
+ it('selects the screen with the largest overlap area', () => {
297
+ const left = createTestScreen(1, 0, 0, 100, 100);
298
+ const lowerRight = createTestScreen(2, 100, 80, 100, 100);
299
+ const host = createScreenQueryHost([left, lowerRight]);
300
+
301
+ const result = getScreenContainingRect(host, { x: 50, y: 50, width: 100, height: 60 }, createScreenInfo());
302
+
303
+ expect(result.id).toBe(1);
304
+ });
305
+
306
+ it('falls back to the screen nearest the rectangle center when none overlap', () => {
307
+ const host = createScreenQueryHost(createSeparatedScreens());
308
+
309
+ const result = getScreenContainingRect(host, { x: 230, y: 20, width: 20, height: 20 }, createScreenInfo());
310
+
311
+ expect(result.id).toBe(2);
312
+ });
313
+
314
+ it('fills the documented default when no screens exist', () => {
315
+ const out = createTestScreen(99, 10, 20, 30, 40);
316
+
317
+ expect(getScreenContainingRect(createScreenQueryHost([]), { x: 0, y: 0, width: 10, height: 10 }, out)).toBe(out);
318
+ expect(Object.entries(out)).toEqual(Object.entries(createScreenInfo()));
319
+ });
66
320
  });
321
+
67
322
  describe('getScreenCurrentMode', () => {
68
- it('is exported', () => expect(screenContract.getScreenCurrentMode).toBeTypeOf('function'));
323
+ it('derives current dimensions and display metrics while clearing unknown format', () => {
324
+ const screen = createTestScreen(1, 0, 0, 1920, 1080, { refreshRate: 144, colorDepth: 30 });
325
+ const out = createScreenMode();
326
+ out.pixelFormat = 'stale';
327
+
328
+ expect(getScreenCurrentMode(screen, out)).toBe(out);
329
+ expect(out).toMatchObject({ width: 1920, height: 1080, refreshRate: 144, colorDepth: 30, pixelFormat: '' });
330
+ });
69
331
  });
332
+
70
333
  describe('getScreenCursorPosition', () => {
71
- it('is exported', () => expect(screenContract.getScreenCursorPosition).toBeTypeOf('function'));
334
+ it('delegates to the host with the caller-owned output', () => {
335
+ const host = createScreenQueryHost([], { x: -20, y: 45 });
336
+ const out = { x: 0, y: 0 };
337
+
338
+ expect(getScreenCursorPosition(host, out)).toBe(out);
339
+ expect(out).toEqual({ x: -20, y: 45 });
340
+ expect(host.screen.query.getCursorPosition).toHaveBeenCalledWith(out);
341
+ });
72
342
  });
343
+
73
344
  describe('getScreenCursorScreen', () => {
74
- it('is exported', () => expect(screenContract.getScreenCursorScreen).toBeTypeOf('function'));
345
+ it('resolves the host cursor position to its nearest screen', () => {
346
+ const host = createScreenQueryHost(createSeparatedScreens(), { x: 340, y: 25 });
347
+ const out = createScreenInfo();
348
+
349
+ expect(getScreenCursorScreen(host, out)).toBe(out);
350
+ expect(out.id).toBe(2);
351
+ });
75
352
  });
353
+
76
354
  describe('getScreenDetailPermission', () => {
77
- it('is exported', () => expect(screenContract.getScreenDetailPermission).toBeTypeOf('function'));
355
+ it('returns the permission state supplied by the host', async () => {
356
+ const host = createScreenDetailsHost('granted', true);
357
+
358
+ await expect(getScreenDetailPermission(host)).resolves.toBe('granted');
359
+ expect(host.screen.details.queryPermission).toHaveBeenCalledOnce();
360
+ });
78
361
  });
362
+
79
363
  describe('getScreenNearestPoint', () => {
80
- it('is exported', () => expect(screenContract.getScreenNearestPoint).toBeTypeOf('function'));
364
+ it('uses half-open containment before distance', () => {
365
+ const horizontalHost = createScreenQueryHost([
366
+ createTestScreen(1, 0, 0, 100, 100),
367
+ createTestScreen(2, 100, 0, 200, 100),
368
+ ]);
369
+ const verticalHost = createScreenQueryHost([
370
+ createTestScreen(1, 0, 0, 100, 100),
371
+ createTestScreen(2, 0, 100, 100, 200),
372
+ ]);
373
+
374
+ expect(getScreenNearestPoint(horizontalHost, { x: 20, y: 30 }, createScreenInfo()).id).toBe(1);
375
+ expect(getScreenNearestPoint(horizontalHost, { x: 100, y: 30 }, createScreenInfo()).id).toBe(2);
376
+ expect(getScreenNearestPoint(verticalHost, { x: 30, y: 100 }, createScreenInfo()).id).toBe(2);
377
+ });
378
+
379
+ it('selects the nearest screen center when the point is outside every screen', () => {
380
+ const host = createScreenQueryHost(createSeparatedScreens());
381
+ const diagonalHost = createScreenQueryHost([
382
+ createTestScreen(1, 0, 0, 100, 100),
383
+ createTestScreen(2, 300, 200, 100, 100),
384
+ ]);
385
+
386
+ expect(getScreenNearestPoint(host, { x: 180, y: 50 }, createScreenInfo()).id).toBe(1);
387
+ expect(getScreenNearestPoint(host, { x: 240, y: 50 }, createScreenInfo()).id).toBe(2);
388
+ expect(getScreenNearestPoint(diagonalHost, { x: 200, y: 100 }, createScreenInfo()).id).toBe(1);
389
+ expect(getScreenNearestPoint(diagonalHost, { x: 200, y: 180 }, createScreenInfo()).id).toBe(2);
390
+ });
391
+
392
+ it('keeps the first screen when center distances tie', () => {
393
+ const host = createScreenQueryHost(createSeparatedScreens());
394
+
395
+ expect(getScreenNearestPoint(host, { x: 200, y: 50 }, createScreenInfo()).id).toBe(1);
396
+ });
397
+
398
+ it('fills the documented default when no screens exist', () => {
399
+ const out = createTestScreen(99, 10, 20, 30, 40);
400
+
401
+ expect(getScreenNearestPoint(createScreenQueryHost([]), { x: 5, y: 5 }, out)).toBe(out);
402
+ expect(Object.entries(out)).toEqual(Object.entries(createScreenInfo()));
403
+ });
81
404
  });
405
+
82
406
  describe('getScreenNearestRect', () => {
83
- it('is exported', () => expect(screenContract.getScreenNearestRect).toBeTypeOf('function'));
407
+ it('prefers a screen that fully contains the rectangle', () => {
408
+ const host = createScreenQueryHost(createSeparatedScreens());
409
+
410
+ const result = getScreenNearestRect(host, { x: 320, y: 20, width: 40, height: 50 }, createScreenInfo());
411
+
412
+ expect(result.id).toBe(2);
413
+ });
414
+
415
+ it('falls back to the screen nearest the rectangle center', () => {
416
+ const host = createScreenQueryHost(createSeparatedScreens());
417
+
418
+ const result = getScreenNearestRect(host, { x: 170, y: 20, width: 20, height: 20 }, createScreenInfo());
419
+
420
+ expect(result.id).toBe(1);
421
+ });
422
+
423
+ it('uses center selection rather than largest overlap when no screen fully contains the rectangle', () => {
424
+ const left = createTestScreen(1, 0, 0, 100, 100);
425
+ const right = createTestScreen(2, 100, 0, 200, 100);
426
+ const host = createScreenQueryHost([left, right]);
427
+ const rect = { x: 50, y: 10, width: 100, height: 50 };
428
+
429
+ expect(getScreenContainingRect(host, rect, createScreenInfo()).id).toBe(1);
430
+ expect(getScreenNearestRect(host, rect, createScreenInfo()).id).toBe(2);
431
+ });
432
+
433
+ it('honors inclusive rectangle boundaries and full extents when testing containment', () => {
434
+ const boundsHost = createScreenQueryHost([
435
+ createTestScreen(1, 0, 0, 100, 100),
436
+ createTestScreen(2, -10, -10, 200, 200),
437
+ ]);
438
+ const horizontalExtentHost = createScreenQueryHost([
439
+ createTestScreen(1, 0, 0, 80, 100),
440
+ createTestScreen(2, 30, 0, 100, 100),
441
+ ]);
442
+ const verticalExtentHost = createScreenQueryHost([
443
+ createTestScreen(1, 0, 0, 100, 80),
444
+ createTestScreen(2, 0, 30, 100, 100),
445
+ ]);
446
+
447
+ expect(getScreenNearestRect(boundsHost, { x: 0, y: 0, width: 100, height: 100 }, createScreenInfo()).id).toBe(1);
448
+ expect(
449
+ getScreenNearestRect(horizontalExtentHost, { x: 40, y: 0, width: 60, height: 100 }, createScreenInfo()).id,
450
+ ).toBe(2);
451
+ expect(
452
+ getScreenNearestRect(verticalExtentHost, { x: 0, y: 40, width: 100, height: 60 }, createScreenInfo()).id,
453
+ ).toBe(2);
454
+ });
455
+
456
+ it('fills the documented default when no screens exist', () => {
457
+ const out = createTestScreen(99, 10, 20, 30, 40);
458
+
459
+ expect(getScreenNearestRect(createScreenQueryHost([]), { x: 0, y: 0, width: 10, height: 10 }, out)).toBe(out);
460
+ expect(Object.entries(out)).toEqual(Object.entries(createScreenInfo()));
461
+ });
84
462
  });
463
+
85
464
  describe('getScreens', () => {
86
- it('is exported', () => expect(screenContract.getScreens).toBeTypeOf('function'));
465
+ it('delegates enumeration into and returns the caller-owned array', () => {
466
+ const screen = createTestScreen(5, 0, 0, 1920, 1080);
467
+ const host = createScreenQueryHost([screen]);
468
+ const out: ScreenInfo[] = [];
469
+
470
+ expect(getScreens(host, out)).toBe(out);
471
+ expect(out).toEqual([screen]);
472
+ expect(host.screen.query.getScreens).toHaveBeenCalledWith(out);
473
+ });
87
474
  });
475
+
88
476
  describe('getScreenWorkArea', () => {
89
- it('is exported', () => expect(screenContract.getScreenWorkArea).toBeTypeOf('function'));
477
+ it('extracts work dimensions at the screen desktop origin', () => {
478
+ const screen = createTestScreen(1, 100, -50, 1920, 1080, { workWidth: 1900, workHeight: 1040 });
479
+ const out = { x: 0, y: 0, width: 0, height: 0 };
480
+
481
+ expect(getScreenWorkArea(screen, out)).toBe(out);
482
+ expect(out).toEqual({ x: 100, y: -50, width: 1900, height: 1040 });
483
+ });
90
484
  });
485
+
91
486
  describe('requestScreenDetails', () => {
92
- it('is exported', () => expect(screenContract.requestScreenDetails).toBeTypeOf('function'));
93
- });
94
- describe('screen entities', () => {
95
- it('composes values and event groups as entities', () => {
96
- expect(EntityRuntimeKey in createScreenInfo()).toBe(true);
97
- expect(EntityRuntimeKey in createScreenMode()).toBe(true);
98
- expect(EntityRuntimeKey in createScreenPermissionChange()).toBe(true);
99
- expect(EntityRuntimeKey in createScreenSignals()).toBe(true);
100
- });
101
-
102
- it('attaches and detaches display events through the supplied host', () => {
103
- const unsubscribe = vi.fn();
104
- let listener: ((event: any) => void) | undefined;
105
- const host = {
106
- screen: {
107
- change: {
108
- [EntityRuntimeKey]: {},
109
- subscribe(next: typeof listener) {
110
- listener = next;
111
- return unsubscribe;
112
- },
113
- },
114
- },
115
- } as any;
116
- const signals = createScreenSignals();
117
- const added = vi.fn();
118
- connectSignal(signals.onScreenAdded, added);
119
- attachScreenSignals(host, signals);
120
- listener?.({ kind: 'ScreenAdded', screen: createScreenInfo(), changedMetrics: null });
121
- expect(added).toHaveBeenCalledOnce();
122
- detachScreenSignals(signals);
123
- expect(unsubscribe).toHaveBeenCalledOnce();
487
+ it('returns whether the host granted detailed screen access', async () => {
488
+ const host = createScreenDetailsHost('prompt', true);
489
+
490
+ await expect(requestScreenDetails(host)).resolves.toBe(true);
491
+ expect(host.screen.details.request).toHaveBeenCalledOnce();
124
492
  });
493
+ });
125
494
 
126
- it('clears every signal on dispose', () => {
127
- const signals = createScreenSignals();
128
- connectSignal(signals.onScreenAdded, vi.fn());
129
- connectSignal(signals.onScreenMetricsChanged, vi.fn());
130
- connectSignal(signals.onScreenRemoved, vi.fn());
131
- disposeScreenSignals(signals);
132
- expect(signals.onScreenAdded.data).toBeNull();
133
- expect(signals.onScreenMetricsChanged.data).toBeNull();
134
- expect(signals.onScreenRemoved.data).toBeNull();
495
+ describe('screenToDipPoint', () => {
496
+ it('converts screen-local pixels to desktop DIPs and returns out', () => {
497
+ const screen = createTestScreen(1, 100, 50, 800, 600, { scaleFactor: 2 });
498
+ const out = { x: -1, y: -1 };
499
+
500
+ expect(screenToDipPoint(screen, { x: 24, y: 46 }, out)).toBe(out);
501
+ expect(out).toEqual({ x: 112, y: 73 });
502
+ });
503
+
504
+ it('is safe when out aliases the input point', () => {
505
+ const screen = createTestScreen(1, 100, 50, 800, 600, { scaleFactor: 2 });
506
+ const point = { x: 24, y: 46 };
507
+
508
+ screenToDipPoint(screen, point, point);
135
509
 
136
- const permission = createScreenPermissionChange();
137
- connectSignal(permission.onChange, vi.fn());
138
- disposeScreenPermissionChange(permission);
139
- expect(permission.onChange.data).toBeNull();
510
+ expect(point).toEqual({ x: 112, y: 73 });
140
511
  });
141
512
  });
142
- describe('screen queries', () => {
143
- it('takes the host explicitly', () => {
144
- const info = createScreenInfo();
145
- info.width = 1920;
146
- const host = {
147
- screen: { query: { [EntityRuntimeKey]: {}, getScreens: (out: any[]) => ((out[0] = info), out) } },
148
- } as any;
149
- expect(getScreens(host, [])[0]).toBe(info);
513
+
514
+ describe('screenToDipRect', () => {
515
+ it('converts screen-local position and extent to desktop DIPs and returns out', () => {
516
+ const screen = createTestScreen(1, 100, 50, 800, 600, { scaleFactor: 2 });
517
+ const out = { x: -1, y: -1, width: -1, height: -1 };
518
+
519
+ expect(screenToDipRect(screen, { x: 24, y: 46, width: 60, height: 80 }, out)).toBe(out);
520
+ expect(out).toEqual({ x: 112, y: 73, width: 30, height: 40 });
150
521
  });
151
522
 
152
- it('derives the current mode without a provider', () => {
153
- const info = createScreenInfo();
154
- Object.assign(info, { width: 1920, height: 1080, refreshRate: 60, colorDepth: 24 });
155
- const mode = getScreenCurrentMode(info, createScreenMode());
156
- expect(mode).toMatchObject({ width: 1920, height: 1080, refreshRate: 60, colorDepth: 24 });
523
+ it('is safe when out aliases the input rectangle', () => {
524
+ const screen = createTestScreen(1, 100, 50, 800, 600, { scaleFactor: 2 });
525
+ const rect = { x: 24, y: 46, width: 60, height: 80 };
526
+
527
+ screenToDipRect(screen, rect, rect);
528
+
529
+ expect(rect).toEqual({ x: 112, y: 73, width: 30, height: 40 });
157
530
  });
158
531
  });
159
532
 
160
- describe('screenToDipPoint', () => {
161
- it('is exported', () => expect(screenContract.screenToDipPoint).toBeTypeOf('function'));
162
- });
533
+ function createPermissionChangeHarness() {
534
+ let listener: ((state: ScreenPermissionState) => void) | undefined;
535
+ const unsubscribe = vi.fn();
536
+ const host = {
537
+ screen: {
538
+ permissionChange: createEntity({
539
+ subscribe(next: (state: ScreenPermissionState) => void): () => void {
540
+ listener = next;
541
+ return unsubscribe;
542
+ },
543
+ }),
544
+ },
545
+ };
546
+ return { host, emit: (state: ScreenPermissionState) => listener?.(state), unsubscribe };
547
+ }
163
548
 
164
- describe('screenToDipRect', () => {
165
- it('is exported', () => expect(screenContract.screenToDipRect).toBeTypeOf('function'));
166
- });
549
+ function createScreenChangeHarness() {
550
+ let listener: ((event: Readonly<ScreenChangeEvent>) => void) | undefined;
551
+ const unsubscribe = vi.fn();
552
+ const host = {
553
+ screen: {
554
+ change: createEntity({
555
+ subscribe(next: (event: Readonly<ScreenChangeEvent>) => void): () => void {
556
+ listener = next;
557
+ return unsubscribe;
558
+ },
559
+ }),
560
+ },
561
+ };
562
+ return { host, emit: (event: Readonly<ScreenChangeEvent>) => listener?.(event), unsubscribe };
563
+ }
564
+
565
+ function createScreenDetailsHost(permission: ScreenPermissionState, requestResult: boolean) {
566
+ return {
567
+ screen: {
568
+ details: createEntity({
569
+ queryPermission: vi.fn(async () => permission),
570
+ request: vi.fn(async () => requestResult),
571
+ }),
572
+ },
573
+ };
574
+ }
575
+
576
+ function createScreenQueryHost(
577
+ screens: readonly ScreenInfo[],
578
+ cursor: Readonly<{ x: number; y: number }> = { x: 0, y: 0 },
579
+ ): HasScreenQuery {
580
+ return {
581
+ screen: {
582
+ query: createEntity({
583
+ getCursorPosition: vi.fn((out: { x: number; y: number }) => {
584
+ out.x = cursor.x;
585
+ out.y = cursor.y;
586
+ return out;
587
+ }),
588
+ getPrimaryScreen: vi.fn((out: ScreenInfo) => {
589
+ const primary = screens.find((screen) => screen.isPrimary) ?? screens[0];
590
+ if (primary !== undefined) Object.assign(out, primary);
591
+ return out;
592
+ }),
593
+ getScreens: vi.fn((out: ScreenInfo[]) => {
594
+ out.length = 0;
595
+ out.push(...screens);
596
+ return out;
597
+ }),
598
+ }),
599
+ },
600
+ };
601
+ }
602
+
603
+ function createSeparatedScreens(): ScreenInfo[] {
604
+ return [createTestScreen(1, 0, 0, 100, 100), createTestScreen(2, 300, 0, 100, 100)];
605
+ }
606
+
607
+ function createTestScreen(
608
+ id: number,
609
+ x: number,
610
+ y: number,
611
+ width: number,
612
+ height: number,
613
+ overrides: Partial<ScreenInfo> = {},
614
+ ): ScreenInfo {
615
+ return Object.assign(
616
+ createScreenInfo(),
617
+ { id, x, y, width, height, workWidth: width, workHeight: height },
618
+ overrides,
619
+ );
620
+ }