@jacques-ai/server 0.0.7-alpha.1
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/dist/config/config.d.ts +34 -0
- package/dist/config/config.d.ts.map +1 -0
- package/dist/config/config.js +32 -0
- package/dist/config/config.js.map +1 -0
- package/dist/connection/applescript.d.ts +46 -0
- package/dist/connection/applescript.d.ts.map +1 -0
- package/dist/connection/applescript.js +62 -0
- package/dist/connection/applescript.js.map +1 -0
- package/dist/connection/applescript.test.d.ts +5 -0
- package/dist/connection/applescript.test.d.ts.map +1 -0
- package/dist/connection/applescript.test.js +64 -0
- package/dist/connection/applescript.test.js.map +1 -0
- package/dist/connection/constants.d.ts +88 -0
- package/dist/connection/constants.d.ts.map +1 -0
- package/dist/connection/constants.js +110 -0
- package/dist/connection/constants.js.map +1 -0
- package/dist/connection/git-info.d.ts +30 -0
- package/dist/connection/git-info.d.ts.map +1 -0
- package/dist/connection/git-info.js +52 -0
- package/dist/connection/git-info.js.map +1 -0
- package/dist/connection/git-info.test.d.ts +5 -0
- package/dist/connection/git-info.test.d.ts.map +1 -0
- package/dist/connection/git-info.test.js +35 -0
- package/dist/connection/git-info.test.js.map +1 -0
- package/dist/connection/index.d.ts +19 -0
- package/dist/connection/index.d.ts.map +1 -0
- package/dist/connection/index.js +36 -0
- package/dist/connection/index.js.map +1 -0
- package/dist/connection/process-detection.d.ts +58 -0
- package/dist/connection/process-detection.d.ts.map +1 -0
- package/dist/connection/process-detection.js +239 -0
- package/dist/connection/process-detection.js.map +1 -0
- package/dist/connection/process-detection.test.d.ts +5 -0
- package/dist/connection/process-detection.test.d.ts.map +1 -0
- package/dist/connection/process-detection.test.js +43 -0
- package/dist/connection/process-detection.test.js.map +1 -0
- package/dist/connection/session-discovery.d.ts +55 -0
- package/dist/connection/session-discovery.d.ts.map +1 -0
- package/dist/connection/session-discovery.js +311 -0
- package/dist/connection/session-discovery.js.map +1 -0
- package/dist/connection/terminal-key.d.ts +126 -0
- package/dist/connection/terminal-key.d.ts.map +1 -0
- package/dist/connection/terminal-key.js +271 -0
- package/dist/connection/terminal-key.js.map +1 -0
- package/dist/connection/terminal-key.test.d.ts +5 -0
- package/dist/connection/terminal-key.test.d.ts.map +1 -0
- package/dist/connection/terminal-key.test.js +221 -0
- package/dist/connection/terminal-key.test.js.map +1 -0
- package/dist/connection/worktree.d.ts +114 -0
- package/dist/connection/worktree.d.ts.map +1 -0
- package/dist/connection/worktree.js +320 -0
- package/dist/connection/worktree.js.map +1 -0
- package/dist/connection/worktree.test.d.ts +5 -0
- package/dist/connection/worktree.test.d.ts.map +1 -0
- package/dist/connection/worktree.test.js +113 -0
- package/dist/connection/worktree.test.js.map +1 -0
- package/dist/focus-watcher.d.ts +51 -0
- package/dist/focus-watcher.d.ts.map +1 -0
- package/dist/focus-watcher.js +169 -0
- package/dist/focus-watcher.js.map +1 -0
- package/dist/handlers/event-handler.d.ts +93 -0
- package/dist/handlers/event-handler.d.ts.map +1 -0
- package/dist/handlers/event-handler.js +196 -0
- package/dist/handlers/event-handler.js.map +1 -0
- package/dist/handlers/event-handler.test.d.ts +5 -0
- package/dist/handlers/event-handler.test.d.ts.map +1 -0
- package/dist/handlers/event-handler.test.js +305 -0
- package/dist/handlers/event-handler.test.js.map +1 -0
- package/dist/handlers/session-handler.d.ts +23 -0
- package/dist/handlers/session-handler.d.ts.map +1 -0
- package/dist/handlers/session-handler.js +104 -0
- package/dist/handlers/session-handler.js.map +1 -0
- package/dist/handlers/session-handler.test.d.ts +5 -0
- package/dist/handlers/session-handler.test.d.ts.map +1 -0
- package/dist/handlers/session-handler.test.js +89 -0
- package/dist/handlers/session-handler.test.js.map +1 -0
- package/dist/handlers/settings-handler.d.ts +32 -0
- package/dist/handlers/settings-handler.d.ts.map +1 -0
- package/dist/handlers/settings-handler.js +127 -0
- package/dist/handlers/settings-handler.js.map +1 -0
- package/dist/handlers/settings-handler.test.d.ts +5 -0
- package/dist/handlers/settings-handler.test.d.ts.map +1 -0
- package/dist/handlers/settings-handler.test.js +105 -0
- package/dist/handlers/settings-handler.test.js.map +1 -0
- package/dist/handlers/window-handler.d.ts +30 -0
- package/dist/handlers/window-handler.d.ts.map +1 -0
- package/dist/handlers/window-handler.js +486 -0
- package/dist/handlers/window-handler.js.map +1 -0
- package/dist/handlers/window-handler.test.d.ts +8 -0
- package/dist/handlers/window-handler.test.d.ts.map +1 -0
- package/dist/handlers/window-handler.test.js +167 -0
- package/dist/handlers/window-handler.test.js.map +1 -0
- package/dist/handlers/worktree-handler.d.ts +28 -0
- package/dist/handlers/worktree-handler.d.ts.map +1 -0
- package/dist/handlers/worktree-handler.js +268 -0
- package/dist/handlers/worktree-handler.js.map +1 -0
- package/dist/handlers/worktree-handler.test.d.ts +8 -0
- package/dist/handlers/worktree-handler.test.d.ts.map +1 -0
- package/dist/handlers/worktree-handler.test.js +118 -0
- package/dist/handlers/worktree-handler.test.js.map +1 -0
- package/dist/handlers/ws-utils.d.ts +12 -0
- package/dist/handlers/ws-utils.d.ts.map +1 -0
- package/dist/handlers/ws-utils.js +16 -0
- package/dist/handlers/ws-utils.js.map +1 -0
- package/dist/http-api.d.ts +26 -0
- package/dist/http-api.d.ts.map +1 -0
- package/dist/http-api.js +148 -0
- package/dist/http-api.js.map +1 -0
- package/dist/logger.d.ts +42 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +147 -0
- package/dist/logger.js.map +1 -0
- package/dist/logging/logger-factory.d.ts +51 -0
- package/dist/logging/logger-factory.d.ts.map +1 -0
- package/dist/logging/logger-factory.js +59 -0
- package/dist/logging/logger-factory.js.map +1 -0
- package/dist/mcp/search-tool.d.ts +65 -0
- package/dist/mcp/search-tool.d.ts.map +1 -0
- package/dist/mcp/search-tool.js +176 -0
- package/dist/mcp/search-tool.js.map +1 -0
- package/dist/mcp/server.d.ts +9 -0
- package/dist/mcp/server.d.ts.map +1 -0
- package/dist/mcp/server.js +152 -0
- package/dist/mcp/server.js.map +1 -0
- package/dist/process-scanner.d.ts +96 -0
- package/dist/process-scanner.d.ts.map +1 -0
- package/dist/process-scanner.js +194 -0
- package/dist/process-scanner.js.map +1 -0
- package/dist/routes/__tests__/archive-routes.test.d.ts +5 -0
- package/dist/routes/__tests__/archive-routes.test.d.ts.map +1 -0
- package/dist/routes/__tests__/archive-routes.test.js +158 -0
- package/dist/routes/__tests__/archive-routes.test.js.map +1 -0
- package/dist/routes/__tests__/config-routes.test.d.ts +5 -0
- package/dist/routes/__tests__/config-routes.test.d.ts.map +1 -0
- package/dist/routes/__tests__/config-routes.test.js +112 -0
- package/dist/routes/__tests__/config-routes.test.js.map +1 -0
- package/dist/routes/__tests__/http-utils.test.d.ts +5 -0
- package/dist/routes/__tests__/http-utils.test.d.ts.map +1 -0
- package/dist/routes/__tests__/http-utils.test.js +102 -0
- package/dist/routes/__tests__/http-utils.test.js.map +1 -0
- package/dist/routes/__tests__/notification-routes.test.d.ts +5 -0
- package/dist/routes/__tests__/notification-routes.test.d.ts.map +1 -0
- package/dist/routes/__tests__/notification-routes.test.js +91 -0
- package/dist/routes/__tests__/notification-routes.test.js.map +1 -0
- package/dist/routes/__tests__/project-routes.test.d.ts +5 -0
- package/dist/routes/__tests__/project-routes.test.d.ts.map +1 -0
- package/dist/routes/__tests__/project-routes.test.js +168 -0
- package/dist/routes/__tests__/project-routes.test.js.map +1 -0
- package/dist/routes/__tests__/session-routes.test.d.ts +5 -0
- package/dist/routes/__tests__/session-routes.test.d.ts.map +1 -0
- package/dist/routes/__tests__/session-routes.test.js +198 -0
- package/dist/routes/__tests__/session-routes.test.js.map +1 -0
- package/dist/routes/__tests__/source-routes.test.d.ts +5 -0
- package/dist/routes/__tests__/source-routes.test.d.ts.map +1 -0
- package/dist/routes/__tests__/source-routes.test.js +142 -0
- package/dist/routes/__tests__/source-routes.test.js.map +1 -0
- package/dist/routes/__tests__/sync-routes.test.d.ts +5 -0
- package/dist/routes/__tests__/sync-routes.test.d.ts.map +1 -0
- package/dist/routes/__tests__/sync-routes.test.js +77 -0
- package/dist/routes/__tests__/sync-routes.test.js.map +1 -0
- package/dist/routes/__tests__/test-helpers.d.ts +47 -0
- package/dist/routes/__tests__/test-helpers.d.ts.map +1 -0
- package/dist/routes/__tests__/test-helpers.js +97 -0
- package/dist/routes/__tests__/test-helpers.js.map +1 -0
- package/dist/routes/archive-routes.d.ts +15 -0
- package/dist/routes/archive-routes.d.ts.map +1 -0
- package/dist/routes/archive-routes.js +181 -0
- package/dist/routes/archive-routes.js.map +1 -0
- package/dist/routes/claude-routes.d.ts +9 -0
- package/dist/routes/claude-routes.d.ts.map +1 -0
- package/dist/routes/claude-routes.js +47 -0
- package/dist/routes/claude-routes.js.map +1 -0
- package/dist/routes/config-routes.d.ts +9 -0
- package/dist/routes/config-routes.d.ts.map +1 -0
- package/dist/routes/config-routes.js +56 -0
- package/dist/routes/config-routes.js.map +1 -0
- package/dist/routes/config-store.d.ts +41 -0
- package/dist/routes/config-store.d.ts.map +1 -0
- package/dist/routes/config-store.js +52 -0
- package/dist/routes/config-store.js.map +1 -0
- package/dist/routes/http-utils.d.ts +32 -0
- package/dist/routes/http-utils.d.ts.map +1 -0
- package/dist/routes/http-utils.js +123 -0
- package/dist/routes/http-utils.js.map +1 -0
- package/dist/routes/index.d.ts +19 -0
- package/dist/routes/index.d.ts.map +1 -0
- package/dist/routes/index.js +17 -0
- package/dist/routes/index.js.map +1 -0
- package/dist/routes/notification-routes.d.ts +10 -0
- package/dist/routes/notification-routes.d.ts.map +1 -0
- package/dist/routes/notification-routes.js +64 -0
- package/dist/routes/notification-routes.js.map +1 -0
- package/dist/routes/project-routes.d.ts +22 -0
- package/dist/routes/project-routes.d.ts.map +1 -0
- package/dist/routes/project-routes.js +415 -0
- package/dist/routes/project-routes.js.map +1 -0
- package/dist/routes/session-routes.d.ts +18 -0
- package/dist/routes/session-routes.d.ts.map +1 -0
- package/dist/routes/session-routes.js +609 -0
- package/dist/routes/session-routes.js.map +1 -0
- package/dist/routes/source-routes.d.ts +12 -0
- package/dist/routes/source-routes.d.ts.map +1 -0
- package/dist/routes/source-routes.js +119 -0
- package/dist/routes/source-routes.js.map +1 -0
- package/dist/routes/static-routes.d.ts +12 -0
- package/dist/routes/static-routes.d.ts.map +1 -0
- package/dist/routes/static-routes.js +52 -0
- package/dist/routes/static-routes.js.map +1 -0
- package/dist/routes/sync-routes.d.ts +9 -0
- package/dist/routes/sync-routes.d.ts.map +1 -0
- package/dist/routes/sync-routes.js +78 -0
- package/dist/routes/sync-routes.js.map +1 -0
- package/dist/routes/tile-routes.d.ts +10 -0
- package/dist/routes/tile-routes.d.ts.map +1 -0
- package/dist/routes/tile-routes.js +108 -0
- package/dist/routes/tile-routes.js.map +1 -0
- package/dist/routes/types.d.ts +17 -0
- package/dist/routes/types.d.ts.map +1 -0
- package/dist/routes/types.js +5 -0
- package/dist/routes/types.js.map +1 -0
- package/dist/routes/usage-routes.d.ts +8 -0
- package/dist/routes/usage-routes.d.ts.map +1 -0
- package/dist/routes/usage-routes.js +18 -0
- package/dist/routes/usage-routes.js.map +1 -0
- package/dist/server.d.ts +8 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +173 -0
- package/dist/server.js.map +1 -0
- package/dist/services/branch-divergence-service.d.ts +48 -0
- package/dist/services/branch-divergence-service.d.ts.map +1 -0
- package/dist/services/branch-divergence-service.js +156 -0
- package/dist/services/branch-divergence-service.js.map +1 -0
- package/dist/services/broadcast-service.d.ts +68 -0
- package/dist/services/broadcast-service.d.ts.map +1 -0
- package/dist/services/broadcast-service.js +78 -0
- package/dist/services/broadcast-service.js.map +1 -0
- package/dist/services/broadcast-service.test.d.ts +5 -0
- package/dist/services/broadcast-service.test.d.ts.map +1 -0
- package/dist/services/broadcast-service.test.js +130 -0
- package/dist/services/broadcast-service.test.js.map +1 -0
- package/dist/services/chat-service.d.ts +72 -0
- package/dist/services/chat-service.d.ts.map +1 -0
- package/dist/services/chat-service.js +342 -0
- package/dist/services/chat-service.js.map +1 -0
- package/dist/services/chat-system-prompt.d.ts +14 -0
- package/dist/services/chat-system-prompt.d.ts.map +1 -0
- package/dist/services/chat-system-prompt.js +68 -0
- package/dist/services/chat-system-prompt.js.map +1 -0
- package/dist/services/notification-service.d.ts +115 -0
- package/dist/services/notification-service.d.ts.map +1 -0
- package/dist/services/notification-service.js +424 -0
- package/dist/services/notification-service.js.map +1 -0
- package/dist/services/notification-service.test.d.ts +5 -0
- package/dist/services/notification-service.test.d.ts.map +1 -0
- package/dist/services/notification-service.test.js +918 -0
- package/dist/services/notification-service.test.js.map +1 -0
- package/dist/session/cleanup-service.d.ts +51 -0
- package/dist/session/cleanup-service.d.ts.map +1 -0
- package/dist/session/cleanup-service.js +98 -0
- package/dist/session/cleanup-service.js.map +1 -0
- package/dist/session/cleanup-service.test.d.ts +5 -0
- package/dist/session/cleanup-service.test.d.ts.map +1 -0
- package/dist/session/cleanup-service.test.js +121 -0
- package/dist/session/cleanup-service.test.js.map +1 -0
- package/dist/session/process-monitor.d.ts +79 -0
- package/dist/session/process-monitor.d.ts.map +1 -0
- package/dist/session/process-monitor.js +270 -0
- package/dist/session/process-monitor.js.map +1 -0
- package/dist/session/process-monitor.test.d.ts +5 -0
- package/dist/session/process-monitor.test.d.ts.map +1 -0
- package/dist/session/process-monitor.test.js +367 -0
- package/dist/session/process-monitor.test.js.map +1 -0
- package/dist/session/session-factory.d.ts +29 -0
- package/dist/session/session-factory.d.ts.map +1 -0
- package/dist/session/session-factory.js +123 -0
- package/dist/session/session-factory.js.map +1 -0
- package/dist/session/session-factory.test.d.ts +5 -0
- package/dist/session/session-factory.test.d.ts.map +1 -0
- package/dist/session/session-factory.test.js +299 -0
- package/dist/session/session-factory.test.js.map +1 -0
- package/dist/session-registry.d.ts +168 -0
- package/dist/session-registry.d.ts.map +1 -0
- package/dist/session-registry.js +626 -0
- package/dist/session-registry.js.map +1 -0
- package/dist/session-registry.test.d.ts +5 -0
- package/dist/session-registry.test.d.ts.map +1 -0
- package/dist/session-registry.test.js +582 -0
- package/dist/session-registry.test.js.map +1 -0
- package/dist/start-server.d.ts +31 -0
- package/dist/start-server.d.ts.map +1 -0
- package/dist/start-server.js +408 -0
- package/dist/start-server.js.map +1 -0
- package/dist/terminal-activator.d.ts +29 -0
- package/dist/terminal-activator.d.ts.map +1 -0
- package/dist/terminal-activator.js +264 -0
- package/dist/terminal-activator.js.map +1 -0
- package/dist/terminal-activator.test.d.ts +9 -0
- package/dist/terminal-activator.test.d.ts.map +1 -0
- package/dist/terminal-activator.test.js +95 -0
- package/dist/terminal-activator.test.js.map +1 -0
- package/dist/terminal-launcher.d.ts +51 -0
- package/dist/terminal-launcher.d.ts.map +1 -0
- package/dist/terminal-launcher.js +298 -0
- package/dist/terminal-launcher.js.map +1 -0
- package/dist/terminal-launcher.test.d.ts +8 -0
- package/dist/terminal-launcher.test.d.ts.map +1 -0
- package/dist/terminal-launcher.test.js +222 -0
- package/dist/terminal-launcher.test.js.map +1 -0
- package/dist/types.d.ts +796 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/dist/unix-socket.d.ts +68 -0
- package/dist/unix-socket.d.ts.map +1 -0
- package/dist/unix-socket.js +180 -0
- package/dist/unix-socket.js.map +1 -0
- package/dist/usage-limits.d.ts +13 -0
- package/dist/usage-limits.d.ts.map +1 -0
- package/dist/usage-limits.js +112 -0
- package/dist/usage-limits.js.map +1 -0
- package/dist/watchers/handoff-watcher.d.ts +74 -0
- package/dist/watchers/handoff-watcher.d.ts.map +1 -0
- package/dist/watchers/handoff-watcher.js +124 -0
- package/dist/watchers/handoff-watcher.js.map +1 -0
- package/dist/watchers/handoff-watcher.test.d.ts +8 -0
- package/dist/watchers/handoff-watcher.test.d.ts.map +1 -0
- package/dist/watchers/handoff-watcher.test.js +142 -0
- package/dist/watchers/handoff-watcher.test.js.map +1 -0
- package/dist/websocket.d.ts +107 -0
- package/dist/websocket.d.ts.map +1 -0
- package/dist/websocket.js +268 -0
- package/dist/websocket.js.map +1 -0
- package/dist/window-manager/index.d.ts +28 -0
- package/dist/window-manager/index.d.ts.map +1 -0
- package/dist/window-manager/index.js +56 -0
- package/dist/window-manager/index.js.map +1 -0
- package/dist/window-manager/layouts.d.ts +42 -0
- package/dist/window-manager/layouts.d.ts.map +1 -0
- package/dist/window-manager/layouts.js +133 -0
- package/dist/window-manager/layouts.js.map +1 -0
- package/dist/window-manager/linux-manager.d.ts +45 -0
- package/dist/window-manager/linux-manager.d.ts.map +1 -0
- package/dist/window-manager/linux-manager.js +299 -0
- package/dist/window-manager/linux-manager.js.map +1 -0
- package/dist/window-manager/macos-manager.d.ts +103 -0
- package/dist/window-manager/macos-manager.d.ts.map +1 -0
- package/dist/window-manager/macos-manager.js +637 -0
- package/dist/window-manager/macos-manager.js.map +1 -0
- package/dist/window-manager/smart-layouts.d.ts +116 -0
- package/dist/window-manager/smart-layouts.d.ts.map +1 -0
- package/dist/window-manager/smart-layouts.js +188 -0
- package/dist/window-manager/smart-layouts.js.map +1 -0
- package/dist/window-manager/smart-layouts.test.d.ts +8 -0
- package/dist/window-manager/smart-layouts.test.d.ts.map +1 -0
- package/dist/window-manager/smart-layouts.test.js +311 -0
- package/dist/window-manager/smart-layouts.test.js.map +1 -0
- package/dist/window-manager/tile-state.d.ts +87 -0
- package/dist/window-manager/tile-state.d.ts.map +1 -0
- package/dist/window-manager/tile-state.js +136 -0
- package/dist/window-manager/tile-state.js.map +1 -0
- package/dist/window-manager/tile-state.test.d.ts +8 -0
- package/dist/window-manager/tile-state.test.d.ts.map +1 -0
- package/dist/window-manager/tile-state.test.js +179 -0
- package/dist/window-manager/tile-state.test.js.map +1 -0
- package/dist/window-manager/types.d.ts +104 -0
- package/dist/window-manager/types.d.ts.map +1 -0
- package/dist/window-manager/types.js +8 -0
- package/dist/window-manager/types.js.map +1 -0
- package/dist/window-manager/windows-manager.d.ts +44 -0
- package/dist/window-manager/windows-manager.d.ts.map +1 -0
- package/dist/window-manager/windows-manager.js +281 -0
- package/dist/window-manager/windows-manager.js.map +1 -0
- package/dist/window-manager/windows-manager.test.d.ts +8 -0
- package/dist/window-manager/windows-manager.test.d.ts.map +1 -0
- package/dist/window-manager/windows-manager.test.js +183 -0
- package/dist/window-manager/windows-manager.test.js.map +1 -0
- package/gui-dist/assets/index-BmYIHRYe.js +142 -0
- package/gui-dist/assets/index-D_N5RH8O.css +1 -0
- package/gui-dist/assets/vendor-icons-ByXNrcwf.js +336 -0
- package/gui-dist/assets/vendor-markdown-DWPYwU1x.js +22 -0
- package/gui-dist/assets/vendor-react-CpILBTDM.js +59 -0
- package/gui-dist/index.html +17 -0
- package/gui-dist/jacsub.png +0 -0
- package/package.json +67 -0
|
@@ -0,0 +1,281 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows Window Manager
|
|
3
|
+
*
|
|
4
|
+
* Implements window positioning and tiling using PowerShell and Win32 API.
|
|
5
|
+
*/
|
|
6
|
+
import { execFile as execFileCb } from 'child_process';
|
|
7
|
+
import { promisify } from 'util';
|
|
8
|
+
import { calculateAllSlots } from './smart-layouts.js';
|
|
9
|
+
const execFileAsync = promisify(execFileCb);
|
|
10
|
+
/**
|
|
11
|
+
* Execute a PowerShell script and return the result.
|
|
12
|
+
*
|
|
13
|
+
* Uses -EncodedCommand (Base64-encoded UTF-16LE) to avoid all quoting and
|
|
14
|
+
* escaping issues. Previous approach used exec() with inline double-quote
|
|
15
|
+
* escaping which broke PowerShell here-strings (@"..."@) and embedded quotes.
|
|
16
|
+
*/
|
|
17
|
+
async function runPowerShell(script) {
|
|
18
|
+
const encoded = Buffer.from(script, 'utf16le').toString('base64');
|
|
19
|
+
const { stdout } = await execFileAsync('powershell', ['-NoProfile', '-NonInteractive', '-EncodedCommand', encoded], { timeout: 10000 });
|
|
20
|
+
return stdout.trim();
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Windows Window Manager using PowerShell and Win32 API
|
|
24
|
+
*/
|
|
25
|
+
export class WindowsWindowManager {
|
|
26
|
+
/** Cache display info to avoid repeated slow .NET assembly loads */
|
|
27
|
+
displayCache = null;
|
|
28
|
+
static DISPLAY_CACHE_TTL = 30000; // 30 seconds
|
|
29
|
+
getPlatform() {
|
|
30
|
+
return 'win32';
|
|
31
|
+
}
|
|
32
|
+
isSupported() {
|
|
33
|
+
return process.platform === 'win32';
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Get all displays using .NET System.Windows.Forms.Screen.
|
|
37
|
+
* Results are cached for 30s to avoid repeated slow PowerShell/.NET loads.
|
|
38
|
+
*/
|
|
39
|
+
async getDisplays() {
|
|
40
|
+
if (this.displayCache && Date.now() - this.displayCache.timestamp < WindowsWindowManager.DISPLAY_CACHE_TTL) {
|
|
41
|
+
return this.displayCache.displays;
|
|
42
|
+
}
|
|
43
|
+
const script = `
|
|
44
|
+
Add-Type -AssemblyName System.Windows.Forms
|
|
45
|
+
$screens = [System.Windows.Forms.Screen]::AllScreens
|
|
46
|
+
$result = @()
|
|
47
|
+
foreach ($screen in $screens) {
|
|
48
|
+
$obj = @{
|
|
49
|
+
name = $screen.DeviceName
|
|
50
|
+
primary = $screen.Primary
|
|
51
|
+
x = $screen.Bounds.X
|
|
52
|
+
y = $screen.Bounds.Y
|
|
53
|
+
width = $screen.Bounds.Width
|
|
54
|
+
height = $screen.Bounds.Height
|
|
55
|
+
workX = $screen.WorkingArea.X
|
|
56
|
+
workY = $screen.WorkingArea.Y
|
|
57
|
+
workWidth = $screen.WorkingArea.Width
|
|
58
|
+
workHeight = $screen.WorkingArea.Height
|
|
59
|
+
}
|
|
60
|
+
$result += $obj
|
|
61
|
+
}
|
|
62
|
+
$result | ConvertTo-Json -Compress
|
|
63
|
+
`;
|
|
64
|
+
try {
|
|
65
|
+
const result = await runPowerShell(script);
|
|
66
|
+
const screens = JSON.parse(result);
|
|
67
|
+
// Handle single display (not an array)
|
|
68
|
+
const screenArray = Array.isArray(screens) ? screens : [screens];
|
|
69
|
+
const displays = screenArray.map((screen, index) => ({
|
|
70
|
+
id: screen.name || `display-${index}`,
|
|
71
|
+
bounds: {
|
|
72
|
+
x: screen.x,
|
|
73
|
+
y: screen.y,
|
|
74
|
+
width: screen.width,
|
|
75
|
+
height: screen.height,
|
|
76
|
+
},
|
|
77
|
+
workArea: {
|
|
78
|
+
x: screen.workX,
|
|
79
|
+
y: screen.workY,
|
|
80
|
+
width: screen.workWidth,
|
|
81
|
+
height: screen.workHeight,
|
|
82
|
+
},
|
|
83
|
+
isPrimary: screen.primary,
|
|
84
|
+
}));
|
|
85
|
+
this.displayCache = { displays, timestamp: Date.now() };
|
|
86
|
+
return displays;
|
|
87
|
+
}
|
|
88
|
+
catch {
|
|
89
|
+
// Fallback to reasonable defaults
|
|
90
|
+
return [
|
|
91
|
+
{
|
|
92
|
+
id: 'primary',
|
|
93
|
+
bounds: { x: 0, y: 0, width: 1920, height: 1080 },
|
|
94
|
+
workArea: { x: 0, y: 0, width: 1920, height: 1040 }, // Account for taskbar
|
|
95
|
+
isPrimary: true,
|
|
96
|
+
},
|
|
97
|
+
];
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Position a terminal window by its terminal key.
|
|
102
|
+
*
|
|
103
|
+
* Handles DISCOVERED: prefix wrapping (e.g., DISCOVERED:PID:12345).
|
|
104
|
+
* Extracts the PID from any key format that contains one.
|
|
105
|
+
*/
|
|
106
|
+
async positionWindow(terminalKey, geometry) {
|
|
107
|
+
// Strip DISCOVERED: prefix if present
|
|
108
|
+
const effectiveKey = terminalKey.startsWith('DISCOVERED:')
|
|
109
|
+
? terminalKey.substring(11)
|
|
110
|
+
: terminalKey;
|
|
111
|
+
// Extract PID from the key using regex (handles PID:xxx, TTY:xxx:pid, etc.)
|
|
112
|
+
const pidMatch = effectiveKey.match(/(?:^PID:|^CONPTY:|^WINTERM:)(\d+)$/);
|
|
113
|
+
if (pidMatch) {
|
|
114
|
+
return this.positionByPid(pidMatch[1], geometry);
|
|
115
|
+
}
|
|
116
|
+
// Fallback: try to extract trailing PID (e.g., TTY:ttys001:12345)
|
|
117
|
+
const trailingPidMatch = effectiveKey.match(/:(\d+)$/);
|
|
118
|
+
if (trailingPidMatch) {
|
|
119
|
+
return this.positionByPid(trailingPidMatch[1], geometry);
|
|
120
|
+
}
|
|
121
|
+
return { success: false, error: `Cannot extract PID from terminal key: ${terminalKey}` };
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Position a window by process ID using Win32 EnumWindows + parent PID traversal.
|
|
125
|
+
*
|
|
126
|
+
* Console apps like node.exe (Claude Code) don't own their window — the visible
|
|
127
|
+
* terminal window belongs to a parent host process (wt.exe, conhost.exe, or
|
|
128
|
+
* powershell.exe). We use EnumWindows to find visible windows by PID, and if
|
|
129
|
+
* none are found, walk up the process tree until we find the window-owning parent.
|
|
130
|
+
*
|
|
131
|
+
* This is the same approach used by production tiling WMs (Komorebi, GlazeWM, FancyWM).
|
|
132
|
+
*/
|
|
133
|
+
async positionByPid(pid, geometry) {
|
|
134
|
+
const { x, y, width, height } = geometry;
|
|
135
|
+
const script = `
|
|
136
|
+
Add-Type @"
|
|
137
|
+
using System;
|
|
138
|
+
using System.Collections.Generic;
|
|
139
|
+
using System.Runtime.InteropServices;
|
|
140
|
+
|
|
141
|
+
public class Win32Window {
|
|
142
|
+
[DllImport("user32.dll")]
|
|
143
|
+
public static extern bool SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags);
|
|
144
|
+
|
|
145
|
+
[DllImport("user32.dll")]
|
|
146
|
+
public static extern bool SetForegroundWindow(IntPtr hWnd);
|
|
147
|
+
|
|
148
|
+
[DllImport("user32.dll")]
|
|
149
|
+
public static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);
|
|
150
|
+
|
|
151
|
+
public delegate bool EnumWindowsProc(IntPtr hWnd, IntPtr lParam);
|
|
152
|
+
|
|
153
|
+
[DllImport("user32.dll")]
|
|
154
|
+
public static extern bool EnumWindows(EnumWindowsProc lpEnumFunc, IntPtr lParam);
|
|
155
|
+
|
|
156
|
+
[DllImport("user32.dll")]
|
|
157
|
+
public static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
|
|
158
|
+
|
|
159
|
+
[DllImport("user32.dll")]
|
|
160
|
+
public static extern bool IsWindowVisible(IntPtr hWnd);
|
|
161
|
+
|
|
162
|
+
[DllImport("user32.dll")]
|
|
163
|
+
public static extern int GetWindowTextLength(IntPtr hWnd);
|
|
164
|
+
|
|
165
|
+
public static List<IntPtr> FindWindowsByPid(uint targetPid) {
|
|
166
|
+
var result = new List<IntPtr>();
|
|
167
|
+
EnumWindows(delegate(IntPtr hWnd, IntPtr lParam) {
|
|
168
|
+
uint pid;
|
|
169
|
+
GetWindowThreadProcessId(hWnd, out pid);
|
|
170
|
+
if (pid == targetPid && IsWindowVisible(hWnd) && GetWindowTextLength(hWnd) > 0) {
|
|
171
|
+
result.Add(hWnd);
|
|
172
|
+
}
|
|
173
|
+
return true;
|
|
174
|
+
}, IntPtr.Zero);
|
|
175
|
+
return result;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
"@
|
|
179
|
+
try {
|
|
180
|
+
$targetPid = [uint32]${pid}
|
|
181
|
+
$hwnd = [IntPtr]::Zero
|
|
182
|
+
$maxDepth = 5
|
|
183
|
+
|
|
184
|
+
# Walk up the process tree to find the window-owning process
|
|
185
|
+
for ($depth = 0; $depth -lt $maxDepth; $depth++) {
|
|
186
|
+
$windows = [Win32Window]::FindWindowsByPid($targetPid)
|
|
187
|
+
if ($windows.Count -gt 0) {
|
|
188
|
+
$hwnd = $windows[0]
|
|
189
|
+
break
|
|
190
|
+
}
|
|
191
|
+
# Get parent PID via CIM (modern replacement for WMI)
|
|
192
|
+
$proc = Get-CimInstance Win32_Process -Filter "ProcessId=$targetPid" -ErrorAction Stop
|
|
193
|
+
if (-not $proc -or -not $proc.ParentProcessId -or $proc.ParentProcessId -eq 0) {
|
|
194
|
+
break
|
|
195
|
+
}
|
|
196
|
+
$targetPid = [uint32]$proc.ParentProcessId
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if ($hwnd -eq [IntPtr]::Zero) {
|
|
200
|
+
Write-Output "no_window"
|
|
201
|
+
exit
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
# SW_RESTORE = 9 (restore if minimized)
|
|
205
|
+
[Win32Window]::ShowWindow($hwnd, 9) | Out-Null
|
|
206
|
+
# SWP_NOZORDER = 0x0004, SWP_SHOWWINDOW = 0x0040
|
|
207
|
+
$result = [Win32Window]::SetWindowPos($hwnd, [IntPtr]::Zero, ${x}, ${y}, ${width}, ${height}, 0x0044)
|
|
208
|
+
[Win32Window]::SetForegroundWindow($hwnd) | Out-Null
|
|
209
|
+
if ($result) {
|
|
210
|
+
Write-Output "ok"
|
|
211
|
+
} else {
|
|
212
|
+
Write-Output "failed"
|
|
213
|
+
}
|
|
214
|
+
} catch {
|
|
215
|
+
Write-Output "error: $($_.Exception.Message)"
|
|
216
|
+
}
|
|
217
|
+
`;
|
|
218
|
+
try {
|
|
219
|
+
const result = await runPowerShell(script);
|
|
220
|
+
if (result === 'ok') {
|
|
221
|
+
return { success: true };
|
|
222
|
+
}
|
|
223
|
+
else if (result === 'no_window') {
|
|
224
|
+
return { success: false, error: 'Process has no main window' };
|
|
225
|
+
}
|
|
226
|
+
else if (result.startsWith('error:')) {
|
|
227
|
+
return { success: false, error: result.substring(7) };
|
|
228
|
+
}
|
|
229
|
+
return { success: false, error: 'Failed to position window' };
|
|
230
|
+
}
|
|
231
|
+
catch (err) {
|
|
232
|
+
return { success: false, error: err instanceof Error ? err.message : String(err) };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
/**
|
|
236
|
+
* Tile multiple terminal windows
|
|
237
|
+
*/
|
|
238
|
+
async tileWindows(terminalKeys, layout, display) {
|
|
239
|
+
if (terminalKeys.length === 0) {
|
|
240
|
+
return { success: true, positioned: 0, total: 0 };
|
|
241
|
+
}
|
|
242
|
+
// Get display info
|
|
243
|
+
const displays = await this.getDisplays();
|
|
244
|
+
const targetDisplay = display || displays.find(d => d.isPrimary) || displays[0];
|
|
245
|
+
if (!targetDisplay) {
|
|
246
|
+
return {
|
|
247
|
+
success: false,
|
|
248
|
+
positioned: 0,
|
|
249
|
+
total: terminalKeys.length,
|
|
250
|
+
errors: ['No display available'],
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
// Use smart layout engine for all window counts (consistent with tile state)
|
|
254
|
+
const allSlots = calculateAllSlots(targetDisplay.workArea, terminalKeys.length);
|
|
255
|
+
const errors = [];
|
|
256
|
+
let positioned = 0;
|
|
257
|
+
// Position each window
|
|
258
|
+
for (let i = 0; i < terminalKeys.length; i++) {
|
|
259
|
+
const terminalKey = terminalKeys[i];
|
|
260
|
+
const geometry = allSlots[i].geometry;
|
|
261
|
+
const result = await this.positionWindow(terminalKey, geometry);
|
|
262
|
+
if (result.success) {
|
|
263
|
+
positioned++;
|
|
264
|
+
}
|
|
265
|
+
else if (result.error) {
|
|
266
|
+
errors.push(`${terminalKey}: ${result.error}`);
|
|
267
|
+
}
|
|
268
|
+
// Small delay between windows
|
|
269
|
+
if (i < terminalKeys.length - 1) {
|
|
270
|
+
await new Promise(resolve => setTimeout(resolve, 50));
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
return {
|
|
274
|
+
success: positioned === terminalKeys.length,
|
|
275
|
+
positioned,
|
|
276
|
+
total: terminalKeys.length,
|
|
277
|
+
errors: errors.length > 0 ? errors : undefined,
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
//# sourceMappingURL=windows-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-manager.js","sourceRoot":"","sources":["../../src/window-manager/windows-manager.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows Window Manager Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests terminal key parsing, PID extraction, result parsing, and tiling logic.
|
|
5
|
+
* PowerShell execution is mocked to prevent real Win32 API calls during tests.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=windows-manager.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-manager.test.d.ts","sourceRoot":"","sources":["../../src/window-manager/windows-manager.test.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Windows Window Manager Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests terminal key parsing, PID extraction, result parsing, and tiling logic.
|
|
5
|
+
* PowerShell execution is mocked to prevent real Win32 API calls during tests.
|
|
6
|
+
*/
|
|
7
|
+
import { jest } from '@jest/globals';
|
|
8
|
+
// ─── MOCKS (must be before module-under-test import) ──────────
|
|
9
|
+
const mockExecFile = jest.fn();
|
|
10
|
+
jest.unstable_mockModule('child_process', () => ({
|
|
11
|
+
execFile: mockExecFile,
|
|
12
|
+
}));
|
|
13
|
+
// ─── IMPORTS (after mocks) ────────────────────────────────────
|
|
14
|
+
const { WindowsWindowManager } = await import('./windows-manager.js');
|
|
15
|
+
// ─── HELPERS ──────────────────────────────────────────────────
|
|
16
|
+
const GEOMETRY = { x: 100, y: 200, width: 800, height: 600 };
|
|
17
|
+
/**
|
|
18
|
+
* Make mockExecFile call back with the given stdout value.
|
|
19
|
+
* The callback is the last argument to execFile(cmd, args, opts, cb).
|
|
20
|
+
*/
|
|
21
|
+
function mockPowerShellResult(stdout) {
|
|
22
|
+
mockExecFile.mockImplementation((...args) => {
|
|
23
|
+
// execFile with promisify: the callback is the last arg
|
|
24
|
+
const cb = args[args.length - 1];
|
|
25
|
+
if (typeof cb === 'function') {
|
|
26
|
+
cb(null, { stdout });
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function mockPowerShellError(message) {
|
|
31
|
+
mockExecFile.mockImplementation((...args) => {
|
|
32
|
+
const cb = args[args.length - 1];
|
|
33
|
+
if (typeof cb === 'function') {
|
|
34
|
+
cb(new Error(message), { stdout: '' });
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
// ─── TESTS ────────────────────────────────────────────────────
|
|
39
|
+
describe('WindowsWindowManager', () => {
|
|
40
|
+
let manager;
|
|
41
|
+
beforeEach(() => {
|
|
42
|
+
jest.clearAllMocks();
|
|
43
|
+
manager = new WindowsWindowManager();
|
|
44
|
+
});
|
|
45
|
+
describe('getPlatform / isSupported', () => {
|
|
46
|
+
it('returns win32 as platform', () => {
|
|
47
|
+
expect(manager.getPlatform()).toBe('win32');
|
|
48
|
+
});
|
|
49
|
+
it('isSupported reflects current platform', () => {
|
|
50
|
+
expect(manager.isSupported()).toBe(process.platform === 'win32');
|
|
51
|
+
});
|
|
52
|
+
});
|
|
53
|
+
describe('positionWindow — terminal key parsing', () => {
|
|
54
|
+
beforeEach(() => {
|
|
55
|
+
mockPowerShellResult('ok');
|
|
56
|
+
});
|
|
57
|
+
it('extracts PID from PID:12345 format', async () => {
|
|
58
|
+
const result = await manager.positionWindow('PID:12345', GEOMETRY);
|
|
59
|
+
expect(result.success).toBe(true);
|
|
60
|
+
// Verify PowerShell was called (meaning PID was extracted)
|
|
61
|
+
expect(mockExecFile).toHaveBeenCalled();
|
|
62
|
+
});
|
|
63
|
+
it('extracts PID from CONPTY:99999 format', async () => {
|
|
64
|
+
const result = await manager.positionWindow('CONPTY:99999', GEOMETRY);
|
|
65
|
+
expect(result.success).toBe(true);
|
|
66
|
+
expect(mockExecFile).toHaveBeenCalled();
|
|
67
|
+
});
|
|
68
|
+
it('extracts PID from WINTERM:54321 format', async () => {
|
|
69
|
+
const result = await manager.positionWindow('WINTERM:54321', GEOMETRY);
|
|
70
|
+
expect(result.success).toBe(true);
|
|
71
|
+
expect(mockExecFile).toHaveBeenCalled();
|
|
72
|
+
});
|
|
73
|
+
it('strips DISCOVERED: prefix before extracting PID', async () => {
|
|
74
|
+
const result = await manager.positionWindow('DISCOVERED:PID:12345', GEOMETRY);
|
|
75
|
+
expect(result.success).toBe(true);
|
|
76
|
+
expect(mockExecFile).toHaveBeenCalled();
|
|
77
|
+
});
|
|
78
|
+
it('strips DISCOVERED: prefix for CONPTY keys', async () => {
|
|
79
|
+
const result = await manager.positionWindow('DISCOVERED:CONPTY:99999', GEOMETRY);
|
|
80
|
+
expect(result.success).toBe(true);
|
|
81
|
+
expect(mockExecFile).toHaveBeenCalled();
|
|
82
|
+
});
|
|
83
|
+
it('extracts trailing PID from TTY:ttys001:12345 format', async () => {
|
|
84
|
+
const result = await manager.positionWindow('TTY:ttys001:12345', GEOMETRY);
|
|
85
|
+
expect(result.success).toBe(true);
|
|
86
|
+
expect(mockExecFile).toHaveBeenCalled();
|
|
87
|
+
});
|
|
88
|
+
it('returns error for keys without extractable PID', async () => {
|
|
89
|
+
const result = await manager.positionWindow('NOKEY', GEOMETRY);
|
|
90
|
+
expect(result.success).toBe(false);
|
|
91
|
+
expect(result.error).toContain('Cannot extract PID');
|
|
92
|
+
// PowerShell should NOT be called
|
|
93
|
+
expect(mockExecFile).not.toHaveBeenCalled();
|
|
94
|
+
});
|
|
95
|
+
it('returns error for empty terminal key', async () => {
|
|
96
|
+
const result = await manager.positionWindow('', GEOMETRY);
|
|
97
|
+
expect(result.success).toBe(false);
|
|
98
|
+
expect(result.error).toContain('Cannot extract PID');
|
|
99
|
+
});
|
|
100
|
+
});
|
|
101
|
+
describe('positionWindow — PowerShell result parsing', () => {
|
|
102
|
+
it('returns success for "ok" result', async () => {
|
|
103
|
+
mockPowerShellResult('ok');
|
|
104
|
+
const result = await manager.positionWindow('PID:1234', GEOMETRY);
|
|
105
|
+
expect(result).toEqual({ success: true });
|
|
106
|
+
});
|
|
107
|
+
it('returns error for "no_window" result', async () => {
|
|
108
|
+
mockPowerShellResult('no_window');
|
|
109
|
+
const result = await manager.positionWindow('PID:1234', GEOMETRY);
|
|
110
|
+
expect(result.success).toBe(false);
|
|
111
|
+
expect(result.error).toBe('Process has no main window');
|
|
112
|
+
});
|
|
113
|
+
it('returns error for "failed" result', async () => {
|
|
114
|
+
mockPowerShellResult('failed');
|
|
115
|
+
const result = await manager.positionWindow('PID:1234', GEOMETRY);
|
|
116
|
+
expect(result.success).toBe(false);
|
|
117
|
+
expect(result.error).toBe('Failed to position window');
|
|
118
|
+
});
|
|
119
|
+
it('returns error message from PowerShell errors', async () => {
|
|
120
|
+
mockPowerShellResult('error: access denied');
|
|
121
|
+
const result = await manager.positionWindow('PID:1234', GEOMETRY);
|
|
122
|
+
expect(result.success).toBe(false);
|
|
123
|
+
expect(result.error).toBe('access denied');
|
|
124
|
+
});
|
|
125
|
+
it('handles PowerShell execution failure', async () => {
|
|
126
|
+
mockPowerShellError('Command failed: timeout');
|
|
127
|
+
const result = await manager.positionWindow('PID:1234', GEOMETRY);
|
|
128
|
+
expect(result.success).toBe(false);
|
|
129
|
+
expect(result.error).toBe('Command failed: timeout');
|
|
130
|
+
});
|
|
131
|
+
});
|
|
132
|
+
describe('positionWindow — script content', () => {
|
|
133
|
+
beforeEach(() => {
|
|
134
|
+
mockPowerShellResult('ok');
|
|
135
|
+
});
|
|
136
|
+
it('passes geometry values to PowerShell script', async () => {
|
|
137
|
+
await manager.positionWindow('PID:5678', { x: 50, y: 100, width: 640, height: 480 });
|
|
138
|
+
expect(mockExecFile).toHaveBeenCalled();
|
|
139
|
+
// The script is Base64-encoded as the -EncodedCommand argument
|
|
140
|
+
const args = mockExecFile.mock.calls[0][1];
|
|
141
|
+
expect(args).toContain('-EncodedCommand');
|
|
142
|
+
// Decode the Base64 to verify PID and geometry are embedded
|
|
143
|
+
const encodedIdx = args.indexOf('-EncodedCommand');
|
|
144
|
+
const encoded = args[encodedIdx + 1];
|
|
145
|
+
const script = Buffer.from(encoded, 'base64').toString('utf16le');
|
|
146
|
+
expect(script).toContain('5678');
|
|
147
|
+
expect(script).toContain('50');
|
|
148
|
+
expect(script).toContain('100');
|
|
149
|
+
expect(script).toContain('640');
|
|
150
|
+
expect(script).toContain('480');
|
|
151
|
+
});
|
|
152
|
+
it('uses EnumWindows approach (not MainWindowHandle)', async () => {
|
|
153
|
+
await manager.positionWindow('PID:1234', GEOMETRY);
|
|
154
|
+
const args = mockExecFile.mock.calls[0][1];
|
|
155
|
+
const encodedIdx = args.indexOf('-EncodedCommand');
|
|
156
|
+
const encoded = args[encodedIdx + 1];
|
|
157
|
+
const script = Buffer.from(encoded, 'base64').toString('utf16le');
|
|
158
|
+
expect(script).toContain('EnumWindows');
|
|
159
|
+
expect(script).toContain('FindWindowsByPid');
|
|
160
|
+
expect(script).toContain('GetWindowThreadProcessId');
|
|
161
|
+
expect(script).toContain('IsWindowVisible');
|
|
162
|
+
expect(script).not.toContain('MainWindowHandle');
|
|
163
|
+
});
|
|
164
|
+
it('includes parent PID traversal via Get-CimInstance', async () => {
|
|
165
|
+
await manager.positionWindow('PID:1234', GEOMETRY);
|
|
166
|
+
const args = mockExecFile.mock.calls[0][1];
|
|
167
|
+
const encodedIdx = args.indexOf('-EncodedCommand');
|
|
168
|
+
const encoded = args[encodedIdx + 1];
|
|
169
|
+
const script = Buffer.from(encoded, 'base64').toString('utf16le');
|
|
170
|
+
expect(script).toContain('Get-CimInstance');
|
|
171
|
+
expect(script).toContain('ParentProcessId');
|
|
172
|
+
expect(script).toContain('$maxDepth');
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
describe('tileWindows', () => {
|
|
176
|
+
it('returns success for empty key list', async () => {
|
|
177
|
+
const result = await manager.tileWindows([], 'side-by-side');
|
|
178
|
+
expect(result).toEqual({ success: true, positioned: 0, total: 0 });
|
|
179
|
+
expect(mockExecFile).not.toHaveBeenCalled();
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
});
|
|
183
|
+
//# sourceMappingURL=windows-manager.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"windows-manager.test.js","sourceRoot":"","sources":["../../src/window-manager/windows-manager.test.ts"],"names":[],"mappings":"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"}
|