Root cause: xterm.js attaches its own pointerdown handler inside the
terminal and calls e.stopPropagation(), which prevents the .leaf
div's onpointerdown from firing for any click landing inside the
terminal body. That's why clicking pane bodies never moved the blue
active border — the event simply never reached our handler.
Fix: register a document-level CAPTURE-phase pointerdown listener
in App.svelte. Capture fires before xterm.js's bubble-phase handler
runs (and before it can stop propagation), so we always see the
click. The handler walks up via Element.closest('[data-leaf-id]')
to find which pane was clicked, then calls orch.setActive.
- LeafPane.svelte: add data-leaf-id={leaf.id} attribute so the
document handler can identify the clicked pane.
- App.svelte: $effect attaches document.addEventListener('pointerdown',
..., true) and cleans up on teardown.
- Keep the per-leaf onpointerdown as a redundant backup for clicks
on toolbar buttons (which sit outside the xterm subtree). Cheap
+ idempotent.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
60 lines
2.3 KiB
PowerShell
60 lines
2.3 KiB
PowerShell
# Helpers for driving the tiletopia window from PowerShell.
|
|
Add-Type -AssemblyName System.Windows.Forms
|
|
Add-Type -AssemblyName System.Drawing
|
|
Add-Type @'
|
|
using System;
|
|
using System.Runtime.InteropServices;
|
|
public class W {
|
|
[DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr h, out RECT r);
|
|
[DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr h);
|
|
[DllImport("user32.dll")] public static extern bool ShowWindow(IntPtr h, int n);
|
|
[DllImport("user32.dll")] public static extern bool SetCursorPos(int x, int y);
|
|
[DllImport("user32.dll")] public static extern void mouse_event(uint flags, uint dx, uint dy, uint dwData, int extraInfo);
|
|
[StructLayout(LayoutKind.Sequential)] public struct RECT { public int Left, Top, Right, Bottom; }
|
|
}
|
|
'@
|
|
|
|
function Get-TileWindow {
|
|
$p = Get-Process tiletopia -ErrorAction Stop | Where-Object { $_.MainWindowHandle -ne 0 } | Select-Object -First 1
|
|
if (-not $p) { throw "no tiletopia window" }
|
|
return $p
|
|
}
|
|
|
|
function Bring-ToFront {
|
|
$p = Get-TileWindow
|
|
[W]::ShowWindow($p.MainWindowHandle, 9) | Out-Null # SW_RESTORE
|
|
[W]::SetForegroundWindow($p.MainWindowHandle) | Out-Null
|
|
Start-Sleep -Milliseconds 300
|
|
$r = New-Object W+RECT
|
|
[W]::GetWindowRect($p.MainWindowHandle, [ref] $r) | Out-Null
|
|
return $r
|
|
}
|
|
|
|
function Save-Shot([string]$path) {
|
|
$r = Bring-ToFront
|
|
$w = $r.Right - $r.Left
|
|
$h = $r.Bottom - $r.Top
|
|
$bmp = New-Object System.Drawing.Bitmap $w, $h
|
|
$g = [System.Drawing.Graphics]::FromImage($bmp)
|
|
$g.CopyFromScreen($r.Left, $r.Top, 0, 0, (New-Object System.Drawing.Size $w, $h))
|
|
$bmp.Save($path)
|
|
$g.Dispose()
|
|
$bmp.Dispose()
|
|
Write-Host ("saved " + $path + " (" + $w + "x" + $h + " at " + $r.Left + "," + $r.Top + ")")
|
|
return @{ x = $r.Left; y = $r.Top; w = $w; h = $h }
|
|
}
|
|
|
|
# Click at *window-relative* coordinates (so we don't depend on the window's
|
|
# screen position from one run to the next).
|
|
function Click-Win([int]$relX, [int]$relY) {
|
|
$r = Bring-ToFront
|
|
$absX = $r.Left + $relX
|
|
$absY = $r.Top + $relY
|
|
[W]::SetCursorPos($absX, $absY) | Out-Null
|
|
Start-Sleep -Milliseconds 80
|
|
[W]::mouse_event(0x0002, 0, 0, 0, 0) # LEFTDOWN
|
|
Start-Sleep -Milliseconds 30
|
|
[W]::mouse_event(0x0004, 0, 0, 0, 0) # LEFTUP
|
|
Start-Sleep -Milliseconds 120
|
|
Write-Host ("clicked window-rel " + $relX + "," + $relY + " (abs " + $absX + "," + $absY + ")")
|
|
}
|