@bobfrankston/winpos 2.0.51 → 2.0.53
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 +296 -200
- package/ffi-wrapper.d.ts +56 -0
- package/ffi-wrapper.js +188 -4
- package/index.d.ts +15 -4
- package/index.js +195 -53
- package/monitors.d.ts +67 -0
- package/monitors.js +146 -0
- package/package.json +10 -3
- package/screenlayout.d.ts +108 -0
- package/screenlayout.js +243 -0
- package/screennums.d.ts +4 -1
- package/screennums.js +48 -16
- package/screens.d.ts +27 -0
- package/screens.js +54 -1
package/README.md
CHANGED
|
@@ -1,200 +1,296 @@
|
|
|
1
|
-
# @bobfrankston/winpos
|
|
2
|
-
|
|
3
|
-
TypeScript implementation of WinPos - A Windows window positioning utility for multi-monitor setups.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Cross-Runtime**: Works with both Node.js (24+) and Bun
|
|
8
|
-
- **FFI-based**: Direct Windows API calls via `koffi` (Node.js) or `bun:ffi` (Bun)
|
|
9
|
-
- **Multi-Monitor**: Full support for multiple displays
|
|
10
|
-
- **Flexible Matching**: Find windows by exact title, prefix, or regex
|
|
11
|
-
- **Window State Management**: Minimize, maximize, restore windows programmatically
|
|
12
|
-
- **Auto-Restore**: Windows are automatically restored from minimized/maximized state when positioning
|
|
13
|
-
- **
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
-
|
|
87
|
-
-
|
|
88
|
-
-
|
|
89
|
-
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
- `-
|
|
94
|
-
- `-
|
|
95
|
-
- `-
|
|
96
|
-
-
|
|
97
|
-
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
winpos
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
]
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
1
|
+
# @bobfrankston/winpos
|
|
2
|
+
|
|
3
|
+
TypeScript implementation of WinPos - A Windows window positioning utility for multi-monitor setups.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Cross-Runtime**: Works with both Node.js (24+) and Bun
|
|
8
|
+
- **FFI-based**: Direct Windows API calls via `koffi` (Node.js) or `bun:ffi` (Bun)
|
|
9
|
+
- **Multi-Monitor**: Full support for multiple displays
|
|
10
|
+
- **Flexible Matching**: Find windows by exact title, prefix, or regex
|
|
11
|
+
- **Window State Management**: Minimize, maximize, restore windows programmatically
|
|
12
|
+
- **Auto-Restore**: Windows are automatically restored from minimized/maximized state when positioning
|
|
13
|
+
- **Monitor Arrangement**: Save the monitor layout and put it back when Windows reverts it (`-screens`)
|
|
14
|
+
- **Library or CLI**: Use as a command-line tool or import as a library
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @bobfrankston/winpos
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Or with Bun:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
bun add @bobfrankston/winpos
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
### Command Line
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Move window to screen 0 at position (100, 200)
|
|
34
|
+
winpos "Notepad" 100 200 0
|
|
35
|
+
|
|
36
|
+
# Move window using percentages
|
|
37
|
+
winpos "Chrome*" 50% 50% 1
|
|
38
|
+
|
|
39
|
+
# Set window size as well
|
|
40
|
+
winpos "Visual Studio Code" 0 0 0 1920 1080
|
|
41
|
+
|
|
42
|
+
# List all windows
|
|
43
|
+
winpos *
|
|
44
|
+
|
|
45
|
+
# Get screen count
|
|
46
|
+
winpos -c
|
|
47
|
+
|
|
48
|
+
# Which physical monitor is screen 0, 1, 2...: id, name, position, mode
|
|
49
|
+
winpos -screens
|
|
50
|
+
|
|
51
|
+
# Save the monitor arrangement, and put it back after Windows reverts it
|
|
52
|
+
winpos -screens save
|
|
53
|
+
winpos -screens restore
|
|
54
|
+
|
|
55
|
+
# Debug mode
|
|
56
|
+
winpos -d "Firefox" 0 0 1
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Pattern Matching
|
|
60
|
+
|
|
61
|
+
- **Exact match**: `winpos "Notepad" 0 0 0`
|
|
62
|
+
- **Prefix match**: `winpos "Chrome*" 0 0 0`
|
|
63
|
+
- **Regex match**: `winpos "/Visual.*Code/" 0 0 0`
|
|
64
|
+
|
|
65
|
+
### As a Library
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
import { run } from '@bobfrankston/winpos';
|
|
69
|
+
|
|
70
|
+
// Move a window programmatically
|
|
71
|
+
run(['Chrome*', '0', '0', '1', '1920', '1080']);
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Screen Numbering
|
|
75
|
+
|
|
76
|
+
Screens are numbered starting from 0, sorted by position:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
+---+---+
|
|
80
|
+
| 2 | 3 |
|
|
81
|
+
+---+---+
|
|
82
|
+
| 0 | 1 |
|
|
83
|
+
+---+---+
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
- 0: Lower right (primary)
|
|
87
|
+
- 1: Lower left
|
|
88
|
+
- 2: Upper left
|
|
89
|
+
- 3: Upper right
|
|
90
|
+
|
|
91
|
+
## Options
|
|
92
|
+
|
|
93
|
+
- `-d` - Debug mode
|
|
94
|
+
- `-dbg` - Verbose debug output
|
|
95
|
+
- `-c` - Return screen count
|
|
96
|
+
- `-v` / `-version` - Show version
|
|
97
|
+
- `-title <name>` - Window title/pattern (alternative to positional)
|
|
98
|
+
- `-pos x,y[,screen]` - Position (comma-separated, screen optional)
|
|
99
|
+
- `-size w,h` - Window size (width,height)
|
|
100
|
+
- `-numsize <inches>` - Physical size of the screen-number overlays (default 2)
|
|
101
|
+
- `-min` - Minimize window
|
|
102
|
+
- `-max` - Maximize window
|
|
103
|
+
- `-load <file>` - Load config from JSON file
|
|
104
|
+
- `-save <file>` - Save config to JSON file (merges if exists)
|
|
105
|
+
- `-screens [list | save [name] | restore [name] | layouts | watch [name]]` - Monitor arrangement (see below)
|
|
106
|
+
- `*` - List all windows
|
|
107
|
+
- `**` - List all windows including ignored
|
|
108
|
+
|
|
109
|
+
## Identifying Screens
|
|
110
|
+
|
|
111
|
+
`winpos` with no arguments, and `winpos *` (or `**`), flash each screen's number
|
|
112
|
+
in the middle of that screen for 5 seconds - the same idea as the Identify
|
|
113
|
+
button in Windows display settings, so you can see which physical monitor is
|
|
114
|
+
screen 0, 1, 2 ... before positioning anything there. With no arguments the
|
|
115
|
+
numbers come up alongside the usage text and its screen table.
|
|
116
|
+
|
|
117
|
+
The numbers are drawn with [msger](https://www.npmjs.com/package/@bobfrankston/msger)
|
|
118
|
+
and all appear at once. They close themselves; winpos returns immediately
|
|
119
|
+
without waiting for them. If msger is unavailable the listing still works, just
|
|
120
|
+
without the numbers.
|
|
121
|
+
|
|
122
|
+
Each overlay is 2 inches square **on the glass**, not 2 inches' worth of pixels
|
|
123
|
+
- `-numsize <inches>` changes that. Sizing anything in pixels (or in CSS
|
|
124
|
+
inches, which are just 96 pixels) comes out a different physical size on every
|
|
125
|
+
monitor, because Windows' scale factor is a preference rather than a
|
|
126
|
+
measurement: a 28" 4K panel left at 100% claims 96 DPI while really being 160.
|
|
127
|
+
winpos asks the display driver for the panel's physical millimetres (EDID, via
|
|
128
|
+
a GDI display DC) and works out each screen's true DPI, so the same square of
|
|
129
|
+
glass lights up on every monitor. Drivers that report nothing fall back to the
|
|
130
|
+
old pixel sizing.
|
|
131
|
+
|
|
132
|
+
```typescript
|
|
133
|
+
import { showScreenNumbers, enumerateScreens, sortScreens, screenDpi } from '@bobfrankston/winpos';
|
|
134
|
+
|
|
135
|
+
const screens = sortScreens(enumerateScreens());
|
|
136
|
+
await showScreenNumbers(screens, 5, 2); // 5 seconds, 2 inches
|
|
137
|
+
console.log(screens.map(screenDpi)); // True DPI per screen
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
## Monitor Arrangement
|
|
141
|
+
|
|
142
|
+
Screen numbers are the monitors sorted by position, and saved window layouts
|
|
143
|
+
address screens by that number. When Windows rearranges the monitors, every
|
|
144
|
+
number changes and every layout puts its windows on the wrong panel. So winpos
|
|
145
|
+
can save the monitor arrangement and put it back - before the windows, in the
|
|
146
|
+
same command.
|
|
147
|
+
|
|
148
|
+
Windows keeps one arrangement per *exact set* of connected monitors. A
|
|
149
|
+
DisplayPort monitor that powers off or deep-sleeps drops off the bus, the set
|
|
150
|
+
changes, and a set Windows has never seen gets the default left-to-right line.
|
|
151
|
+
That is the "my monitors keep reverting" problem this solves.
|
|
152
|
+
|
|
153
|
+
```
|
|
154
|
+
winpos -screens list monitors: screen number, device, id, name, position, mode, primary
|
|
155
|
+
winpos -screens save [name] save the current arrangement
|
|
156
|
+
winpos -screens restore [name] put the saved arrangement back, then read it back and verify
|
|
157
|
+
winpos -screens layouts list the layouts saved for this machine
|
|
158
|
+
winpos -screens watch [name] stay resident and restore whenever Windows moves a saved monitor
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Monitors are identified by EDID id and serial number (`GSM7721:106NTKF55597`),
|
|
162
|
+
read from the monitor's EDID in the registry - never by `\\.\DISPLAYn`, which
|
|
163
|
+
renumbers whenever a monitor comes or goes. A machine normally has one standard
|
|
164
|
+
arrangement, so the name is optional: without one, every command uses the
|
|
165
|
+
layout called `default`. Give a name only for an alternate setup (a travel
|
|
166
|
+
layout, a single-monitor layout).
|
|
167
|
+
|
|
168
|
+
Layouts are kept per machine in `winpos-screens.json` in the user config
|
|
169
|
+
directory (`@bobfrankston/userconfig`). The file has the same shape as the
|
|
170
|
+
older `displays.ps1` tool's `displays.json`, so a layout copies between them.
|
|
171
|
+
|
|
172
|
+
`restore` applies the layout to whichever of its monitors are connected, and
|
|
173
|
+
says so: a saved monitor that is absent is reported and skipped, a connected
|
|
174
|
+
monitor the layout does not mention is left where Windows put it. It then
|
|
175
|
+
waits for Windows to settle, reads the arrangement back, and reports what
|
|
176
|
+
Windows actually did - Windows closes gaps when a monitor is missing, so the
|
|
177
|
+
result can differ from the request. Exit code 1 if anything did not land where
|
|
178
|
+
asked, or if the layout does not exist.
|
|
179
|
+
|
|
180
|
+
`watch` polls the arrangement every few seconds (no message loop, no
|
|
181
|
+
callbacks) and, once a change has settled, re-applies the layout if any saved
|
|
182
|
+
monitor is out of place. It ignores the change its own apply causes, and if an
|
|
183
|
+
apply changes nothing it stops retrying until the set of monitors changes
|
|
184
|
+
again, so it cannot loop. Run it from a logon task if you want it always on.
|
|
185
|
+
|
|
186
|
+
A window layout file can restore the monitors first by using the wrapped form:
|
|
187
|
+
|
|
188
|
+
```json
|
|
189
|
+
{
|
|
190
|
+
"screens": "default",
|
|
191
|
+
"windows": [
|
|
192
|
+
{ "name": "Notepad", "pos": { "x": 100, "y": 100, "screen": 0 } }
|
|
193
|
+
]
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
`screens` is a saved layout name, or an inline layout (the `monitors` array as
|
|
198
|
+
saved). Files without `screens` behave exactly as before.
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
import { enumerateMonitors, saveLayout, getLayout, restoreLayout, formatMonitors } from '@bobfrankston/winpos';
|
|
202
|
+
|
|
203
|
+
console.log(formatMonitors(enumerateMonitors()).join('\n'));
|
|
204
|
+
saveLayout(); // the machine's standard layout
|
|
205
|
+
const result = await restoreLayout(getLayout());
|
|
206
|
+
console.log(result.ok, result.absent, result.mismatches);
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Parameters
|
|
210
|
+
|
|
211
|
+
### Positional (legacy)
|
|
212
|
+
```
|
|
213
|
+
winpos <title> <x> <y> <screen> [<width> <height>]
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
### Flag-based (new)
|
|
217
|
+
```
|
|
218
|
+
winpos <title> -pos x,y[,screen] [-size w,h]
|
|
219
|
+
winpos -title <name> -pos x,y,screen -size w,h
|
|
220
|
+
winpos <title> -min
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### JSON Config
|
|
224
|
+
```
|
|
225
|
+
winpos layout.json
|
|
226
|
+
winpos -load layout.json [-save output.json]
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## JSON Config Format
|
|
230
|
+
|
|
231
|
+
Single window:
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"name": "Notepad",
|
|
235
|
+
"pos": { "x": 100, "y": 100, "screen": 0 },
|
|
236
|
+
"size": { "w": 800, "h": 600 }
|
|
237
|
+
}
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
Multiple windows:
|
|
241
|
+
```json
|
|
242
|
+
[
|
|
243
|
+
{ "name": "app1", "pos": { "x": 0, "y": 0, "screen": 0 } },
|
|
244
|
+
{ "name": "app2*", "pos": { "x": 100, "y": 100, "screen": 1 } },
|
|
245
|
+
{ "name": "pattern", "regex": true, "pos": { "x": 0, "y": 0, "screen": 2 } },
|
|
246
|
+
{ "name": "minimize-me", "minimize": true }
|
|
247
|
+
]
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
- `name` - Window title (exact match, prefix with `*`, or regex if `regex: true`)
|
|
251
|
+
- `regex` - If true, `name` is treated as a regex pattern
|
|
252
|
+
- `pos` - Position with x, y, and optional screen index
|
|
253
|
+
- `size` - Size with w (width) and h (height)
|
|
254
|
+
- `minimize` / `maximize` - Window state
|
|
255
|
+
|
|
256
|
+
Wrapped form, monitors first then windows (see Monitor Arrangement):
|
|
257
|
+
```json
|
|
258
|
+
{ "screens": "default", "windows": [ { "name": "app1", "pos": { "x": 0, "y": 0, "screen": 0 } } ] }
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Known Issues
|
|
262
|
+
|
|
263
|
+
### Windows batch file working directory
|
|
264
|
+
|
|
265
|
+
When calling `winpos` from a batch file without `call`, the working directory may not be inherited correctly due to a Windows cmd.exe quirk.
|
|
266
|
+
|
|
267
|
+
**Workarounds:**
|
|
268
|
+
- Use `call winpos` instead of `winpos` in batch files
|
|
269
|
+
- Use `winpos.ps1` instead of `winpos`
|
|
270
|
+
- Use absolute paths for config files: `winpos "%~dp0config.json"`
|
|
271
|
+
|
|
272
|
+
## Requirements
|
|
273
|
+
|
|
274
|
+
- Windows OS
|
|
275
|
+
- Node.js 24+ or Bun 1.0+
|
|
276
|
+
|
|
277
|
+
## Development
|
|
278
|
+
|
|
279
|
+
```bash
|
|
280
|
+
# Install dependencies
|
|
281
|
+
npm install
|
|
282
|
+
|
|
283
|
+
# Build
|
|
284
|
+
npm run build
|
|
285
|
+
|
|
286
|
+
# Watch mode
|
|
287
|
+
npm run watch
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
## License
|
|
291
|
+
|
|
292
|
+
MIT
|
|
293
|
+
|
|
294
|
+
## Author
|
|
295
|
+
|
|
296
|
+
Bob Frankston
|
package/ffi-wrapper.d.ts
CHANGED
|
@@ -25,9 +25,46 @@ export interface MONITORINFO {
|
|
|
25
25
|
rcMonitor: RECT;
|
|
26
26
|
rcWork: RECT;
|
|
27
27
|
dwFlags: number;
|
|
28
|
+
/** Display device name, e.g. \\.\DISPLAY1 (MONITORINFOEXW szDevice) */
|
|
29
|
+
szDevice?: string;
|
|
28
30
|
}
|
|
29
31
|
export declare const MONITORINFOF_PRIMARY = 1;
|
|
30
32
|
export declare const DEFAULT_SCALE_PERCENT = 100;
|
|
33
|
+
export declare const DISPLAY_DEVICE_ATTACHED_TO_DESKTOP = 1;
|
|
34
|
+
export declare const DISPLAY_DEVICE_PRIMARY_DEVICE = 4;
|
|
35
|
+
export declare const DISPLAY_DEVICE_MIRRORING_DRIVER = 8;
|
|
36
|
+
export declare const EDD_GET_DEVICE_INTERFACE_NAME = 1;
|
|
37
|
+
/** ChangeDisplaySettingsExW return codes */
|
|
38
|
+
export declare const DISP_CHANGE_SUCCESSFUL = 0;
|
|
39
|
+
export declare const DISP_CHANGE_RESTART = 1;
|
|
40
|
+
export declare const DISP_CHANGE_FAILED = -1;
|
|
41
|
+
export declare const DISP_CHANGE_BADMODE = -2;
|
|
42
|
+
export declare const DISP_CHANGE_NOTUPDATED = -3;
|
|
43
|
+
export declare const DISP_CHANGE_BADFLAGS = -4;
|
|
44
|
+
export declare const DISP_CHANGE_BADPARAM = -5;
|
|
45
|
+
export declare const DISP_CHANGE_BADDUALVIEW = -6;
|
|
46
|
+
/** One entry from EnumDisplayDevicesW: a display adapter, or the monitor on one */
|
|
47
|
+
export interface DisplayDevice {
|
|
48
|
+
/** Adapter: \\.\DISPLAY1. Monitor: \\.\DISPLAY1\Monitor0 */
|
|
49
|
+
deviceName: string;
|
|
50
|
+
/** Driver's description: adapter model, or "Generic PnP Monitor"-style monitor text */
|
|
51
|
+
deviceString: string;
|
|
52
|
+
/** DISPLAY_DEVICE_* bits */
|
|
53
|
+
stateFlags: number;
|
|
54
|
+
/** Monitor with EDD_GET_DEVICE_INTERFACE_NAME: \\?\DISPLAY#GSM7721#4&11d6709e&0&UID53318#{guid} */
|
|
55
|
+
deviceID: string;
|
|
56
|
+
deviceKey: string;
|
|
57
|
+
}
|
|
58
|
+
/** An adapter's current mode from EnumDisplaySettingsW */
|
|
59
|
+
export interface DisplayMode {
|
|
60
|
+
/** Desktop position of the top-left corner, in pixels; the primary is 0,0 */
|
|
61
|
+
x: number;
|
|
62
|
+
y: number;
|
|
63
|
+
width: number;
|
|
64
|
+
height: number;
|
|
65
|
+
/** Refresh rate in Hz */
|
|
66
|
+
hz: number;
|
|
67
|
+
}
|
|
31
68
|
export interface WindowsAPI {
|
|
32
69
|
EnumWindows: (callback: (hwnd: bigint, lParam: bigint) => boolean, lParam: bigint) => boolean;
|
|
33
70
|
GetWindowTextW: (hwnd: bigint, text: any, maxCount: number) => number;
|
|
@@ -42,6 +79,25 @@ export interface WindowsAPI {
|
|
|
42
79
|
GetMonitorInfoW: (hMonitor: bigint, lpmi: any) => boolean;
|
|
43
80
|
/** Monitor scale factor as a percent (100, 125, 150...). 100 when unavailable. */
|
|
44
81
|
GetScaleFactorForMonitor?: (hMonitor: bigint) => number;
|
|
82
|
+
/** Physical panel size in millimetres from the display driver (EDID). Null when unavailable. */
|
|
83
|
+
GetPhysicalSizeMm?: (deviceName: string) => {
|
|
84
|
+
width: number;
|
|
85
|
+
height: number;
|
|
86
|
+
} | null;
|
|
87
|
+
/** Adapter iDevNum (device null), or the monitor on an adapter (device = its name, iDevNum 0). Null past the end. */
|
|
88
|
+
EnumDisplayDevicesW?: (device: string, iDevNum: number, flags: number) => DisplayDevice;
|
|
89
|
+
/** Current mode of an adapter. Null when the adapter has none (not attached to the desktop). */
|
|
90
|
+
EnumDisplaySettingsW?: (device: string) => DisplayMode;
|
|
91
|
+
/**
|
|
92
|
+
* Stage a new desktop position for one adapter: written to the registry,
|
|
93
|
+
* not applied yet. Apply all staged positions with ApplyDisplayChanges.
|
|
94
|
+
* Returns a DISP_CHANGE_* code.
|
|
95
|
+
*/
|
|
96
|
+
StageDisplayPosition?: (device: string, x: number, y: number, primary: boolean) => number;
|
|
97
|
+
/** Apply every position staged with StageDisplayPosition. Returns a DISP_CHANGE_* code. */
|
|
98
|
+
ApplyDisplayChanges?: () => number;
|
|
99
|
+
/** A REG_BINARY value under HKEY_LOCAL_MACHINE. Null when the key or value is absent or unreadable. */
|
|
100
|
+
RegGetBinaryHKLM?: (subKey: string, valueName: string) => Buffer;
|
|
45
101
|
}
|
|
46
102
|
declare const user32: WindowsAPI;
|
|
47
103
|
export { user32, isBun };
|