@bobfrankston/winpos 2.0.20
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/.editorconfig +20 -0
- package/.gitattributes +16 -0
- package/DEVELOPMENT.md +148 -0
- package/README.md +126 -0
- package/ffi-wrapper.d.ts +45 -0
- package/ffi-wrapper.d.ts.map +1 -0
- package/ffi-wrapper.js +172 -0
- package/ffi-wrapper.js.map +1 -0
- package/ffi-wrapper.ts +213 -0
- package/ignores.txt +75 -0
- package/index.d.ts +12 -0
- package/index.d.ts.map +1 -0
- package/index.js +213 -0
- package/index.js.map +1 -0
- package/index.ts +294 -0
- package/package.json +41 -0
- package/screens.d.ts +18 -0
- package/screens.d.ts.map +1 -0
- package/screens.js +83 -0
- package/screens.js.map +1 -0
- package/screens.ts +101 -0
- package/tabs.d.ts +42 -0
- package/tabs.d.ts.map +1 -0
- package/tabs.js +115 -0
- package/tabs.js.map +1 -0
- package/tabs.ts +133 -0
- package/tsconfig.json +28 -0
- package/windows.d.ts +51 -0
- package/windows.d.ts.map +1 -0
- package/windows.js +170 -0
- package/windows.js.map +1 -0
- package/windows.ts +200 -0
package/ffi-wrapper.ts
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* FFI Wrapper - Runtime-agnostic FFI for Node.js and Bun
|
|
3
|
+
* Provides a unified interface for calling Windows API functions
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
// @ts-ignore - Bun global may not exist
|
|
7
|
+
const isBun = typeof Bun !== 'undefined';
|
|
8
|
+
|
|
9
|
+
// Windows API Types
|
|
10
|
+
export interface RECT {
|
|
11
|
+
Left: number;
|
|
12
|
+
Top: number;
|
|
13
|
+
Right: number;
|
|
14
|
+
Bottom: number;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// Window state constants
|
|
18
|
+
export const SW_HIDE = 0;
|
|
19
|
+
export const SW_SHOWNORMAL = 1;
|
|
20
|
+
export const SW_SHOWMINIMIZED = 2;
|
|
21
|
+
export const SW_SHOWMAXIMIZED = 3;
|
|
22
|
+
export const SW_MAXIMIZE = 3;
|
|
23
|
+
export const SW_SHOWNOACTIVATE = 4;
|
|
24
|
+
export const SW_SHOW = 5;
|
|
25
|
+
export const SW_MINIMIZE = 6;
|
|
26
|
+
export const SW_SHOWMINNOACTIVE = 7;
|
|
27
|
+
export const SW_SHOWNA = 8;
|
|
28
|
+
export const SW_RESTORE = 9;
|
|
29
|
+
|
|
30
|
+
export interface MONITORINFO {
|
|
31
|
+
cbSize: number;
|
|
32
|
+
rcMonitor: RECT;
|
|
33
|
+
rcWork: RECT;
|
|
34
|
+
dwFlags: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export const MONITORINFOF_PRIMARY = 1;
|
|
38
|
+
|
|
39
|
+
export interface WindowsAPI {
|
|
40
|
+
EnumWindows: (callback: (hwnd: bigint, lParam: bigint) => boolean, lParam: bigint) => boolean;
|
|
41
|
+
GetWindowTextW: (hwnd: bigint, text: any, maxCount: number) => number;
|
|
42
|
+
GetWindowRect: (hwnd: bigint, rect: any) => boolean;
|
|
43
|
+
MoveWindow: (hwnd: bigint, x: number, y: number, width: number, height: number, repaint: boolean) => boolean;
|
|
44
|
+
SetForegroundWindow: (hwnd: bigint) => boolean;
|
|
45
|
+
ShowWindow: (hwnd: bigint, nCmdShow: number) => boolean;
|
|
46
|
+
IsZoomed: (hwnd: bigint) => boolean;
|
|
47
|
+
IsIconic: (hwnd: bigint) => boolean;
|
|
48
|
+
GetWindowPlacement: (hwnd: bigint, placement: any) => boolean;
|
|
49
|
+
EnumDisplayMonitors: (callback: (hMonitor: bigint, hdcMonitor: bigint, lprcMonitor: any, dwData: bigint) => boolean, dwData: bigint) => boolean;
|
|
50
|
+
GetMonitorInfoW: (hMonitor: bigint, lpmi: any) => boolean;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
async function initializeFFI(): Promise<WindowsAPI> {
|
|
54
|
+
if (isBun) {
|
|
55
|
+
// @ts-ignore - bun:ffi is only available in Bun
|
|
56
|
+
const { dlopen, FFIType } = await import('bun:ffi');
|
|
57
|
+
|
|
58
|
+
const { symbols } = dlopen('user32.dll', {
|
|
59
|
+
EnumWindows: {
|
|
60
|
+
args: [FFIType.ptr, FFIType.u64],
|
|
61
|
+
returns: FFIType.bool,
|
|
62
|
+
},
|
|
63
|
+
GetWindowTextW: {
|
|
64
|
+
args: [FFIType.ptr, FFIType.ptr, FFIType.i32],
|
|
65
|
+
returns: FFIType.i32,
|
|
66
|
+
},
|
|
67
|
+
GetWindowRect: {
|
|
68
|
+
args: [FFIType.ptr, FFIType.ptr],
|
|
69
|
+
returns: FFIType.bool,
|
|
70
|
+
},
|
|
71
|
+
MoveWindow: {
|
|
72
|
+
args: [FFIType.ptr, FFIType.i32, FFIType.i32, FFIType.i32, FFIType.i32, FFIType.bool],
|
|
73
|
+
returns: FFIType.bool,
|
|
74
|
+
},
|
|
75
|
+
SetForegroundWindow: {
|
|
76
|
+
args: [FFIType.ptr],
|
|
77
|
+
returns: FFIType.bool,
|
|
78
|
+
},
|
|
79
|
+
ShowWindow: {
|
|
80
|
+
args: [FFIType.ptr, FFIType.i32],
|
|
81
|
+
returns: FFIType.bool,
|
|
82
|
+
},
|
|
83
|
+
IsZoomed: {
|
|
84
|
+
args: [FFIType.ptr],
|
|
85
|
+
returns: FFIType.bool,
|
|
86
|
+
},
|
|
87
|
+
IsIconic: {
|
|
88
|
+
args: [FFIType.ptr],
|
|
89
|
+
returns: FFIType.bool,
|
|
90
|
+
},
|
|
91
|
+
GetWindowPlacement: {
|
|
92
|
+
args: [FFIType.ptr, FFIType.ptr],
|
|
93
|
+
returns: FFIType.bool,
|
|
94
|
+
},
|
|
95
|
+
EnumDisplayMonitors: {
|
|
96
|
+
args: [FFIType.ptr, FFIType.ptr, FFIType.ptr, FFIType.u64],
|
|
97
|
+
returns: FFIType.bool,
|
|
98
|
+
},
|
|
99
|
+
GetMonitorInfoW: {
|
|
100
|
+
args: [FFIType.ptr, FFIType.ptr],
|
|
101
|
+
returns: FFIType.bool,
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
return symbols as any;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// Node.js with koffi (following sqlunified pattern)
|
|
109
|
+
const koffi = (await import('koffi')).default;
|
|
110
|
+
const lib = koffi.load('user32.dll');
|
|
111
|
+
|
|
112
|
+
// Define callback type for EnumWindows
|
|
113
|
+
const EnumWindowsProc = koffi.proto('bool __stdcall EnumWindowsProc(void *hwnd, void *lParam)');
|
|
114
|
+
|
|
115
|
+
// Define RECT structure
|
|
116
|
+
const RECT_Struct = koffi.struct('RECT', {
|
|
117
|
+
Left: 'int',
|
|
118
|
+
Top: 'int',
|
|
119
|
+
Right: 'int',
|
|
120
|
+
Bottom: 'int',
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
// Define all user32 functions
|
|
124
|
+
const EnumWindows = lib.func('bool __stdcall EnumWindows(EnumWindowsProc *enumProc, void *lParam)');
|
|
125
|
+
const GetWindowTextW = lib.func('int __stdcall GetWindowTextW(void *hWnd, uint16_t *lpString, int nMaxCount)');
|
|
126
|
+
const GetWindowRect = lib.func('bool __stdcall GetWindowRect(void *hWnd, RECT *lpRect)');
|
|
127
|
+
const MoveWindow = lib.func('bool __stdcall MoveWindow(void *hWnd, int X, int Y, int nWidth, int nHeight, bool bRepaint)');
|
|
128
|
+
const SetForegroundWindow = lib.func('bool __stdcall SetForegroundWindow(void *hWnd)');
|
|
129
|
+
const ShowWindow = lib.func('bool __stdcall ShowWindow(void *hWnd, int nCmdShow)');
|
|
130
|
+
const IsZoomed = lib.func('bool __stdcall IsZoomed(void *hWnd)');
|
|
131
|
+
const IsIconic = lib.func('bool __stdcall IsIconic(void *hWnd)');
|
|
132
|
+
const GetWindowPlacement = lib.func('bool __stdcall GetWindowPlacement(void *hWnd, void *lpwndpl)');
|
|
133
|
+
|
|
134
|
+
// Monitor enumeration functions
|
|
135
|
+
const MonitorEnumProc = koffi.proto('bool __stdcall MonitorEnumProc(void *hMonitor, void *hdcMonitor, RECT *lprcMonitor, void *dwData)');
|
|
136
|
+
const EnumDisplayMonitors = lib.func('bool __stdcall EnumDisplayMonitors(void *hdc, RECT *lprcClip, MonitorEnumProc *lpfnEnum, void *dwData)');
|
|
137
|
+
const GetMonitorInfoW = lib.func('bool __stdcall GetMonitorInfoW(void *hMonitor, void *lpmi)');
|
|
138
|
+
|
|
139
|
+
// Keep references to registered callbacks while native calls are in progress
|
|
140
|
+
let __enumWindowsCbRef: any = null;
|
|
141
|
+
let __enumDisplayMonitorsCbRef: any = null;
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
EnumWindows: (callback: (hwnd: bigint, lParam: bigint) => boolean, lParam: bigint) => {
|
|
145
|
+
__enumWindowsCbRef = koffi.register(callback, koffi.pointer(EnumWindowsProc));
|
|
146
|
+
try {
|
|
147
|
+
return EnumWindows(__enumWindowsCbRef, lParam as any);
|
|
148
|
+
} finally {
|
|
149
|
+
// release reference so GC can collect after native call finishes
|
|
150
|
+
__enumWindowsCbRef = null;
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
GetWindowTextW,
|
|
154
|
+
GetWindowRect: (hwnd: bigint, rect: any) => {
|
|
155
|
+
// Use Buffer for RECT structure (4 ints = 16 bytes)
|
|
156
|
+
const rectBuf = Buffer.alloc(16);
|
|
157
|
+
const result = GetWindowRect(hwnd as any, rectBuf);
|
|
158
|
+
if (result) {
|
|
159
|
+
rect.Left = rectBuf.readInt32LE(0);
|
|
160
|
+
rect.Top = rectBuf.readInt32LE(4);
|
|
161
|
+
rect.Right = rectBuf.readInt32LE(8);
|
|
162
|
+
rect.Bottom = rectBuf.readInt32LE(12);
|
|
163
|
+
}
|
|
164
|
+
return result;
|
|
165
|
+
},
|
|
166
|
+
MoveWindow,
|
|
167
|
+
SetForegroundWindow,
|
|
168
|
+
ShowWindow,
|
|
169
|
+
IsZoomed,
|
|
170
|
+
IsIconic,
|
|
171
|
+
GetWindowPlacement,
|
|
172
|
+
EnumDisplayMonitors: (callback: (hMonitor: bigint, hdcMonitor: bigint, lprcMonitor: any, dwData: bigint) => boolean, dwData: bigint) => {
|
|
173
|
+
__enumDisplayMonitorsCbRef = koffi.register(callback, koffi.pointer(MonitorEnumProc));
|
|
174
|
+
try {
|
|
175
|
+
return EnumDisplayMonitors(null, null, __enumDisplayMonitorsCbRef, null);
|
|
176
|
+
} finally {
|
|
177
|
+
__enumDisplayMonitorsCbRef = null;
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
GetMonitorInfoW: (hMonitor: bigint, lpmi: any) => {
|
|
181
|
+
// MONITORINFO structure:
|
|
182
|
+
// DWORD cbSize (4 bytes)
|
|
183
|
+
// RECT rcMonitor (16 bytes)
|
|
184
|
+
// RECT rcWork (16 bytes)
|
|
185
|
+
// DWORD dwFlags (4 bytes)
|
|
186
|
+
// Total: 40 bytes
|
|
187
|
+
const buffer = Buffer.alloc(40);
|
|
188
|
+
buffer.writeUInt32LE(40, 0); // cbSize
|
|
189
|
+
const result = GetMonitorInfoW(hMonitor as any, buffer);
|
|
190
|
+
if (result) {
|
|
191
|
+
lpmi.cbSize = buffer.readUInt32LE(0);
|
|
192
|
+
lpmi.rcMonitor = {
|
|
193
|
+
Left: buffer.readInt32LE(4),
|
|
194
|
+
Top: buffer.readInt32LE(8),
|
|
195
|
+
Right: buffer.readInt32LE(12),
|
|
196
|
+
Bottom: buffer.readInt32LE(16),
|
|
197
|
+
};
|
|
198
|
+
lpmi.rcWork = {
|
|
199
|
+
Left: buffer.readInt32LE(20),
|
|
200
|
+
Top: buffer.readInt32LE(24),
|
|
201
|
+
Right: buffer.readInt32LE(28),
|
|
202
|
+
Bottom: buffer.readInt32LE(32),
|
|
203
|
+
};
|
|
204
|
+
lpmi.dwFlags = buffer.readUInt32LE(36);
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
const user32 = await initializeFFI();
|
|
212
|
+
|
|
213
|
+
export { user32, isBun };
|
package/ignores.txt
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
.NET*
|
|
2
|
+
Acro*
|
|
3
|
+
AutoCompleteProxy
|
|
4
|
+
Backblaze*
|
|
5
|
+
Battery Watcher
|
|
6
|
+
Battery Meter
|
|
7
|
+
Brother Status Monitor
|
|
8
|
+
bzbuitray
|
|
9
|
+
Diskhealth
|
|
10
|
+
C:\*
|
|
11
|
+
CFD*
|
|
12
|
+
Cicero*
|
|
13
|
+
Copilot*
|
|
14
|
+
Core Sync
|
|
15
|
+
DDE Server Window
|
|
16
|
+
Default IME
|
|
17
|
+
DesktopWindowXamlSource
|
|
18
|
+
Dialog
|
|
19
|
+
Dropbox*
|
|
20
|
+
DWM*
|
|
21
|
+
DYMO QuickPrint Utility
|
|
22
|
+
Epson Event Manager Background
|
|
23
|
+
EXPLORER
|
|
24
|
+
Font Capture
|
|
25
|
+
GDI+*
|
|
26
|
+
Google Drive*
|
|
27
|
+
Hardware*
|
|
28
|
+
Hidden Window
|
|
29
|
+
LangSel
|
|
30
|
+
MediaContextNotificationWindow
|
|
31
|
+
MediaPlayer*
|
|
32
|
+
Microsoft Edge*
|
|
33
|
+
Microsoft Store
|
|
34
|
+
Microsoft Store*
|
|
35
|
+
Microsoft Text Input Application
|
|
36
|
+
Microsoft Text Input Application*
|
|
37
|
+
Microsoft*
|
|
38
|
+
Minimize the Folder Pane
|
|
39
|
+
MSCTFIME UI
|
|
40
|
+
Notifications
|
|
41
|
+
OfficePower*
|
|
42
|
+
OfficePowerManagementSystem
|
|
43
|
+
OneDRive*
|
|
44
|
+
PDFM*
|
|
45
|
+
PopupHost
|
|
46
|
+
Power Automate
|
|
47
|
+
PowerToys*
|
|
48
|
+
Program Manager
|
|
49
|
+
Properties
|
|
50
|
+
PToyTrayIconWindow
|
|
51
|
+
REALTEK USB Wireless LAN Utility
|
|
52
|
+
SecurityHealthSysTray
|
|
53
|
+
Settings
|
|
54
|
+
Shell Handwriting Canvas
|
|
55
|
+
SSMS*
|
|
56
|
+
Start
|
|
57
|
+
Status Monitor
|
|
58
|
+
Switch USB
|
|
59
|
+
System Tray
|
|
60
|
+
SystemResourceNotifyWindow
|
|
61
|
+
Task Host Window
|
|
62
|
+
Task Switching
|
|
63
|
+
Taskbar
|
|
64
|
+
ThorConnWndClass
|
|
65
|
+
TNOTIF*
|
|
66
|
+
Tray Assistant
|
|
67
|
+
ViewDeferd*
|
|
68
|
+
W
|
|
69
|
+
Widgets
|
|
70
|
+
Windows*
|
|
71
|
+
WinUI*
|
|
72
|
+
WISPTIS
|
|
73
|
+
WMS*
|
|
74
|
+
Word
|
|
75
|
+
Insta360*
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* tswinpos - TypeScript Windows Positioning Utility
|
|
4
|
+
* Cross-platform Node.js/Bun implementation with FFI
|
|
5
|
+
*/
|
|
6
|
+
import { user32, RECT } from './ffi-wrapper.js';
|
|
7
|
+
import { enumerateScreens, sortScreens, ScreenInfo } from './screens.js';
|
|
8
|
+
import { enumerateWindows, findWindowsByPattern, WindowInfo, WindowState, getWindowState, setWindowState, isMinimized, isMaximized, isNormal, minimizeWindow, maximizeWindow, restoreWindow } from './windows.js';
|
|
9
|
+
import { enumerateTabs, TabInfo, mightHaveTabs, TAB_ENUMERATION_NOTE } from './tabs.js';
|
|
10
|
+
export { RECT, ScreenInfo, WindowInfo, WindowState, TabInfo, enumerateScreens, sortScreens, enumerateWindows, findWindowsByPattern, getWindowState, setWindowState, isMinimized, isMaximized, isNormal, minimizeWindow, maximizeWindow, restoreWindow, enumerateTabs, mightHaveTabs, TAB_ENUMERATION_NOTE, user32 };
|
|
11
|
+
export declare function run(args: string[]): void;
|
|
12
|
+
//# sourceMappingURL=index.d.ts.map
|
package/index.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":";AACA;;;GAGG;AAEH,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACzE,OAAO,EACH,gBAAgB,EAChB,oBAAoB,EAEpB,UAAU,EACV,WAAW,EACX,cAAc,EACd,cAAc,EACd,WAAW,EACX,WAAW,EACX,QAAQ,EACR,cAAc,EACd,cAAc,EACd,aAAa,EAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,aAAa,EAAE,OAAO,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AAKxF,OAAO,EACH,IAAI,EACJ,UAAU,EACV,UAAU,EACV,WAAW,EACX,OAAO,EACP,gBAAgB,EAChB,WAAW,EACX,gBAAgB,EAChB,oBAAoB,EACpB,cAAc,EACd,cAAc,EACd,WAAW,EACX,WAAW,EACX,QAAQ,EACR,cAAc,EACd,cAAc,EACd,aAAa,EACb,aAAa,EACb,aAAa,EACb,oBAAoB,EACpB,MAAM,EACT,CAAC;AA0KF,wBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,QAoEjC"}
|
package/index.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* tswinpos - TypeScript Windows Positioning Utility
|
|
4
|
+
* Cross-platform Node.js/Bun implementation with FFI
|
|
5
|
+
*/
|
|
6
|
+
import { user32 } from './ffi-wrapper.js';
|
|
7
|
+
import { enumerateScreens, sortScreens } from './screens.js';
|
|
8
|
+
import { enumerateWindows, findWindowsByPattern, loadIgnorePatterns, WindowState, getWindowState, setWindowState, isMinimized, isMaximized, isNormal, minimizeWindow, maximizeWindow, restoreWindow } from './windows.js';
|
|
9
|
+
import { enumerateTabs, mightHaveTabs, TAB_ENUMERATION_NOTE } from './tabs.js';
|
|
10
|
+
import { join } from 'path';
|
|
11
|
+
import * as packageJson from './package.json' with { type: 'json' };
|
|
12
|
+
// Re-export public API for library usage
|
|
13
|
+
export { WindowState, enumerateScreens, sortScreens, enumerateWindows, findWindowsByPattern, getWindowState, setWindowState, isMinimized, isMaximized, isNormal, minimizeWindow, maximizeWindow, restoreWindow, enumerateTabs, mightHaveTabs, TAB_ENUMERATION_NOTE, user32 };
|
|
14
|
+
let dbg = false;
|
|
15
|
+
let screens = [];
|
|
16
|
+
function parseDimension(input, fullDimension) {
|
|
17
|
+
if (input.endsWith('%')) {
|
|
18
|
+
const percentage = parseFloat(input.slice(0, -1)) / 100.0;
|
|
19
|
+
return Math.floor(fullDimension * percentage);
|
|
20
|
+
}
|
|
21
|
+
const val = parseInt(input, 10);
|
|
22
|
+
return val < 0 ? fullDimension + val : val;
|
|
23
|
+
}
|
|
24
|
+
function adjustWindow(args) {
|
|
25
|
+
const windowTitle = args[0];
|
|
26
|
+
// Check if user wants to minimize the window (min or -min in position)
|
|
27
|
+
const shouldMinimize = args[1].toLowerCase() === 'min' || args[1].toLowerCase() === '-min';
|
|
28
|
+
if (shouldMinimize) {
|
|
29
|
+
if (dbg)
|
|
30
|
+
console.log(`Minimizing window '${windowTitle}'`);
|
|
31
|
+
let matchedWindows = findWindowsByPattern(windowTitle);
|
|
32
|
+
// Filter out command windows running tswinpos
|
|
33
|
+
matchedWindows = matchedWindows.filter(w => !w.title.toLowerCase().includes('tswinpos'));
|
|
34
|
+
for (const window of matchedWindows) {
|
|
35
|
+
if (dbg)
|
|
36
|
+
console.log(`Minimizing window '${window.title}'`);
|
|
37
|
+
minimizeWindow(window.hwnd);
|
|
38
|
+
}
|
|
39
|
+
if (matchedWindows.length === 0)
|
|
40
|
+
console.log(`No windows found matching '${windowTitle}'.`);
|
|
41
|
+
return;
|
|
42
|
+
}
|
|
43
|
+
const screenIndex = parseInt(args[3], 10);
|
|
44
|
+
if (screenIndex < 0 || screenIndex >= screens.length) {
|
|
45
|
+
usage(`Invalid screen number: ${screenIndex}. Must be between 0 and ${screens.length - 1}`);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
const targetScreen = screens[screenIndex];
|
|
49
|
+
const bounds = targetScreen.bounds;
|
|
50
|
+
const x = parseDimension(args[1], bounds.Width) + bounds.Left;
|
|
51
|
+
const y = parseDimension(args[2], bounds.Height) + bounds.Top;
|
|
52
|
+
let width = args.length > 4 ? parseDimension(args[4], bounds.Width) : 0;
|
|
53
|
+
let height = args.length > 5 ? parseDimension(args[5], bounds.Height) : 0;
|
|
54
|
+
if (dbg)
|
|
55
|
+
console.log(`Trying window '${windowTitle}'`);
|
|
56
|
+
let matchedWindows = findWindowsByPattern(windowTitle);
|
|
57
|
+
// Filter out command windows running tswinpos
|
|
58
|
+
matchedWindows = matchedWindows.filter(w => !w.title.toLowerCase().includes('tswinpos'));
|
|
59
|
+
for (const window of matchedWindows) {
|
|
60
|
+
if (dbg)
|
|
61
|
+
console.log(`Moving window '${window.title}' to (${x}, ${y}) on screen ${screenIndex}.`);
|
|
62
|
+
if (width === 0)
|
|
63
|
+
width = window.rect.Right - window.rect.Left;
|
|
64
|
+
if (height === 0)
|
|
65
|
+
height = window.rect.Bottom - window.rect.Top;
|
|
66
|
+
// Restore window if minimized or maximized to ensure it moves to the correct position
|
|
67
|
+
if (isMinimized(window.hwnd) || isMaximized(window.hwnd)) {
|
|
68
|
+
restoreWindow(window.hwnd);
|
|
69
|
+
}
|
|
70
|
+
user32.MoveWindow(window.hwnd, x, y, width, height, true);
|
|
71
|
+
user32.SetForegroundWindow(window.hwnd);
|
|
72
|
+
}
|
|
73
|
+
if (matchedWindows.length === 0)
|
|
74
|
+
console.log(`No windows found matching '${windowTitle}'.`);
|
|
75
|
+
}
|
|
76
|
+
function getScreenForWindow(windowRect) {
|
|
77
|
+
// Find which screen contains the center of the window
|
|
78
|
+
const centerX = (windowRect.Left + windowRect.Right) / 2;
|
|
79
|
+
const centerY = (windowRect.Top + windowRect.Bottom) / 2;
|
|
80
|
+
for (let i = 0; i < screens.length; i++) {
|
|
81
|
+
const screen = screens[i];
|
|
82
|
+
if (centerX >= screen.bounds.Left && centerX < screen.bounds.Right &&
|
|
83
|
+
centerY >= screen.bounds.Top && centerY < screen.bounds.Bottom) {
|
|
84
|
+
return i;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
// If not found, return the primary screen (or first screen)
|
|
88
|
+
return screens.findIndex(s => s.primary) || 0;
|
|
89
|
+
}
|
|
90
|
+
function listAllWindows(includeIgnored = false) {
|
|
91
|
+
console.log('====================================');
|
|
92
|
+
console.log('Screens');
|
|
93
|
+
for (let i = 0; i < screens.length; i++) {
|
|
94
|
+
const screen = screens[i];
|
|
95
|
+
console.log(`${i} Screen: ${screen.deviceName} (${screen.bounds.Top}/${screen.bounds.Bottom}x${screen.bounds.Left}/${screen.bounds.Right})`);
|
|
96
|
+
}
|
|
97
|
+
console.log();
|
|
98
|
+
const windows = enumerateWindows(includeIgnored).sort((a, b) => a.title.localeCompare(b.title));
|
|
99
|
+
console.log('Title X Y Scr Width Height');
|
|
100
|
+
console.log('-----------------------------------------------------------------------------------');
|
|
101
|
+
for (const window of windows) {
|
|
102
|
+
const screenIndex = getScreenForWindow(window.rect);
|
|
103
|
+
const screen = screens[screenIndex];
|
|
104
|
+
// Normalize coordinates relative to the screen
|
|
105
|
+
const x = window.rect.Left - screen.bounds.Left;
|
|
106
|
+
const y = window.rect.Top - screen.bounds.Top;
|
|
107
|
+
const width = window.rect.Right - window.rect.Left;
|
|
108
|
+
const height = window.rect.Bottom - window.rect.Top;
|
|
109
|
+
// Truncate title if too long
|
|
110
|
+
const title = window.title.length > 45 ? window.title.substring(0, 42) + '...' : window.title;
|
|
111
|
+
console.log(`${title.padEnd(45)} ${x.toString().padStart(6)} ${y.toString().padStart(6)} ${screenIndex.toString().padStart(5)} ${width.toString().padStart(7)} ${height.toString().padStart(7)}`);
|
|
112
|
+
}
|
|
113
|
+
console.log();
|
|
114
|
+
console.log('Command format: tswinpos <title> <x> <y> <screen> [<width> <height>]');
|
|
115
|
+
}
|
|
116
|
+
function usage(msg = '') {
|
|
117
|
+
if (msg)
|
|
118
|
+
console.log(msg);
|
|
119
|
+
console.log('Usage: tswinpos [-d -c -version *] <window title> <x> <y> <screen> [<width> <height>]');
|
|
120
|
+
console.log(' tswinpos <window title> min | -min');
|
|
121
|
+
console.log(' -d debug, -c return count, -version (or -v) show version');
|
|
122
|
+
console.log(' where <screen> is a number from 0 to N-1, where N is the number of screens.');
|
|
123
|
+
console.log(' <x> and <y> can be a number of pixels or a percentage (e.g. 50%)');
|
|
124
|
+
console.log(' Use "min" or "-min" in place of <x> to minimize the window to the taskbar');
|
|
125
|
+
console.log(' title can be a regex pattern (if enclosed in /.../) or a prefix (if it ends with \'*\')');
|
|
126
|
+
console.log(' <width> and <height> are optional and can be a number of pixels or a percentage (e.g. 50%) or 0 (to keep the current size)');
|
|
127
|
+
console.log('To list all windows: tswinpos *');
|
|
128
|
+
console.log('To list all windows (including ignored): tswinpos **');
|
|
129
|
+
console.log('To return the window count use -c');
|
|
130
|
+
console.log();
|
|
131
|
+
console.log(' +---+---+');
|
|
132
|
+
console.log(' | 2 | 3 |');
|
|
133
|
+
console.log(' +---+---+');
|
|
134
|
+
console.log(' | 0 | 1 |');
|
|
135
|
+
console.log(' +---+---+');
|
|
136
|
+
console.log();
|
|
137
|
+
console.log('Screen | X Y | W H ');
|
|
138
|
+
console.log('------------------------------------');
|
|
139
|
+
for (let i = 0; i < screens.length; i++) {
|
|
140
|
+
const screen = screens[i];
|
|
141
|
+
console.log(`${i.toString().padStart(6)} | ${screen.bounds.Left.toString().padStart(5)} ${screen.bounds.Top.toString().padStart(5)} | ${screen.bounds.Width.toString().padStart(5)} ${screen.bounds.Height.toString().padStart(5)}`);
|
|
142
|
+
}
|
|
143
|
+
console.log();
|
|
144
|
+
console.log('0-Lower right, 1-Lower Left, 2-Upper left, 3-Upper right');
|
|
145
|
+
process.exit(1);
|
|
146
|
+
}
|
|
147
|
+
export function run(args) {
|
|
148
|
+
// Initialize screens
|
|
149
|
+
try {
|
|
150
|
+
screens = sortScreens(enumerateScreens());
|
|
151
|
+
}
|
|
152
|
+
catch (e) {
|
|
153
|
+
if (e.message && e.message.includes('Bun')) {
|
|
154
|
+
console.error(e.message);
|
|
155
|
+
process.exit(1);
|
|
156
|
+
}
|
|
157
|
+
throw e; // Re-throw if it's a different error
|
|
158
|
+
}
|
|
159
|
+
// Load ignore patterns from the same directory as the script
|
|
160
|
+
const ignoresPath = join(import.meta.dirname, 'ignores.txt');
|
|
161
|
+
loadIgnorePatterns(ignoresPath);
|
|
162
|
+
// Parse options
|
|
163
|
+
while (args.length > 0 && args[0].startsWith('-')) {
|
|
164
|
+
const opt = args[0].substring(1);
|
|
165
|
+
switch (opt) {
|
|
166
|
+
case 'd':
|
|
167
|
+
dbg = true;
|
|
168
|
+
console.log('Debug mode enabled.');
|
|
169
|
+
break;
|
|
170
|
+
case 'c':
|
|
171
|
+
console.log(screens.length);
|
|
172
|
+
process.exit(screens.length);
|
|
173
|
+
break;
|
|
174
|
+
case 'version':
|
|
175
|
+
case 'v':
|
|
176
|
+
console.log(`tswinpos version ${packageJson.default.version}`);
|
|
177
|
+
process.exit(0);
|
|
178
|
+
break;
|
|
179
|
+
default:
|
|
180
|
+
usage(`Unknown option: ${args[0]}`);
|
|
181
|
+
break;
|
|
182
|
+
}
|
|
183
|
+
args = args.slice(1);
|
|
184
|
+
}
|
|
185
|
+
// Handle commands
|
|
186
|
+
// console.log(DEBUG: args.length=', args.length, 'args[0]=', args[0], 'check=', args.length === 1 && args[0] === '*');
|
|
187
|
+
if (dbg)
|
|
188
|
+
console.log(`DEBUG[${packageJson.default.version}]: ${args.join(' ')}`);
|
|
189
|
+
if (args.length === 1 && args[0] === '*') {
|
|
190
|
+
listAllWindows();
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
if (args.length === 1 && args[0] === '**') {
|
|
194
|
+
listAllWindows(true);
|
|
195
|
+
return;
|
|
196
|
+
}
|
|
197
|
+
// Check for minimize command (title + min/-min)
|
|
198
|
+
// TODO: Refactor to eliminate duplicate min/minimize check - consolidate with adjustWindow logic
|
|
199
|
+
if (args.length === 2 && (args[1].toLowerCase() === 'min' || args[1].toLowerCase() === '-min')) {
|
|
200
|
+
adjustWindow(args);
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
if (args.length < 4) {
|
|
204
|
+
usage();
|
|
205
|
+
return;
|
|
206
|
+
}
|
|
207
|
+
adjustWindow(args);
|
|
208
|
+
}
|
|
209
|
+
// CLI entry point using import.meta.main
|
|
210
|
+
if (import.meta.main) {
|
|
211
|
+
run(process.argv.slice(2));
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=index.js.map
|
package/index.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["index.ts"],"names":[],"mappings":"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"}
|