@bobfrankston/winpos 2.0.40 → 2.0.42
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 +13 -13
- package/index.d.ts +16 -0
- package/index.d.ts.map +1 -1
- package/index.js +378 -54
- package/index.js.map +1 -1
- package/index.ts +440 -54
- package/package.json +2 -3
- package/.claude/settings.local.json +0 -36
- package/.editorconfig +0 -20
- package/.gitattributes +0 -16
- package/.vscode/launch.json +0 -59
- package/.vscode/settings.json +0 -25
- package/.vscode/spellright.dict +0 -4
- package/.vscode/tasks.json +0 -20
- package/DEVELOPMENT.md +0 -148
- package/problem.txt +0 -11
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"permissions": {
|
|
3
|
-
"allow": [
|
|
4
|
-
"Bash(npm search:*)",
|
|
5
|
-
"Bash(npm run installer:*)",
|
|
6
|
-
"Bash(npm run build:*)",
|
|
7
|
-
"Bash(node index.js:*)",
|
|
8
|
-
"Bash(git add:*)",
|
|
9
|
-
"Bash(git diff-index:*)",
|
|
10
|
-
"Bash(git commit:*)",
|
|
11
|
-
"Bash(npm version:*)",
|
|
12
|
-
"Bash(git push:*)",
|
|
13
|
-
"Read(//y/x/bin/**)",
|
|
14
|
-
"Bash(git rev-list:*)",
|
|
15
|
-
"Bash(git count-objects:*)",
|
|
16
|
-
"Bash(git verify-pack:*)",
|
|
17
|
-
"Bash(nul)",
|
|
18
|
-
"Bash(more:*)",
|
|
19
|
-
"Bash(git cat-file:*)",
|
|
20
|
-
"Bash(findstr:*)",
|
|
21
|
-
"Bash(powershell -Command \"git rev-list --objects --all | git cat-file --batch-check=''%(objecttype) %(objectname) %(objectsize) %(rest)'' | Where-Object { $_-match ''^blob'' } | Sort-Object { [int]($_-split '' '')[2] } -Descending | Select-Object -First 20\")",
|
|
22
|
-
"Bash(dir /s /o-s Y:devutilswinpos 2)",
|
|
23
|
-
"Bash(git gc:*)",
|
|
24
|
-
"Bash(git rm:*)",
|
|
25
|
-
"Bash(git reset:*)",
|
|
26
|
-
"Bash(git reflog:*)",
|
|
27
|
-
"Bash(git fetch:*)",
|
|
28
|
-
"Bash(git clone:*)",
|
|
29
|
-
"Bash(cmd /c \"cd /d Y:\\dev\\utils && git clone https://github.com/BobFrankston/winpos.git winpos-clean\")",
|
|
30
|
-
"Bash(git -C \"Y:\\dev\\utils\\winpos-clean\" count-objects -vH)",
|
|
31
|
-
"Bash(xcopy:*)"
|
|
32
|
-
],
|
|
33
|
-
"deny": [],
|
|
34
|
-
"ask": []
|
|
35
|
-
}
|
|
36
|
-
}
|
package/.editorconfig
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
# EditorConfig is awesome: https://EditorConfig.org
|
|
2
|
-
|
|
3
|
-
# top-most EditorConfig file
|
|
4
|
-
root = true
|
|
5
|
-
|
|
6
|
-
# Unix-style newlines with a newline ending every file
|
|
7
|
-
[*]
|
|
8
|
-
end_of_line = lf
|
|
9
|
-
insert_final_newline = true
|
|
10
|
-
charset = utf-8
|
|
11
|
-
trim_trailing_whitespace = true
|
|
12
|
-
|
|
13
|
-
# TypeScript/JavaScript files
|
|
14
|
-
[*.{ts,js,json}]
|
|
15
|
-
indent_style = space
|
|
16
|
-
indent_size = 4
|
|
17
|
-
|
|
18
|
-
# Markdown files
|
|
19
|
-
[*.md]
|
|
20
|
-
trim_trailing_whitespace = false
|
package/.gitattributes
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
# Set default behavior to automatically normalize line endings to LF
|
|
2
|
-
* text=auto eol=lf
|
|
3
|
-
|
|
4
|
-
# Explicitly declare text files you want to always be normalized and converted to LF
|
|
5
|
-
*.ts text eol=lf
|
|
6
|
-
*.js text eol=lf
|
|
7
|
-
*.json text eol=lf
|
|
8
|
-
*.md text eol=lf
|
|
9
|
-
*.txt text eol=lf
|
|
10
|
-
|
|
11
|
-
# Denote all files that are truly binary and should not be modified
|
|
12
|
-
*.png binary
|
|
13
|
-
*.jpg binary
|
|
14
|
-
*.ico binary
|
|
15
|
-
*.exe binary
|
|
16
|
-
*.dll binary
|
package/.vscode/launch.json
DELETED
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"configurations": [
|
|
3
|
-
{
|
|
4
|
-
"name": "noargs",
|
|
5
|
-
"program": "${workspaceFolder}/index.js",
|
|
6
|
-
"request": "launch",
|
|
7
|
-
"skipFiles": [
|
|
8
|
-
"<node_internals>/**"
|
|
9
|
-
],
|
|
10
|
-
"type": "node"
|
|
11
|
-
},
|
|
12
|
-
{
|
|
13
|
-
"name": "ping/node",
|
|
14
|
-
"program": "${workspaceFolder}/index.js",
|
|
15
|
-
"request": "launch",
|
|
16
|
-
"skipFiles": [
|
|
17
|
-
"<node_internals>/**"
|
|
18
|
-
],
|
|
19
|
-
"type": "node",
|
|
20
|
-
"args": [
|
|
21
|
-
"pings",
|
|
22
|
-
"67",
|
|
23
|
-
"702",
|
|
24
|
-
"3",
|
|
25
|
-
"1200",
|
|
26
|
-
"645"
|
|
27
|
-
]
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"name": "resender/test",
|
|
31
|
-
"program": "${workspaceFolder}/index.js",
|
|
32
|
-
"request": "launch",
|
|
33
|
-
"skipFiles": [
|
|
34
|
-
"<node_internals>/**"
|
|
35
|
-
],
|
|
36
|
-
"type": "node",
|
|
37
|
-
"args": [
|
|
38
|
-
"resender",
|
|
39
|
-
"1330",
|
|
40
|
-
"10",
|
|
41
|
-
"3"
|
|
42
|
-
]
|
|
43
|
-
},
|
|
44
|
-
{
|
|
45
|
-
"name": "bun",
|
|
46
|
-
"program": "${workspaceFolder}/index.js",
|
|
47
|
-
"request": "launch",
|
|
48
|
-
"type": "bun",
|
|
49
|
-
"args": [
|
|
50
|
-
"pings",
|
|
51
|
-
"67",
|
|
52
|
-
"702",
|
|
53
|
-
"3",
|
|
54
|
-
"1605",
|
|
55
|
-
"645"
|
|
56
|
-
]
|
|
57
|
-
}
|
|
58
|
-
]
|
|
59
|
-
}
|
package/.vscode/settings.json
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"workbench.colorCustomizations": {
|
|
3
|
-
"activityBar.activeBackground": "#95d998",
|
|
4
|
-
"activityBar.background": "#95d998",
|
|
5
|
-
"activityBar.foreground": "#15202b",
|
|
6
|
-
"activityBar.inactiveForeground": "#15202b99",
|
|
7
|
-
"activityBarBadge.background": "#7672cd",
|
|
8
|
-
"activityBarBadge.foreground": "#e7e7e7",
|
|
9
|
-
"commandCenter.border": "#15202b99",
|
|
10
|
-
"sash.hoverBorder": "#95d998",
|
|
11
|
-
"statusBar.background": "#70cb73",
|
|
12
|
-
"statusBar.foreground": "#15202b",
|
|
13
|
-
"statusBarItem.hoverBackground": "#4bbd4e",
|
|
14
|
-
"statusBarItem.remoteBackground": "#70cb73",
|
|
15
|
-
"statusBarItem.remoteForeground": "#15202b",
|
|
16
|
-
"titleBar.activeBackground": "#70cb73",
|
|
17
|
-
"titleBar.activeForeground": "#15202b",
|
|
18
|
-
"titleBar.inactiveBackground": "#70cb7399",
|
|
19
|
-
"titleBar.inactiveForeground": "#15202b99"
|
|
20
|
-
},
|
|
21
|
-
"peacock.color": "#70cb73",
|
|
22
|
-
"files.eol": "\n",
|
|
23
|
-
"files.insertFinalNewline": true,
|
|
24
|
-
"files.trimTrailingWhitespace": true
|
|
25
|
-
}
|
package/.vscode/spellright.dict
DELETED
package/.vscode/tasks.json
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": "2.0.0",
|
|
3
|
-
"tasks": [
|
|
4
|
-
{
|
|
5
|
-
"label": "tsc: watch",
|
|
6
|
-
"type": "shell",
|
|
7
|
-
"command": "tsc",
|
|
8
|
-
"args": ["--watch"],
|
|
9
|
-
"runOptions": {
|
|
10
|
-
"runOn": "folderOpen"
|
|
11
|
-
},
|
|
12
|
-
"problemMatcher": "$tsc-watch",
|
|
13
|
-
"isBackground": true,
|
|
14
|
-
"group": {
|
|
15
|
-
"kind": "build",
|
|
16
|
-
"isDefault": true
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
]
|
|
20
|
-
}
|
package/DEVELOPMENT.md
DELETED
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
# Development Notes for tswinpos
|
|
2
|
-
|
|
3
|
-
## VSCode Setup
|
|
4
|
-
|
|
5
|
-
### Running/Debugging
|
|
6
|
-
- Use VSCode debugger (F5) instead of terminal commands
|
|
7
|
-
- Breakpoints in .ts files work correctly with source maps
|
|
8
|
-
- TypeScript compiles automatically with `tsc -w`
|
|
9
|
-
|
|
10
|
-
### Quick Commands
|
|
11
|
-
```bash
|
|
12
|
-
# Watch mode (keep running in terminal)
|
|
13
|
-
npm run watch
|
|
14
|
-
|
|
15
|
-
# Test CLI
|
|
16
|
-
node index.js "*" # List all windows
|
|
17
|
-
node index.js "Chrome*" 100 100 0 # Move Chrome to position
|
|
18
|
-
|
|
19
|
-
# Debug mode
|
|
20
|
-
node index.js -d "*"
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Project Structure
|
|
24
|
-
|
|
25
|
-
```
|
|
26
|
-
tswinpos/
|
|
27
|
-
├── index.ts # Main entry + CLI + exported API
|
|
28
|
-
├── ffi-wrapper.ts # Windows API FFI (Node/Bun runtime detection)
|
|
29
|
-
├── screens.ts # Screen enumeration
|
|
30
|
-
├── windows.ts # Window enumeration + state management
|
|
31
|
-
├── tabs.ts # Tab enumeration (placeholder - COM interop needed)
|
|
32
|
-
├── ignores.txt # Window title filters
|
|
33
|
-
├── package.json # @bobfrankston/tswinpos
|
|
34
|
-
└── tsconfig.json # Standard config
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Key Implementation Details
|
|
38
|
-
|
|
39
|
-
### FFI Pattern (following sqlunified)
|
|
40
|
-
```typescript
|
|
41
|
-
// 1. Load library
|
|
42
|
-
const koffi = (await import('koffi')).default;
|
|
43
|
-
const lib = koffi.load('user32.dll');
|
|
44
|
-
|
|
45
|
-
// 2. Define functions
|
|
46
|
-
const GetWindowRect = lib.func('bool __stdcall GetWindowRect(void *hWnd, RECT *lpRect)');
|
|
47
|
-
|
|
48
|
-
// 3. Use Buffer for structures (simpler than koffi.alloc/decode)
|
|
49
|
-
const rectBuf = Buffer.alloc(16); // 4 ints
|
|
50
|
-
GetWindowRect(hwnd, rectBuf);
|
|
51
|
-
rect.Left = rectBuf.readInt32LE(0);
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### Differences from sqlunified
|
|
55
|
-
- **sqlunified**: Uses `koffi.alloc()` and `koffi.decode()` for memory management
|
|
56
|
-
- **tswinpos**: Uses Node.js Buffer directly for simpler struct handling
|
|
57
|
-
- **Both**: Use same `.func()` and `koffi.register()` patterns
|
|
58
|
-
|
|
59
|
-
### Runtime Detection
|
|
60
|
-
```typescript
|
|
61
|
-
const isBun = typeof Bun !== 'undefined';
|
|
62
|
-
|
|
63
|
-
if (isBun) {
|
|
64
|
-
// Use bun:ffi
|
|
65
|
-
} else {
|
|
66
|
-
// Use koffi
|
|
67
|
-
}
|
|
68
|
-
```
|
|
69
|
-
|
|
70
|
-
### CLI + Library Pattern
|
|
71
|
-
```typescript
|
|
72
|
-
// Export API for library use
|
|
73
|
-
export { enumerateWindows, findWindowsByPattern, ... };
|
|
74
|
-
|
|
75
|
-
// CLI entry point
|
|
76
|
-
if (import.meta.main) {
|
|
77
|
-
run(process.argv.slice(2));
|
|
78
|
-
}
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Common Tasks
|
|
82
|
-
|
|
83
|
-
### Adding New Windows API Functions
|
|
84
|
-
1. Add to FFI wrapper interface in `ffi-wrapper.ts`
|
|
85
|
-
2. Implement for both Bun and Node.js paths
|
|
86
|
-
3. Export from appropriate module
|
|
87
|
-
4. Re-export from `index.ts` if public API
|
|
88
|
-
|
|
89
|
-
### Testing
|
|
90
|
-
```bash
|
|
91
|
-
# List windows (test enumeration)
|
|
92
|
-
node index.js "*"
|
|
93
|
-
|
|
94
|
-
# Test positioning
|
|
95
|
-
node index.js "Notepad" 0 0 0
|
|
96
|
-
|
|
97
|
-
# Test with debug
|
|
98
|
-
node index.js -d "Chrome*" 100 100 1
|
|
99
|
-
```
|
|
100
|
-
|
|
101
|
-
### Shell Gotcha
|
|
102
|
-
⚠️ **IMPORTANT**: Quote the asterisk!
|
|
103
|
-
```bash
|
|
104
|
-
node index.js "*" # ✅ Correct - lists windows
|
|
105
|
-
node index.js * # ❌ Wrong - shell expands to all files
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Known Limitations
|
|
109
|
-
|
|
110
|
-
### Tab Enumeration
|
|
111
|
-
- Windows has no standard tab enumeration API
|
|
112
|
-
- Would require COM interop with UI Automation
|
|
113
|
-
- Placeholder API in `tabs.ts` with documentation
|
|
114
|
-
- See `TAB_ENUMERATION_NOTE` for details
|
|
115
|
-
|
|
116
|
-
### Screen Enumeration
|
|
117
|
-
- Currently simplified (single screen)
|
|
118
|
-
- Full multi-monitor via EnumDisplayMonitors would need:
|
|
119
|
-
- Complex koffi struct handling
|
|
120
|
-
- MONITORINFOEXW structure
|
|
121
|
-
- Callback registration
|
|
122
|
-
|
|
123
|
-
## Future Enhancements
|
|
124
|
-
|
|
125
|
-
1. **Full Multi-Monitor Support**
|
|
126
|
-
- Implement proper EnumDisplayMonitors
|
|
127
|
-
- Parse MONITORINFOEXW structure
|
|
128
|
-
|
|
129
|
-
2. **Tab Enumeration**
|
|
130
|
-
- Requires UI Automation COM interop
|
|
131
|
-
- Consider PowerShell bridge alternative
|
|
132
|
-
|
|
133
|
-
3. **Window Classes**
|
|
134
|
-
- Add GetClassName API
|
|
135
|
-
- Filter by window class
|
|
136
|
-
|
|
137
|
-
4. **Window Properties**
|
|
138
|
-
- Process ID (GetWindowThreadProcessId)
|
|
139
|
-
- Window styles (GetWindowLong)
|
|
140
|
-
- Z-order information
|
|
141
|
-
|
|
142
|
-
## Notes for Future Claude Code Sessions
|
|
143
|
-
|
|
144
|
-
- All .ts/.js/.d.ts/.map files are co-located (no dist folder)
|
|
145
|
-
- Use `tsc -w` for continuous compilation
|
|
146
|
-
- Test with `node index.js` directly (source maps work)
|
|
147
|
-
- Follow patterns from sqlunified for koffi usage
|
|
148
|
-
- Remember: Buffer.readInt32LE() for struct parsing
|
package/problem.txt
DELETED