|
| 1 | +# End-to-end check of MaximizeButtonArea (#70) in a real Flutter app on |
| 2 | +# Windows 11: flutter_window_title_bar_example with its title bar hidden draws |
| 3 | +# its own Maximize / Restore chip, wrapped in MaximizeButtonArea. Resting the |
| 4 | +# cursor on it opens the snap layouts; clicking it maximizes and restores. |
| 5 | +# Owner-guarded clicks on the example's own window only, no keyboard input. |
| 6 | +$ErrorActionPreference = 'Stop' |
| 7 | +. "$PSScriptRoot\env.ps1" |
| 8 | +. "$PSScriptRoot\winput.ps1" |
| 9 | +. "$PSScriptRoot\guiapp.ps1" |
| 10 | +Add-Type @" |
| 11 | +using System; |
| 12 | +using System.Runtime.InteropServices; |
| 13 | +public static class SnapWin { |
| 14 | + [DllImport("user32.dll")] public static extern bool IsZoomed(IntPtr h); |
| 15 | +} |
| 16 | +"@ |
| 17 | +Add-Type -AssemblyName System.Drawing |
| 18 | + |
| 19 | +Start-Result "$RemoteScratch\flutter_window_title_bar_snap_test.result.txt" |
| 20 | +$exe = $env:TITLE_BAR_EXAMPLE_EXE |
| 21 | +if (-not $exe) { |
| 22 | + $exe = Get-FlutterExe "$RemoteWorkspace\examples\flutter_window_title_bar_example" 'window_title_bar_example' |
| 23 | +} |
| 24 | +Assert-Idle |
| 25 | +$app = Start-GuiApp $exe |
| 26 | +# The probe fails (a traceback on stderr) until the VM service is up, and |
| 27 | +# PowerShell 5.1 turns native stderr into a terminating error under Stop. |
| 28 | +function Get-ViewsQuietly { |
| 29 | + $saved = $ErrorActionPreference |
| 30 | + $ErrorActionPreference = 'Continue' |
| 31 | + try { @(Get-Views $app 2>$null) } catch { @() } finally { $ErrorActionPreference = $saved } |
| 32 | +} |
| 33 | +function Get-State { |
| 34 | + $script:win = Get-Win $app 'nativeapi*' |
| 35 | + if (-not $script:win) { throw 'The example window is missing' } |
| 36 | + $script:view = Get-ViewsQuietly | Select-Object -First 1 |
| 37 | + if (-not $script:view) { throw 'The example has no Flutter view to probe' } |
| 38 | +} |
| 39 | +try { |
| 40 | + $deadline = (Get-Date).AddSeconds(40) |
| 41 | + while (@(Get-ViewsQuietly).Count -eq 0 -and (Get-Date) -lt $deadline) { Pause 0.5 } |
| 42 | + Get-State |
| 43 | + Invoke-Activate $app $win |
| 44 | + Invoke-Click $app (ConvertTo-Screen $win (Get-TextCenter $view 'Hidden')) |
| 45 | + Pause 1.5 |
| 46 | + Get-State |
| 47 | + Check 'Hidden puts a Maximize chip into the strip' (Test-ViewText $view 'Maximize') |
| 48 | + $restoredWidth = $win.Right - $win.Left |
| 49 | + |
| 50 | + # Rest on the chip: the snap layouts open below it, over this window. |
| 51 | + $button = ConvertTo-Screen $win (Get-TextCenter $view 'Maximize') |
| 52 | + $below = @($button[0], ($button[1] + [int](80 * $win.Scale))) |
| 53 | + $ownerBefore = [WInput]::Owner($below[0], $below[1]) |
| 54 | + Assert-Owner $app.Proc.Id $button[0] $button[1] |
| 55 | + Move-Cursor $button 500 |
| 56 | + Pause 2.0 |
| 57 | + $ownerDuring = [WInput]::Owner($below[0], $below[1]) |
| 58 | + $bmp = New-Object System.Drawing.Bitmap 900, 520 |
| 59 | + $g = [System.Drawing.Graphics]::FromImage($bmp) |
| 60 | + $g.CopyFromScreen([Math]::Max(0, $button[0] - 650), [Math]::Max(0, $button[1] - 60), 0, 0, $bmp.Size) |
| 61 | + $bmp.Save("$RemoteScratch\flutter_window_title_bar_snap_test.png", [System.Drawing.Imaging.ImageFormat]::Png) |
| 62 | + $g.Dispose(); $bmp.Dispose() |
| 63 | + Check 'below the chip is the example before the hover' ($ownerBefore -eq $app.Proc.Id) "pid $ownerBefore" |
| 64 | + $process = (Get-Process -Id $ownerDuring -ErrorAction SilentlyContinue).ProcessName |
| 65 | + Check 'resting on the chip opens the snap layouts over it' ` |
| 66 | + ($ownerDuring -ne $app.Proc.Id -and $ownerDuring -ne 0) "pid $ownerDuring ($process)" |
| 67 | + |
| 68 | + # Leave sideways along the strip, away from the flyout. |
| 69 | + $side = @(($button[0] - [int](220 * $win.Scale)), $button[1]) |
| 70 | + Assert-Owner $app.Proc.Id $side[0] $side[1] |
| 71 | + Move-Cursor $side 400 |
| 72 | + Pause 1.5 |
| 73 | + Check 'leaving the chip closes the snap layouts' ([WInput]::Owner($below[0], $below[1]) -eq $app.Proc.Id) |
| 74 | + |
| 75 | + # A click on the chip reaches Flutter, which maximizes the window. |
| 76 | + Invoke-Click $app $button 400 |
| 77 | + Pause 1.5 |
| 78 | + Get-State |
| 79 | + Check 'clicking Maximize maximizes the window' ([SnapWin]::IsZoomed([IntPtr]$win.Hwnd)) "width $($win.Right - $win.Left)" |
| 80 | + Check 'the chip now reads Restore' (Test-ViewText $view 'Restore') |
| 81 | + |
| 82 | + $button = ConvertTo-Screen $win (Get-TextCenter $view 'Restore') |
| 83 | + Invoke-Click $app $button 400 |
| 84 | + Pause 1.5 |
| 85 | + Get-State |
| 86 | + Check 'clicking Restore restores the window' (-not [SnapWin]::IsZoomed([IntPtr]$win.Hwnd)) |
| 87 | + Check 'at its earlier width' ([Math]::Abs(($win.Right - $win.Left) - $restoredWidth) -le 2) "$($win.Right - $win.Left) vs $restoredWidth" |
| 88 | + Check 'the chip reads Maximize again' (Test-ViewText $view 'Maximize') |
| 89 | +} finally { |
| 90 | + Stop-GuiApp $app | Out-Null |
| 91 | +} |
| 92 | +Say "$(if ($script:Failures) { 'FAILED' } else { 'OK' })" |
0 commit comments