diff --git a/CHANGELOG.md b/CHANGELOG.md index 9c04c3242..77e9391ad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,27 @@ # Changelog +## 1.4.3 - 2026-08-27 + +Stable production hotfix for **Click to position cursor**. This patch restores +reliable cursor positioning when normal physical mouse jitter occurs between +left-button press and release. It publishes as GitHub Latest with application +version `1.4.3`, package/file version `1.4.3.0`, PowerShell module version +`1.4.3`, and tag `v1.4.3`. + +### Fixed + +- Fixed Click to position cursor working intermittently when sub-threshold + pointer movement occurred between mouse-down and mouse-up. +- Fixed stale selection-copy state that could keep rejecting later plain + cursor-position clicks after one jittered gesture. +- Pointer movement below the existing drag-selection threshold now remains a + click and does not mutate selection or create a phantom copy candidate. +- Cursor-reposition eligibility and selection-copy eligibility now have + independent gesture responsibilities. +- Added deterministic coverage for 1-pixel and repeated jitter, ten sequential + clicks, a poisoned-follow-up gesture, the exact drag-threshold boundary, + continued drag selection, CopyOnSelect, and stale-state recovery. + ## 1.4.2 - 2026-08-25 Stable patch release of the **Pane Search** generation and **Click to position diff --git a/README.ja.md b/README.ja.md index b96b2552c..f88e6002a 100644 --- a/README.ja.md +++ b/README.ja.md @@ -14,7 +14,7 @@ 最新の安定版リリースページには、インストーラー(Setup EXE)、ポータブルZIP、 リリースノート、チェックサムがまとめて掲載されています。現在の安定版は -**winTerm 1.4.2** です。 +**winTerm 1.4.3** です。 インストーラーは署名されていないため、Windowsに「不明な発行元」または SmartScreenの警告が表示される場合があります。必ず上記の公式リリースから @@ -34,8 +34,8 @@ Microsoft、Windows、Windows Terminalのロゴも使用していません。 - `winTerm--setup-x64.exe` — 現在のユーザー、または全ユーザーへのインストール用; - `winTerm--portable-x64.zip` — 展開してそのまま実行する用。 -現在のソースバージョンは `1.4.2` で、 -最新の安定版リリースも `1.4.2` です。公開されている資産の一覧とチェックサムの全体は、 +現在のソースバージョンは `1.4.3` で、 +最新の安定版リリースも `1.4.3` です。公開されている資産の一覧とチェックサムの全体は、 [最新の公式リリース](https://github.com/HelloThisWorld/winTerm/releases/latest) を参照してください。 @@ -46,7 +46,7 @@ Windowsに「不明な発行元」またはSmartScreenの警告が表示され Windows SDK、`Add-AppxPackage` は一切必要ありません。 [インストール手順(英語)](docs/user/installation.md)、 -[1.4.2のリリースノート(英語)](docs/releases/1.4.2.md)、 +[1.4.3のリリースノート(英語)](docs/releases/1.4.3.md)、 [1.3.0のリリースノート(英語)](docs/releases/1.3.0.md)もあわせて参照してください。 ## 主な機能 @@ -57,7 +57,8 @@ Windows SDK、`Add-AppxPackage` は一切必要ありません。 出力が流れ続けている間も検索結果が更新されます; - **クリックした位置へカーソルを移動**: シェル統合で安全に確認できる現在の編集中 コマンド内をクリックすると、シェルのテキストカーソルがその位置へ移動します。 - 既定で有効で、Profile > Advancedから無効にできます。ドラッグ、Shift、単語/行選択、 + 既定で有効で、Profile > Advancedから無効にできます。ドラッグ判定のしきい値未満の + 小さなマウス移動は通常のクリックとして扱われます。ドラッグ、Shift、単語/行選択、 ハイパーリンク、VTマウス対応アプリの操作が優先され、明示的な `false` 設定も維持されます; - ペインごとの**Command Timeline**(`Ctrl+Tab`、またはターミナル左端の細い ハンドル): そのペインで実行したコマンドをメモリ上に保持する一覧です。 @@ -116,8 +117,8 @@ PowerShell 7と、[ビルド手順(英語)](docs/build.md)に記載された .\scripts\winterm\build.ps1 -Configuration Release -Platform x64 -IncludeTests .\scripts\winterm\test.ps1 -Suite Relevant -Configuration Release -Platform x64 .\scripts\winterm\build-unpackaged.ps1 -Configuration Release -Platform x64 -.\scripts\winterm\build-installer.ps1 -Version 1.4.2 -Platform x64 -.\scripts\winterm\build-portable.ps1 -Version 1.4.2 -Platform x64 +.\scripts\winterm\build-installer.ps1 -Version 1.4.3 -Platform x64 +.\scripts\winterm\build-portable.ps1 -Version 1.4.3 -Platform x64 ``` アンパッケージ形式の生成処理では、統合されたリソースインデックスを作るための diff --git a/README.md b/README.md index 6eb8496dc..858e428ef 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ English | [日本語](README.ja.md) [**Open the latest stable release and download winTerm for x64**](https://github.com/HelloThisWorld/winTerm/releases/latest) The latest stable Release page provides the Setup EXE, Portable ZIP, release -notes, and checksums together. The current stable release is **winTerm 1.4.2**. +notes, and checksums together. The current stable release is **winTerm 1.4.3**. The installer is unsigned, so Windows may display Unknown Publisher or a SmartScreen warning. Download only from the official release above and verify @@ -31,8 +31,8 @@ application downloads are: - `winTerm--setup-x64.exe` — current-user or all-users installation; - `winTerm--portable-x64.zip` — extract and run without installation. -The current source version is `1.4.2`; -the latest stable release is `1.4.2`. See the +The current source version is `1.4.3`; +the latest stable release is `1.4.3`. See the [latest official Release](https://github.com/HelloThisWorld/winTerm/releases/latest) for the complete published asset list and checksums. @@ -42,7 +42,7 @@ Release. No MSIX certificate, Developer Mode, Visual Studio, Windows SDK, or `Add-AppxPackage` is required to install a release EXE. See [installation guidance](docs/user/installation.md), the -[1.4.2 release notes](docs/releases/1.4.2.md), and the earlier +[1.4.3 release notes](docs/releases/1.4.3.md), and the earlier [1.3.0 notes](docs/releases/1.3.0.md). ## Core features @@ -52,9 +52,10 @@ See [installation guidance](docs/user/installation.md), the and regex modes, a compact match counter, and a scrollbar overview that stays current while output streams; - **Click to position cursor** inside the current shell-integrated editable - command, enabled by default and available under Profile > Advanced; normal - drag, Shift, word/line selection, hyperlinks, and VT mouse applications - retain precedence, and an explicit setting of `false` remains respected; + command, enabled by default and available under Profile > Advanced; small + pointer movement below the drag threshold remains a plain click, while drag, + Shift, word/line selection, hyperlinks, and VT mouse applications retain + precedence, and an explicit setting of `false` remains respected; - a per-pane **Command Timeline** (`Ctrl+Tab`, or the thin handle on the terminal's left edge): an in-memory list of the commands that pane has run, built from OSC 133 shell integration only, with load-without-executing onto @@ -109,8 +110,8 @@ Use PowerShell 7 and the Microsoft Terminal toolchain described in .\scripts\winterm\build.ps1 -Configuration Release -Platform x64 -IncludeTests .\scripts\winterm\test.ps1 -Suite Relevant -Configuration Release -Platform x64 .\scripts\winterm\build-unpackaged.ps1 -Configuration Release -Platform x64 -.\scripts\winterm\build-installer.ps1 -Version 1.4.2 -Platform x64 -.\scripts\winterm\build-portable.ps1 -Version 1.4.2 -Platform x64 +.\scripts\winterm\build-installer.ps1 -Version 1.4.3 -Platform x64 +.\scripts\winterm\build-portable.ps1 -Version 1.4.3 -Platform x64 ``` The unpackaged generator uses an unsigned MSIX only as an upstream build diff --git a/docs/current-progress.md b/docs/current-progress.md index 3fcc7a960..205816b28 100644 --- a/docs/current-progress.md +++ b/docs/current-progress.md @@ -1,138 +1,184 @@ # Current development progress -Last updated: 2026-08-25 +Last updated: 2026-08-27 ## Repository state -- Working branch: `codex/release-v1.4.2` -- Branch base: `09dc76796725d9b7bd7b0d86a28196bce14698c7` (`origin/main` at - release preparation start) -- Application version: `1.4.2` -- Package/file version: `1.4.2.0` -- PowerShell module version: `1.4.2` with an empty prerelease suffix +- Working branch: `fix/v1.4.3-click-position` +- Branch base: `0ee3adcb63c9cb028a44badeddb0362db38fa5f7` + (`origin/main` at hotfix preparation start) +- Application version: `1.4.3` +- Package/file version: `1.4.3.0` +- PowerShell module version: `1.4.3` with an empty prerelease suffix - Release channel: `stable` -- Intended tag: `v1.4.2` +- Intended tag: `v1.4.3` - Supported target: Windows 11 x64 The source remains based on the repository's pinned Microsoft Terminal baseline `release-1.25@1cea42d433253d95c4487a3037db48197b5e72f4`. -Microsoft Terminal `upstream/main` was separately fetched through -`86d15aef08e500be34497ff4e3a6f0d099ffb067` (2026-08-24) for a targeted -cursor-positioning audit; no broad upstream merge was performed. - -## 1.4.2 release scope - -winTerm 1.4.2 promotes the complete Pane Search development line and adds -Click to position cursor as a stable, default-enabled winTerm feature. It is -the combined application delta since stable v1.3.0. The immutable v1.4.1 tag -reached packaging but did not publish a GitHub Release because its release-note -signing heading did not match the exact verifier contract; 1.4.2 corrects that -release-only defect. The earlier 1.4.0 alpha and beta entries remain historical -records only. - -### Pane Search - -- `Ctrl+F` opens the focused pane's search overlay; `Ctrl+Shift+F` remains a - compatibility alias. -- Full-scrollback live matching, all-match highlighting, forward/backward - navigation, case-sensitive and regular-expression modes, and the compact - `current / total` counter are complete. -- The pane-local scrollbar overview is complete and remains independent of - the generic `ShowMarks` setting. -- Typing coalescing, sustained-output convergence, repaint signatures, - reflow, scrollback eviction, alternate-buffer changes, wide characters, - and invalid regex handling have regression coverage. - -### Click to position cursor - -- A plain single click is recorded on mouse-down and acted on only at - mouse-up. Crossing the existing drag threshold cancels positioning and - preserves normal selection without first moving the shell cursor. -- Ctrl+Click hyperlinks, VT mouse applications, double/triple click, - Shift+Click, drag selection, and copy-on-select retain their established - precedence. -- Positioning requires the unfinished final OSC 133 shell mark and accepts - only the current editable command. Historical commands, output, scrollback, - and untrusted locations safely do nothing. -- Coordinate translation validates viewport, buffer, inclusive TextBuffer - bounds, padding, overflow, resize-era points, and malformed input before any - buffer iterator is obtained. -- Full-width glyph trailing cells are excluded from LEFT/RIGHT event counts, - and each split pane sends input only through its own connection. -- The winTerm default is enabled; an explicit profile value of `false` is - preserved. The compatible internal JSON key remains - `experimental.repositionCursorWithMouse`, while localized UI describes the - stable feature as **Click to position cursor**. - -### Visual Progress and Command Timeline - -- Visual Progress remains stable in 1.4.2, including its determinate and - indeterminate renderer, per-pane state, accessibility path, and local-only - recognition controls. -- Command Timeline remains stable and pane-local, with OSC 133-backed command - boundaries, filtering, load-without-executing, copy, jump, and status. -- The 1.4.2 cursor work does not change either feature's settings, protocol, - persistence, or privacy boundaries. - -## Upstream cursor audit - -- Inspected Microsoft Terminal PR #20442 and merged commit - `de3fc87d186e5da1d5ccd8731412905f5e2aba30`, which clamps click coordinates - before TextBuffer access. -- Searched subsequent upstream history for changes involving - `RepositionCursorWithMouse`, `_repositionCursorWithMouse`, and related click - behavior. No later directly applicable cursor-safety fix was found. -- Also reviewed earlier related cursor-selection commits - `4995af3dc1cc600b57fcdd953734a13b9b1a425f` and - `d14ff939dc418fa04401304fdef539424dbb5bd5`; their relevant behavior was - already present in winTerm. -- The backport follows current inclusive coordinate contracts rather than - copying the upstream clamp literally, and adds stricter editable-mark, - overflow, vertical-padding, glyph, and release-time interaction guards. +Microsoft Terminal `upstream/main` was separately refreshed through +`c7572cde0c69733e4511787dc963eb336f17adbf` (2026-08-25) for the required +upstream-state check. No broad upstream merge was performed. + +## 1.4.3 hotfix scope + +winTerm 1.4.3 is a focused production regression hotfix for Click to position +cursor. The feature shipped in the 1.4.1 payload and remained unchanged in +1.4.2. Real physical mouse testing showed that small movement between +mouse-down and mouse-up could intermittently reject the first click and could +leave later clicks unable to reposition the cursor. + +No unrelated feature work is included. Pane Search, Command Timeline, Visual +Progress, workspace behavior, package identity, and protocol/schema versions +remain unchanged. + +Visual Progress remains unchanged in 1.4.3; this hotfix does not alter its +rendering, recognition, accessibility, privacy, or per-pane behavior. + +## Confirmed root cause + +The press path correctly recorded a plain single left click as a pending cursor +reposition and saved its touchdown position. The move path calculated the +existing drag threshold correctly, but then called `SetEndSelectionPoint()` +even when movement was still below that threshold. + +With no active selection, `ControlCore::SetEndSelectionPoint()` returned +without changing terminal selection. `ControlInteractivity` nevertheless set +`_selectionNeedsToBeCopied = true`, producing this invalid state: + +```text +HasSelection() = false +_cursorRepositionPending = true +_selectionNeedsToBeCopied = true +``` + +The release path then required the copy flag to be false before repositioning. +Normal 1-pixel jitter could therefore reject an otherwise valid click, and the +stale copy flag could remain set into future gestures. + +The bug was reproduced before production changes with a compiled deterministic +press, 1-pixel move, release test. It failed exactly on the phantom copy-state +assertion while confirming no selection existed and cursor reposition remained +pending. + +## State-machine correction + +- Pointer movement below the existing drag threshold performs no selection + operation. Cursor reposition remains pending and selection-copy state is not + modified. +- Crossing the threshold cancels cursor reposition, establishes the selection + anchor once, updates the selection end, and transfers ownership to the drag. +- Moves after the threshold continue updating only the selection end; the + anchor is not re-established. +- `ControlCore::SetEndSelectionPoint()` now reports whether an active selection + was actually updated. Interactivity marks copy state dirty only on success. +- `PointerReleased()` uses `_cursorRepositionPending` and the established + modifier/VT/Core safety checks to decide click ownership. It does not use the + selection-copy flag as the primary click proof. +- A release with no active selection normalizes stale copy state without + clearing or damaging legitimate mark-mode or CopyOnSelect state while a real + selection exists. + +Ctrl+Click hyperlinks, VT mouse reporting, double-click word selection, +triple-click line selection, Shift+Click, drag selection, and CopyOnSelect keep +their existing precedence. The 1.4.1/1.4.2 negative-coordinate, padding, +viewport, buffer-bound, historical-output, finished-mark, editable-range, +full-width-glyph, and split-pane safeguards are unchanged. + +## Regression coverage + +New deterministic Control tests cover: + +- a 1-pixel move remaining a click with no phantom selection-copy state; +- several alternating sub-threshold moves remaining a click; +- ten independent cursor-position clicks at different editable positions; +- a jittered gesture followed by another successful ordinary click; +- exact below-threshold and at-threshold behavior; +- drag selection continuing to update after the threshold without cursor + input; +- CopyOnSelect copying real drag selection but not sub-threshold jitter; +- recovery from `_selectionNeedsToBeCopied = true` while no selection exists. + +The existing cursor tests continue to cover release-only positioning, +Shift+Click, double/triple click, explicit disablement, editable shell marks, +historical output, padding, wrapped commands, CJK/full-width glyphs, and +split-pane connection isolation. + +Current local automated results: + +- focused cursor-position family: PASS, 11/11; +- complete Debug x64 compiled Control suite: PASS, 100/100; +- complete Debug x64 Relevant suite: PASS (Settings Model 245/245, + TerminalApp 51/51, Control 100/100); +- complete Release x64 application and compiled-test build: PASS; +- complete Release x64 Relevant suite: PASS (Settings Model 245/245, + TerminalApp 51/51, Control 100/100); +- Smoke suite: PASS; +- version verification: PASS for application 1.4.3, package/file 1.4.3.0, + PowerShell module 1.4.3, stable channel, and tag v1.4.3; +- branding verification with publisher `CN=helloThisWorld`: PASS; +- source-only Visual Progress verification: PASS; +- unpackaged Release x64 stage generation and layout verification: PASS. + +## Real GUI validation gate + +The real Release x64 application was launched in isolated portable mode with +PowerShell 7 and an unexecuted `git commit --amend --no-edit` command. An +OS-input validation run used actual absolute mouse-move packets between +button-down and button-up. It passed 30/30 cursor-position clicks across the +beginning, middle, and end of the line, alternating left and right, including +ten rapid far-apart clicks. Every gesture included 1-pixel X and Y movement, +inserted a temporary marker at the asserted command index, restored the +original command, and left no selected text. A paced drag selected +`commit --a`, a double click selected exactly `commit`, and a triple click +selected the complete line. + +This OS-injected real-window evidence is supplemental and is not represented +as manual physical-mouse validation. The required physical-mouse GUI gate is +still **NOT RUN**. Five verified execute/new-prompt lifecycles are also not yet +recorded because the isolated window closed during that attempted sequence. +Release readiness therefore still requires manual mouse validation with normal +physical jitter, at least 30 cursor-position clicks, separate click timing +versus genuine double/triple click, five prompt lifecycles, and PowerShell 7 at +minimum. PowerShell 5, cmd.exe, WSL, and representative VT mouse applications +should also be exercised where available. + +The 1.4.3 release must not be tagged or described as complete until this gate +has actual evidence. ## Release channel and artifacts The guarded tag workflow must confirm an exact tag/version match, absence of -an existing Release, a clean checkout, version/branding/security/privacy -gates, an x64 Release build with compiled tests, artifact generation, and a -public asset re-download before publication is considered complete. +an existing Release, a clean checkout, version/branding/security/privacy gates, +an x64 Release build with compiled tests, artifact generation, Draft Release +round-trip validation, publication, and public asset re-download. The expected public Release assets are: -- `winTerm-1.4.2-setup-x64.exe` -- `winTerm-1.4.2-portable-x64.zip` +- `winTerm-1.4.3-setup-x64.exe` +- `winTerm-1.4.3-portable-x64.zip` - `SHA256SUMS.txt` - `THIRD_PARTY_NOTICES.md` - `SBOM.spdx.json` - `SBOM.cyclonedx.json` - `release-metadata.json` -- `winTerm-1.4.2-release-notes.md` +- `winTerm-1.4.3-release-notes.md` -The installer is currently not Authenticode-signed, so Unknown Publisher or +The installer is not currently Authenticode-signed, so Unknown Publisher or SmartScreen warnings remain possible. The Release notes disclose this and direct users to verify `SHA256SUMS.txt`. -## Validation state - -Local stable-candidate validation completed on 2026-08-25: - -- Debug x64 package and all three unit-test projects built successfully. -- Smoke and Relevant suites passed. -- Compiled Settings Model, Terminal App, and Control suites passed with - 381/381, 51/51, and 93/93 tests respectively. -- Version, branding, privacy, release-workflow, and PowerShell syntax gates - passed as part of those suites. - -The formal Release workflow and public asset verification remain authoritative -for the published installer and Portable ZIP. - -## Next steps - -1. Merge through the application pull request, synchronize the Wiki ledger, - tag the exact merged `main` commit, and monitor the formal Release workflow - through public asset validation. -2. Update and deploy winterm.dev from the real `published_at` timestamp and - public v1.4.2 asset URLs, then verify English/Japanese production pages. -3. Only after both the stable Release and website are verified, remove the - published v1.4.0-beta GitHub prerelease entry while retaining its historical - git tag. +## Release plan + +1. Complete the final diff audit after all validation records are updated. +2. Complete and record the manual physical GUI mouse-jitter, repeated-click, selection, + prompt-lifecycle, shell, and VT mouse validation gate. +3. Commit the focused 1.4.3 source/docs change, publish the matching Wiki + ledger entry, push the branch, and merge through the application pull + request only after it is genuinely release-ready. +4. Synchronize `main`, create annotated tag `v1.4.3` on the exact merged commit, + push only that tag, and monitor the formal Release workflow to a terminal + result. +5. Verify GitHub Latest and every public asset and checksum, then update + `winterm-site` from the real Release URL, `published_at`, asset URLs, and + filenames. Publish and verify English/Japanese production parity. diff --git a/docs/releases/1.4.3.md b/docs/releases/1.4.3.md new file mode 100644 index 000000000..ffcd5481d --- /dev/null +++ b/docs/releases/1.4.3.md @@ -0,0 +1,80 @@ +# winTerm 1.4.3 + +**winTerm 1.4.3 is a stable production hotfix.** GitHub Latest points to +`v1.4.3`; there is no alpha, beta, preview, or prerelease suffix in the +application, package, PowerShell module, or Release metadata. + +This patch fixes a Click to position cursor regression present in the 1.4.1 +application payload and unchanged in 1.4.2. A normal click could work only +intermittently, and one failed gesture could make later clicks stop moving the +cursor. + +## Click-position reliability fix + +A plain single left click is allowed a small amount of normal physical mouse +movement between button press and release. Movement below the existing +drag-selection threshold remains a click, does not create or modify a text +selection, and does not become eligible for CopyOnSelect. + +The regression occurred because every pointer-move event extended the +selection endpoint even before a drag existed. The terminal Core correctly +ignored that request when there was no active selection, but the Interactivity +layer still marked selection-copy state as dirty. Release-time cursor +positioning then treated that unrelated state as proof that the gesture was +not a click, and the stale value could persist into later gestures. + +winTerm 1.4.3 separates the two responsibilities: + +- cursor-reposition pending state decides whether the current gesture still + qualifies as a plain click; +- selection-copy state becomes dirty only when a real selection is active and + was updated; +- crossing the existing drag threshold establishes the selection anchor once, + updates the selection end, and transfers ownership to selection; +- release-time cursor positioning no longer uses selection-copy state as its + primary click test, and a no-selection release normalizes stale copy state. + +Existing interaction precedence is unchanged: Ctrl+Click hyperlinks, VT mouse +reporting, double-click word selection, triple-click line selection, +Shift+Click, and drag selection all retain ownership ahead of a plain click. +The coordinate, padding, buffer-bound, historical-output, editable-mark, +full-width-glyph, and split-pane protections from 1.4.1 and 1.4.2 remain in +place. + +## Compatibility and limitations + +Click positioning still requires shell integration to identify the current, +unfinished editable command. Previous commands, completed output, unrelated +scrollback, malformed coordinates, and positions outside the trustworthy +editable range remain safe no-ops. Mouse-aware applications such as Vim, +Less, top, htop, k9s, and tmux keep mouse ownership while VT mouse reporting +is active. + +## Downloads + +- `winTerm-1.4.3-setup-x64.exe` — current-user or all-users installation. +- `winTerm-1.4.3-portable-x64.zip` — extract and run without installation; + `portable.marker` keeps data beside the executable. +- `SHA256SUMS.txt` — SHA-256 checksums for the application downloads and every + other published release artifact. +- `THIRD_PARTY_NOTICES.md` — dependency and attribution notices. +- `SBOM.spdx.json` and `SBOM.cyclonedx.json` — software bills of materials. +- `release-metadata.json` — immutable build and source provenance. +- `winTerm-1.4.3-release-notes.md` — the packaged copy of these notes. + +Download assets only from the official `v1.4.3` GitHub Release. Verify the +Setup EXE and Portable ZIP against `SHA256SUMS.txt` from that same Release +before running them. Upgrading keeps settings, themes, workspaces, and +snapshots under `%LOCALAPPDATA%\winTerm`, or under the adjacent `data` +directory in portable mode. + +## Signing + +The installer is **not Authenticode-signed**. Windows may display Unknown +Publisher or a Microsoft Defender SmartScreen warning. Download only from the +official GitHub Release and verify `SHA256SUMS.txt` from that same Release +before running the installer. + +Requires Windows 11 x64. winTerm is an independent open-source project based +on Microsoft Terminal source code; it is not a Microsoft product and is not +affiliated with or endorsed by Microsoft. diff --git a/scripts/winterm/package-shell-assets.ps1 b/scripts/winterm/package-shell-assets.ps1 index a6afb5f2d..bb99d44cb 100644 --- a/scripts/winterm/package-shell-assets.ps1 +++ b/scripts/winterm/package-shell-assets.ps1 @@ -32,9 +32,9 @@ foreach ($relativePath in $sourceAssets) } $version = Get-Content -LiteralPath (Join-Path $repositoryRoot 'shell\shared\version.json') -Raw | ConvertFrom-Json -if ($version.moduleVersion -ne '1.4.2' -or +if ($version.moduleVersion -ne '1.4.3' -or $version.modulePrerelease -ne '' -or - $version.applicationVersion -ne '1.4.2' -or + $version.applicationVersion -ne '1.4.3' -or $version.protocolVersion -ne 1) { throw 'The winTerm Shell asset version metadata is invalid.' diff --git a/scripts/winterm/test-visual-progress.ps1 b/scripts/winterm/test-visual-progress.ps1 index 559414c43..8af7eae81 100644 --- a/scripts/winterm/test-visual-progress.ps1 +++ b/scripts/winterm/test-visual-progress.ps1 @@ -1411,10 +1411,10 @@ try Assert-Matches $releaseNotes $requiredPattern 'winTerm 1.2.0 Visual Progress release notes' } Assert-Matches $source.Changelog '(?m)^##\s+.*1\.2\.0' 'Changelog 1.2.0 entry' - Assert-Matches $source.CurrentProgress '(?i)1\.4\.2' 'Current progress v1.4.2 milestone' + Assert-Matches $source.CurrentProgress '(?i)1\.4\.3' 'Current progress v1.4.3 milestone' Assert-Matches $source.CurrentProgress '(?i)Visual Progress' 'Current progress Visual Progress coverage' Assert-Contains $source.Readme '/releases/latest' 'Stable latest-release README download route' - Assert-Matches $source.Readme '(?i)1\.4\.2' 'README v1.4.2 surface' + Assert-Matches $source.Readme '(?i)1\.4\.3' 'README v1.4.3 surface' foreach ($requiredPattern in @( '(?is)recognition.*runs locally|locally.*recognition', '(?is)bounded.*newly\s+arriving\s+output|newly\s+arriving.*bounded', @@ -1432,12 +1432,12 @@ try $version = $source.VersionMetadata | ConvertFrom-Json $expectedVersionValues = [ordered]@{ - applicationVersion = '1.4.2' - packageVersion = '1.4.2.0' - moduleVersion = '1.4.2' + applicationVersion = '1.4.3' + packageVersion = '1.4.3.0' + moduleVersion = '1.4.3' modulePrerelease = '' channel = 'stable' - tag = 'v1.4.2' + tag = 'v1.4.3' workspaceSchemaVersion = 2 dockingModelVersion = 1 shellProtocolVersion = 1 @@ -1452,39 +1452,39 @@ try } } $shellVersion = $source.ShellVersion | ConvertFrom-Json - if ($shellVersion.applicationVersion -ne '1.4.2' -or $shellVersion.moduleVersion -ne '1.4.2' -or $shellVersion.protocolVersion -ne 1) + if ($shellVersion.applicationVersion -ne '1.4.3' -or $shellVersion.moduleVersion -ne '1.4.3' -or $shellVersion.protocolVersion -ne 1) { - throw 'Shell version metadata does not match winTerm version 1.4.2 with protocol version 1.' + throw 'Shell version metadata does not match winTerm version 1.4.3 with protocol version 1.' } foreach ($surface in @( - @{ Content = $source.ReleaseMetadata; Value = 'ApplicationVersion{ L"1.4.2" }'; Description = 'About release metadata' }, - @{ Content = $source.PackageManifest; Value = 'Version="1.4.2.0"'; Description = 'MSIX package manifest' }, - @{ Content = $source.HostResource; Value = 'FILEVERSION 1,4,2,0'; Description = 'Terminal host file version' }, - @{ Content = $source.HostResource; Value = '"ProductVersion", "1.4.2\0"'; Description = 'Terminal host display version' }, - @{ Content = $source.ShimResource; Value = 'FILEVERSION 1,4,2,0'; Description = 'Shim file version' }, - @{ Content = $source.ShimResource; Value = '"ProductVersion", "1.4.2\0"'; Description = 'Shim display version' }, + @{ Content = $source.ReleaseMetadata; Value = 'ApplicationVersion{ L"1.4.3" }'; Description = 'About release metadata' }, + @{ Content = $source.PackageManifest; Value = 'Version="1.4.3.0"'; Description = 'MSIX package manifest' }, + @{ Content = $source.HostResource; Value = 'FILEVERSION 1,4,3,0'; Description = 'Terminal host file version' }, + @{ Content = $source.HostResource; Value = '"ProductVersion", "1.4.3\0"'; Description = 'Terminal host display version' }, + @{ Content = $source.ShimResource; Value = 'FILEVERSION 1,4,3,0'; Description = 'Shim file version' }, + @{ Content = $source.ShimResource; Value = '"ProductVersion", "1.4.3\0"'; Description = 'Shim display version' }, @{ Content = $source.CustomProps; Value = '1'; Description = 'Executable major version' }, @{ Content = $source.CustomProps; Value = '4'; Description = 'Executable minor version' }, - @{ Content = $source.ShellModuleManifest; Value = "ModuleVersion = '1.4.2'"; Description = 'PowerShell module manifest' }, - @{ Content = $source.ShellModule; Value = "`$script:WinTermModuleVersion = '1.4.2'"; Description = 'PowerShell module runtime' }, + @{ Content = $source.ShellModuleManifest; Value = "ModuleVersion = '1.4.3'"; Description = 'PowerShell module manifest' }, + @{ Content = $source.ShellModule; Value = "`$script:WinTermModuleVersion = '1.4.3'"; Description = 'PowerShell module runtime' }, @{ Content = $source.PackageShellAssets; Value = "'shell\shared\version.json'"; Description = 'Canonical shell version metadata packaging' }, - @{ Content = $source.WorkspaceSerializer; Value = '"1.4.2"'; Description = 'Workspace application-version fallback' } + @{ Content = $source.WorkspaceSerializer; Value = '"1.4.3"'; Description = 'Workspace application-version fallback' } )) { Assert-Contains $surface.Content $surface.Value $surface.Description } foreach ($required in @( - "applicationVersion -eq '1.4.2'", - "packageVersion -eq '1.4.2.0'", - "moduleVersion -eq '1.4.2'", - "tag -eq 'v1.4.2'", + "applicationVersion -eq '1.4.3'", + "packageVersion -eq '1.4.3.0'", + "moduleVersion -eq '1.4.3'", + "tag -eq 'v1.4.3'", "Workspace Schema version remains 2", "Docking Model version remains 1", "Shell Protocol version remains 1", "Theme Schema remains at version 1" )) { - Assert-Contains $source.VerifyVersion $required 'Authoritative v1.4.2 version validation surface' + Assert-Contains $source.VerifyVersion $required 'Authoritative v1.4.3 version validation surface' } $testBinary = Join-Path $root "bin\$Platform\$Configuration\UnitTests_SettingsModel\SettingsModel.Unit.Tests.dll" diff --git a/scripts/winterm/test.ps1 b/scripts/winterm/test.ps1 index 6f9677891..1abc8b26a 100644 --- a/scripts/winterm/test.ps1 +++ b/scripts/winterm/test.ps1 @@ -292,7 +292,7 @@ function Test-ShellExperienceFoundations } $manifest = Import-PowerShellDataFile -LiteralPath $moduleManifest - if ($manifest.ModuleVersion -ne '1.4.2' -or + if ($manifest.ModuleVersion -ne '1.4.3' -or $manifest.PrivateData.PSData.Prerelease -ne '' -or $manifest.PowerShellVersion -ne '5.1') { diff --git a/scripts/winterm/verify-branding.ps1 b/scripts/winterm/verify-branding.ps1 index 6a2ed2179..b423b6e2e 100644 --- a/scripts/winterm/verify-branding.ps1 +++ b/scripts/winterm/verify-branding.ps1 @@ -126,7 +126,7 @@ function Test-Manifest Test-Requirement -Condition ($null -ne $identity -and $identity.Name -eq 'HelloThisWorld.winTerm') -Message "$Path uses package identity HelloThisWorld.winTerm" Test-Requirement -Condition ($null -ne $identity -and $identity.Name -notmatch '^Microsoft\.') -Message "$Path does not use a Microsoft package name" Test-Requirement -Condition ($null -ne $identity -and $identity.Publisher -ceq $ExpectedPublisher) -Message "$Path uses the expected non-Microsoft publisher" - Test-Requirement -Condition ($null -ne $identity -and $identity.Version -eq '1.4.2.0') -Message "$Path uses package version 1.4.2.0" + Test-Requirement -Condition ($null -ne $identity -and $identity.Version -eq '1.4.3.0') -Message "$Path uses package version 1.4.3.0" Test-Requirement -Condition ($null -ne $properties -and $properties.DisplayName -eq 'winTerm') -Message "$Path package display name is winTerm" Test-Requirement -Condition ($null -ne $application -and $application.Id -eq 'winTerm') -Message "$Path application ID is winTerm" Test-Requirement -Condition ($null -ne $visualElements -and $visualElements.DisplayName -eq 'winTerm') -Message "$Path application display name is winTerm" diff --git a/scripts/winterm/verify-version.ps1 b/scripts/winterm/verify-version.ps1 index a4b7d7060..a941ce7eb 100644 --- a/scripts/winterm/verify-version.ps1 +++ b/scripts/winterm/verify-version.ps1 @@ -49,9 +49,9 @@ try $versionPath = Join-Path $repositoryRoot 'src\winterm\Branding\version.json' $version = Get-Content -LiteralPath $versionPath -Raw | ConvertFrom-Json - Assert-Condition ($version.applicationVersion -eq '1.4.2') 'Application version is 1.4.2' - Assert-Condition ($version.packageVersion -eq '1.4.2.0') 'Package version is 1.4.2.0' - Assert-Condition ($version.moduleVersion -eq '1.4.2') 'PowerShell module version is 1.4.2' + Assert-Condition ($version.applicationVersion -eq '1.4.3') 'Application version is 1.4.3' + Assert-Condition ($version.packageVersion -eq '1.4.3.0') 'Package version is 1.4.3.0' + Assert-Condition ($version.moduleVersion -eq '1.4.3') 'PowerShell module version is 1.4.3' Assert-Condition ($version.modulePrerelease -eq '') 'PowerShell module prerelease suffix is empty for stable' # The release workflow treats any channel other than 'stable' as a @@ -66,7 +66,7 @@ try Assert-Condition ($version.packageVersion -match '^\d+\.\d+\.\d+\.\d+$') 'Package version stays a four-part numeric version' Assert-Condition ($version.moduleVersion -match '^\d+\.\d+\.\d+$') 'PowerShell module version stays numeric' - Assert-Condition ($version.tag -eq 'v1.4.2') 'Stable tag is v1.4.2' + Assert-Condition ($version.tag -eq 'v1.4.3') 'Stable tag is v1.4.3' Assert-Condition ($version.workspaceSchemaVersion -eq 2) 'Workspace Schema version remains 2' Assert-Condition ($version.dockingModelVersion -eq 1) 'Docking Model version remains 1' Assert-Condition ($version.shellProtocolVersion -eq 1) 'Shell Protocol version remains 1' @@ -90,7 +90,7 @@ try $moduleManifest = Import-PowerShellDataFile -LiteralPath (Join-Path $repositoryRoot 'shell\powershell\winTerm.Shell\winTerm.Shell.psd1') Assert-Condition ($moduleManifest.ModuleVersion.ToString() -eq $version.moduleVersion) 'PowerShell manifest version matches release metadata' Assert-Condition ($moduleManifest.PrivateData.PSData.Prerelease -eq $version.modulePrerelease) 'PowerShell manifest prerelease matches release metadata' - Assert-Condition ((Get-Text 'shell\powershell\winTerm.Shell\winTerm.Shell.psm1').Contains("`$script:WinTermModuleVersion = '1.4.2'")) 'PowerShell module runtime version matches release metadata' + Assert-Condition ((Get-Text 'shell\powershell\winTerm.Shell\winTerm.Shell.psm1').Contains("`$script:WinTermModuleVersion = '1.4.3'")) 'PowerShell module runtime version matches release metadata' $shellVersion = Get-Text 'shell\shared\version.json' | ConvertFrom-Json Assert-Condition ($shellVersion.applicationVersion -eq $version.applicationVersion) 'Shell asset application version matches release metadata' @@ -98,7 +98,7 @@ try Assert-Condition ($shellVersion.protocolVersion -eq $version.shellProtocolVersion) 'Shell asset protocol version matches release metadata' $releaseHeader = Get-Text 'src\winterm\Branding\ReleaseMetadata.h' - Assert-Condition ($releaseHeader.Contains('ApplicationVersion{ L"1.4.2" }')) 'About metadata application version is 1.4.2' + Assert-Condition ($releaseHeader.Contains('ApplicationVersion{ L"1.4.3" }')) 'About metadata application version is 1.4.3' Assert-Condition ($releaseHeader.Contains('ReleaseChannel{ L"Stable" }')) 'About metadata channel is Stable' Assert-Condition ($releaseHeader.Contains($version.microsoftTerminalUpstreamRevision)) 'About metadata contains the Microsoft Terminal upstream revision' Assert-Condition ($releaseHeader.Contains('WorkspaceSchemaVersion{ 2 }')) 'About metadata contains Workspace Schema version 2' @@ -129,10 +129,10 @@ try Assert-Condition ((Get-Text 'src\winterm\Workspaces\Model\WorkspaceDescriptor.h').Contains('WorkspaceSchemaVersion{ 2 }')) 'Workspace model remains at Schema version 2' Assert-Condition ((Get-Text 'src\winterm\Workspaces\Model\WorkspaceDescriptor.h').Contains('DockingModelVersion{ 1 }')) 'Workspace model remains at Docking version 1' - Assert-Condition ((Get-Text 'src\winterm\Workspaces\Model\WorkspaceDescriptor.h').Contains('applicationVersion{ "1.4.2" }')) 'Workspace model application-version fallback is 1.4.2' + Assert-Condition ((Get-Text 'src\winterm\Workspaces\Model\WorkspaceDescriptor.h').Contains('applicationVersion{ "1.4.3" }')) 'Workspace model application-version fallback is 1.4.3' Assert-Condition ((Get-Text 'src\winterm\Shell\Protocol\ShellIntegrationProtocol.h').Contains('ShellProtocolVersion{ 1 }')) 'Shell protocol remains at version 1' Assert-Condition ((Get-Text 'src\winterm\Appearance\Themes\ThemeDescriptor.h').Contains('CurrentThemeSchemaVersion{ 1 }')) 'Theme Schema remains at version 1' - Assert-Condition ((Get-Text 'src\winterm\Workspaces\Persistence\WorkspaceSerializer.cpp').Contains('"1.4.2"')) 'Workspace serializer application-version fallback is 1.4.2' + Assert-Condition ((Get-Text 'src\winterm\Workspaces\Persistence\WorkspaceSerializer.cpp').Contains('"1.4.3"')) 'Workspace serializer application-version fallback is 1.4.3' $releaseWorkflow = Get-Text '.github\workflows\release.yml' Assert-Condition ($releaseWorkflow.Contains("- 'v*'")) 'Release workflow accepts version tags through a generic guarded trigger' @@ -141,9 +141,9 @@ try Assert-Condition ($releaseWorkflow.Contains("`$expectedTag = `"v`$(`$metadata.applicationVersion)`"")) 'Release workflow derives the expected tag from version.json' Assert-Condition ($releaseWorkflow.Contains("`$metadata.tag -cne `$expectedTag")) 'Release workflow rejects a version metadata tag mismatch' - Assert-Condition ((Get-Text 'CHANGELOG.md').Contains('## 1.4.2 - 2026-08-25')) 'Changelog contains the 1.4.2 stable entry' + Assert-Condition ((Get-Text 'CHANGELOG.md').Contains('## 1.4.3 - 2026-08-27')) 'Changelog contains the 1.4.3 stable entry' Assert-Condition ((Get-Text 'README.md').Contains("current source version is ``$($version.applicationVersion)``")) 'README source version matches release metadata' - Assert-Condition ((Get-Text 'README.md').Contains('latest stable release is `1.4.2`')) 'README stable pointer is 1.4.2' + Assert-Condition ((Get-Text 'README.md').Contains('latest stable release is `1.4.3`')) 'README stable pointer is 1.4.3' # The Japanese README is a maintained counterpart, not a marketing summary: # both files must link to each other, the translation must point at the @@ -162,7 +162,7 @@ try Assert-Condition ($readmeJa.Contains('[English](README.md)')) 'Japanese README links back to the English README' Assert-Condition ($readmeJa.Contains('https://winterm.dev/ja/')) 'Japanese README links to the Japanese website' Assert-Condition ($readmeJa.Contains("``$($version.applicationVersion)``")) 'Japanese README source version matches release metadata' - Assert-Condition ($readmeJa.Contains('`1.4.2`')) 'Japanese README stable pointer is 1.4.2' + Assert-Condition ($readmeJa.Contains('`1.4.3`')) 'Japanese README stable pointer is 1.4.3' Assert-Condition ($readmeJa.Contains('winTerm--setup-x64.exe')) 'Japanese README retains the installer asset pattern' Assert-Condition ($readmeJa.Contains('winTerm--portable-x64.zip')) 'Japanese README retains the portable asset pattern' Assert-Condition ($readmeJa.Contains('SHA256SUMS.txt')) 'Japanese README retains the checksum filename' @@ -187,7 +187,7 @@ try if ($RequireTag) { $tag = (& git describe --tags --exact-match 2>$null).Trim() - Assert-Condition ($LASTEXITCODE -eq 0 -and $tag -eq $version.tag) 'Checked-out commit is exactly tagged v1.4.2' + Assert-Condition ($LASTEXITCODE -eq 0 -and $tag -eq $version.tag) 'Checked-out commit is exactly tagged v1.4.3' } Write-Host 'winTerm version consistency verification passed.' -ForegroundColor Green diff --git a/shell/powershell/winTerm.Shell/winTerm.Shell.psd1 b/shell/powershell/winTerm.Shell/winTerm.Shell.psd1 index 5b1e4a033..dec5724e4 100644 --- a/shell/powershell/winTerm.Shell/winTerm.Shell.psd1 +++ b/shell/powershell/winTerm.Shell/winTerm.Shell.psd1 @@ -1,6 +1,6 @@ @{ RootModule = 'winTerm.Shell.psm1' - ModuleVersion = '1.4.2' + ModuleVersion = '1.4.3' GUID = 'f65cd8f4-5d25-4a2a-a0d4-58df1ab3dc5a' Author = 'winTerm contributors' CompanyName = 'winTerm' diff --git a/shell/powershell/winTerm.Shell/winTerm.Shell.psm1 b/shell/powershell/winTerm.Shell/winTerm.Shell.psm1 index 43bc977f0..53460e771 100644 --- a/shell/powershell/winTerm.Shell/winTerm.Shell.psm1 +++ b/shell/powershell/winTerm.Shell/winTerm.Shell.psm1 @@ -3,7 +3,7 @@ Set-StrictMode -Version Latest -$script:WinTermModuleVersion = '1.4.2' +$script:WinTermModuleVersion = '1.4.3' $script:WinTermProtocolVersion = 1 $script:WinTermIntegrationEnabled = $false $script:WinTermPromptWrapped = $false diff --git a/shell/shared/version.json b/shell/shared/version.json index 7acd4496a..1b4297c57 100644 --- a/shell/shared/version.json +++ b/shell/shared/version.json @@ -1,6 +1,6 @@ { - "applicationVersion": "1.4.2", - "moduleVersion": "1.4.2", + "applicationVersion": "1.4.3", + "moduleVersion": "1.4.3", "modulePrerelease": "", "protocolVersion": 1 } diff --git a/src/cascadia/CascadiaPackage/Package-winTerm.appxmanifest b/src/cascadia/CascadiaPackage/Package-winTerm.appxmanifest index 0e8a2be4d..6341d135f 100644 --- a/src/cascadia/CascadiaPackage/Package-winTerm.appxmanifest +++ b/src/cascadia/CascadiaPackage/Package-winTerm.appxmanifest @@ -18,7 +18,7 @@ + Version="1.4.3.0" /> winTerm diff --git a/src/cascadia/TerminalControl/ControlCore.cpp b/src/cascadia/TerminalControl/ControlCore.cpp index 7b1508cf1..298749af9 100644 --- a/src/cascadia/TerminalControl/ControlCore.cpp +++ b/src/cascadia/TerminalControl/ControlCore.cpp @@ -1425,16 +1425,18 @@ namespace winrt::Microsoft::Terminal::Control::implementation // Method Description: // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. - // Arguments: - // - position: the point in terminal coordinates (in cells, not pixels) - void ControlCore::SetEndSelectionPoint(const til::point position) - { - const auto lock = _terminal->LockForWriting(); - - if (!_terminal->IsSelectionActive()) - { - return; - } + // Arguments: + // - position: the point in terminal coordinates (in cells, not pixels) + // Return Value: + // - true if an active selection was updated; false if no selection exists + bool ControlCore::SetEndSelectionPoint(const til::point position) + { + const auto lock = _terminal->LockForWriting(); + + if (!_terminal->IsSelectionActive()) + { + return false; + } // clamp the converted position to be within the viewport bounds // x: allow range of [0, RightExclusive] @@ -1444,10 +1446,11 @@ namespace winrt::Microsoft::Terminal::Control::implementation std::clamp(position.y, 0, _terminal->GetViewport().Height() - 1) }; - // save location (for rendering) + render - _terminal->SetSelectionEnd(terminalPosition); - _updateSelectionUI(); - } + // save location (for rendering) + render + _terminal->SetSelectionEnd(terminalPosition); + _updateSelectionUI(); + return true; + } // Method Description: // - Given a copy-able selection, get the selected text from the buffer and send it to the diff --git a/src/cascadia/TerminalControl/ControlCore.h b/src/cascadia/TerminalControl/ControlCore.h index fbd258a93..24abcbae0 100644 --- a/src/cascadia/TerminalControl/ControlCore.h +++ b/src/cascadia/TerminalControl/ControlCore.h @@ -251,7 +251,7 @@ namespace winrt::Microsoft::Terminal::Control::implementation bool CopyOnSelect() const; Control::SelectionData SelectionInfo() const; void SetSelectionAnchor(const til::point position); - void SetEndSelectionPoint(const til::point position); + bool SetEndSelectionPoint(const til::point position); SearchResults Search(const SearchRequest& request); const std::vector& SearchResultRows() const noexcept; diff --git a/src/cascadia/TerminalControl/ControlInteractivity.cpp b/src/cascadia/TerminalControl/ControlInteractivity.cpp index 2b9be4047..eac790cb0 100644 --- a/src/cascadia/TerminalControl/ControlInteractivity.cpp +++ b/src/cascadia/TerminalControl/ControlInteractivity.cpp @@ -384,11 +384,12 @@ namespace winrt::Microsoft::Terminal::Control::implementation // GH#4603 - don't modify the selection if the pointer press didn't // actually start _in_ the control bounds. Case in point - someone drags // a file into the bounds of the control. That shouldn't send the - // selection into space. - else if (focused && pointerPressedInBounds && WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown)) - { - if (_singleClickTouchdownPos) - { + // selection into space. + else if (focused && pointerPressedInBounds && WI_IsFlagSet(buttonState, MouseButtonState::IsLeftButtonDown)) + { + auto updateSelectionEnd = !_singleClickTouchdownPos; + if (_singleClickTouchdownPos) + { // Figure out if the user's moved a 1/4th of a cell's smaller axis // (practically always the width) away from the clickdown point. const auto fontSizeInDips = _core->FontSizeInDips(); @@ -423,12 +424,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation } _core->SetSelectionAnchor(termPos); - // stop tracking the touchdown point - _singleClickTouchdownPos = std::nullopt; - } - } - - SetEndSelectionPoint(pixelPosition); + // stop tracking the touchdown point + _singleClickTouchdownPos = std::nullopt; + updateSelectionEnd = true; + } + } + + // Normal physical mouse jitter must not turn a click into a + // selection gesture. Before the drag threshold is crossed there + // is no selection to extend and selection-copy state must remain + // untouched. Once the drag owns the gesture, subsequent moves + // continue updating the existing selection end. + if (updateSelectionEnd) + { + SetEndSelectionPoint(pixelPosition); + } } _core->SetHoveredCell(terminalPosition.to_core_point()); @@ -488,11 +498,21 @@ namespace winrt::Microsoft::Terminal::Control::implementation } // Only a left click release when copy on select is active should perform a copy. - // Right clicks and middle clicks should not need to do anything when released. - const auto isLeftMouseRelease = pointerUpdateKind == WM_LBUTTONUP; - + // Right clicks and middle clicks should not need to do anything when released. + const auto isLeftMouseRelease = pointerUpdateKind == WM_LBUTTONUP; + const auto hasSelection = _core->HasSelection(); + + // A copy candidate without a real selection is stale by definition. + // Normalize it here without disturbing legitimate mark-mode or + // CopyOnSelect state while a selection remains active. + if (!hasSelection) + { + _selectionNeedsToBeCopied = false; + } + if (_core->CopyOnSelect() && isLeftMouseRelease && + hasSelection && _selectionNeedsToBeCopied) { // IMPORTANT! @@ -503,7 +523,6 @@ namespace winrt::Microsoft::Terminal::Control::implementation if (isLeftMouseRelease && repositionPending && - !_selectionNeedsToBeCopied && !modifiers.IsAltPressed() && !modifiers.IsShiftPressed() && !modifiers.IsCtrlPressed()) @@ -728,13 +747,19 @@ namespace winrt::Microsoft::Terminal::Control::implementation // - Sets selection's end position to match supplied cursor position, e.g. while mouse dragging. // Arguments: // - cursorPosition: in pixels, relative to the origin of the control - void ControlInteractivity::SetEndSelectionPoint(const Core::Point pixelPosition) - { - // Don't round in VT mouse mode; cell-level precision matters more - const auto round = !_core->IsVtMouseModeEnabled(); - _core->SetEndSelectionPoint(_getTerminalPosition(til::point{ pixelPosition }, round)); - _selectionNeedsToBeCopied = true; - } + void ControlInteractivity::SetEndSelectionPoint(const Core::Point pixelPosition) + { + // Don't round in VT mouse mode; cell-level precision matters more + const auto round = !_core->IsVtMouseModeEnabled(); + if (_core->SetEndSelectionPoint(_getTerminalPosition(til::point{ pixelPosition }, round))) + { + _selectionNeedsToBeCopied = true; + } + else + { + _selectionNeedsToBeCopied = false; + } + } // Method Description: // - Gets the corresponding viewport terminal position for the point in diff --git a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp index 8ea34c02d..58909f660 100644 --- a/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp +++ b/src/cascadia/UnitTests_Control/ControlInteractivityTests.cpp @@ -44,6 +44,13 @@ namespace ControlUnitTests TEST_METHOD(AltBufferClampMouse); TEST_METHOD(RightClickCopiesSelectionThenPastes); TEST_METHOD(CursorRepositionOccursOnReleaseOnly); + TEST_METHOD(CursorRepositionSurvivesSubThresholdMovement); + TEST_METHOD(CursorRepositionSurvivesSeveralSubThresholdMovements); + TEST_METHOD(CursorRepositionSurvivesRepeatedClicks); + TEST_METHOD(CursorRepositionGestureCannotPoisonNextClick); + TEST_METHOD(CursorRepositionHonorsDragThresholdBoundary); + TEST_METHOD(CursorRepositionCopyOnSelectOwnsOnlyRealSelections); + TEST_METHOD(CursorRepositionRecoversFromStaleCopyState); TEST_METHOD(CursorRepositionDragAndSelectionPriority); TEST_CLASS_SETUP(ClassSetup) @@ -1114,6 +1121,273 @@ namespace ControlUnitTests VERIFY_IS_FALSE(interactivity->_cursorRepositionPending); } + void ControlInteractivityTests::CursorRepositionSurvivesSubThresholdMovement() + { + auto [settings, conn] = _createSettingsAndConnection(); + settings->RepositionCursorWithMouse(true); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); + conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\aPS> \x1b]133;B\aabcdef")); + + std::wstring sent; + conn->TerminalOutput([&](const winrt::array_view value) { + sent.append(winrt_array_to_wstring_view(value)); + }); + + const auto font = core->FontSizeInDips(); + const Core::Point click{ static_cast(font.Width * 5.5f), static_cast(font.Height * 0.5f) }; + const Core::Point jitter{ click.X + 1, click.Y }; + const auto modifiers = ControlKeyStates{}; + const auto leftMouseDown = Control::MouseButtonState::IsLeftButtonDown; + const Control::MouseButtonState noMouseDown{}; + + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, 1, modifiers, click); + interactivity->PointerMoved(leftMouseDown, WM_MOUSEMOVE, modifiers, true, jitter, true); + VERIFY_IS_FALSE(core->HasSelection(), L"Sub-threshold movement must not create a selection"); + VERIFY_IS_TRUE(interactivity->_cursorRepositionPending, L"Sub-threshold movement must remain a click"); + VERIFY_IS_FALSE(interactivity->_selectionNeedsToBeCopied, L"Sub-threshold movement must not create a phantom copy candidate"); + + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, jitter); + VERIFY_ARE_EQUAL(std::wstring{ L"\x1b[D\x1b[D\x1b[D\x1b[D" }, sent); + VERIFY_IS_FALSE(interactivity->_cursorRepositionPending); + VERIFY_IS_FALSE(interactivity->_selectionNeedsToBeCopied); + } + + void ControlInteractivityTests::CursorRepositionSurvivesSeveralSubThresholdMovements() + { + auto [settings, conn] = _createSettingsAndConnection(); + settings->RepositionCursorWithMouse(true); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); + conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\aPS> \x1b]133;B\aabcdef")); + + std::wstring sent; + conn->TerminalOutput([&](const winrt::array_view value) { + sent.append(winrt_array_to_wstring_view(value)); + }); + + const auto font = core->FontSizeInDips(); + const Core::Point click{ static_cast(font.Width * 5.5f), static_cast(font.Height * 0.5f) }; + const std::array jitter{ + Core::Point{ click.X + 1, click.Y }, + Core::Point{ click.X - 1, click.Y }, + Core::Point{ click.X + 1, click.Y }, + }; + const auto modifiers = ControlKeyStates{}; + const auto leftMouseDown = Control::MouseButtonState::IsLeftButtonDown; + const Control::MouseButtonState noMouseDown{}; + + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, 1, modifiers, click); + for (const auto& position : jitter) + { + interactivity->PointerMoved(leftMouseDown, WM_MOUSEMOVE, modifiers, true, position, true); + VERIFY_IS_FALSE(core->HasSelection()); + VERIFY_IS_TRUE(interactivity->_cursorRepositionPending); + VERIFY_IS_FALSE(interactivity->_selectionNeedsToBeCopied); + } + + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, jitter.back()); + VERIFY_ARE_EQUAL(std::wstring{ L"\x1b[D\x1b[D\x1b[D\x1b[D" }, sent); + VERIFY_IS_FALSE(core->HasSelection()); + } + + void ControlInteractivityTests::CursorRepositionSurvivesRepeatedClicks() + { + auto [settings, conn] = _createSettingsAndConnection(); + settings->RepositionCursorWithMouse(true); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); + conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\aPS> \x1b]133;B\aabcdefghijklmnopqrst")); + + std::wstring sent; + conn->TerminalOutput([&](const winrt::array_view value) { + sent.append(winrt_array_to_wstring_view(value)); + }); + + const auto expectedMove = [](const int32_t from, const int32_t to) { + std::wstring expected; + const auto sequence = to < from ? L"\x1b[D" : L"\x1b[C"; + for (auto i = 0; i < std::abs(to - from); ++i) + { + expected.append(sequence); + } + return expected; + }; + const auto font = core->FontSizeInDips(); + const auto modifiers = ControlKeyStates{}; + const auto leftMouseDown = Control::MouseButtonState::IsLeftButtonDown; + const Control::MouseButtonState noMouseDown{}; + uint64_t timestamp = 1; + + for (int32_t target = 0; target < 10; ++target) + { + const Core::Point click{ static_cast(font.Width * (target + 4.5f)), static_cast(font.Height * 0.5f) }; + const auto cursorBefore = core->CursorPosition().X; + const auto terminalTarget = interactivity->_getTerminalPosition(til::point{ click }, true).x; + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, timestamp, modifiers, click); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, click); + + VERIFY_ARE_EQUAL(expectedMove(cursorBefore, terminalTarget), sent, L"Every independent click must emit the correct cursor input"); + VERIFY_IS_FALSE(core->HasSelection()); + VERIFY_IS_FALSE(interactivity->_cursorRepositionPending); + VERIFY_IS_FALSE(interactivity->_selectionNeedsToBeCopied); + + sent.clear(); + timestamp += interactivity->_multiClickTimer + 10; + } + } + + void ControlInteractivityTests::CursorRepositionGestureCannotPoisonNextClick() + { + auto [settings, conn] = _createSettingsAndConnection(); + settings->RepositionCursorWithMouse(true); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); + conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\aPS> \x1b]133;B\aabcdef")); + + std::wstring sent; + conn->TerminalOutput([&](const winrt::array_view value) { + sent.append(winrt_array_to_wstring_view(value)); + }); + + const auto font = core->FontSizeInDips(); + const Core::Point first{ static_cast(font.Width * 5.5f), static_cast(font.Height * 0.5f) }; + const Core::Point second{ static_cast(font.Width * 6.5f), static_cast(font.Height * 0.5f) }; + const auto modifiers = ControlKeyStates{}; + const auto leftMouseDown = Control::MouseButtonState::IsLeftButtonDown; + const Control::MouseButtonState noMouseDown{}; + + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, 1, modifiers, first); + interactivity->PointerMoved(leftMouseDown, WM_MOUSEMOVE, modifiers, true, Core::Point{ first.X + 1, first.Y }, true); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, first); + VERIFY_ARE_EQUAL(std::wstring{ L"\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D" }, sent); + + sent.clear(); + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, interactivity->_multiClickTimer + 10, modifiers, second); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, second); + VERIFY_ARE_EQUAL(std::wstring{ L"\x1b[C" }, sent, L"A jittered gesture must not poison the next click"); + VERIFY_IS_FALSE(core->HasSelection()); + VERIFY_IS_FALSE(interactivity->_selectionNeedsToBeCopied); + } + + void ControlInteractivityTests::CursorRepositionHonorsDragThresholdBoundary() + { + auto [settings, conn] = _createSettingsAndConnection(); + settings->RepositionCursorWithMouse(true); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); + conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\aPS> \x1b]133;B\aabcdef")); + + std::wstring sent; + conn->TerminalOutput([&](const winrt::array_view value) { + sent.append(winrt_array_to_wstring_view(value)); + }); + + const auto font = core->FontSizeInDips(); + const auto maxDistanceSquared = font.Width * font.Width / 16.0f; + int32_t boundaryDelta = 1; + while (static_cast(boundaryDelta * boundaryDelta) < maxDistanceSquared) + { + ++boundaryDelta; + } + const auto belowDelta = boundaryDelta - 1; + VERIFY_IS_TRUE(static_cast(belowDelta * belowDelta) < maxDistanceSquared); + VERIFY_IS_TRUE(static_cast(boundaryDelta * boundaryDelta) >= maxDistanceSquared); + + const Core::Point start{ static_cast(font.Width * 5.5f), static_cast(font.Height * 0.5f) }; + const auto modifiers = ControlKeyStates{}; + const auto leftMouseDown = Control::MouseButtonState::IsLeftButtonDown; + const Control::MouseButtonState noMouseDown{}; + + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, 1, modifiers, start); + interactivity->PointerMoved(leftMouseDown, WM_MOUSEMOVE, modifiers, true, Core::Point{ start.X + belowDelta, start.Y }, true); + VERIFY_IS_FALSE(core->HasSelection(), L"distanceSquared below the threshold remains a click"); + VERIFY_IS_TRUE(interactivity->_cursorRepositionPending); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, start); + VERIFY_IS_FALSE(sent.empty()); + + sent.clear(); + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, interactivity->_multiClickTimer + 10, modifiers, start); + interactivity->PointerMoved(leftMouseDown, WM_MOUSEMOVE, modifiers, true, Core::Point{ start.X + boundaryDelta, start.Y }, true); + VERIFY_IS_TRUE(core->HasSelection(), L"distanceSquared at the threshold starts selection"); + VERIFY_IS_FALSE(interactivity->_cursorRepositionPending); + VERIFY_IS_TRUE(interactivity->_selectionNeedsToBeCopied); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, start); + VERIFY_IS_TRUE(sent.empty(), L"A threshold-crossing selection must not reposition the cursor"); + } + + void ControlInteractivityTests::CursorRepositionCopyOnSelectOwnsOnlyRealSelections() + { + auto [settings, conn] = _createSettingsAndConnection(); + settings->RepositionCursorWithMouse(true); + settings->CopyOnSelect(true); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); + conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\aPS> \x1b]133;B\aabcdef")); + + size_t copyCount = 0; + core->WriteToClipboard([&](auto&&, auto&&) { + ++copyCount; + }); + + std::wstring sent; + conn->TerminalOutput([&](const winrt::array_view value) { + sent.append(winrt_array_to_wstring_view(value)); + }); + + const auto font = core->FontSizeInDips(); + const Core::Point start{ static_cast(font.Width * 5.5f), static_cast(font.Height * 0.5f) }; + const Core::Point dragEnd{ static_cast(font.Width * 9.5f), start.Y }; + const auto modifiers = ControlKeyStates{}; + const auto leftMouseDown = Control::MouseButtonState::IsLeftButtonDown; + const Control::MouseButtonState noMouseDown{}; + + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, 1, modifiers, start); + interactivity->PointerMoved(leftMouseDown, WM_MOUSEMOVE, modifiers, true, dragEnd, true); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, dragEnd); + VERIFY_IS_TRUE(core->HasSelection()); + VERIFY_ARE_EQUAL(1u, copyCount, L"CopyOnSelect must copy a real drag selection"); + VERIFY_IS_TRUE(sent.empty()); + + core->ClearSelection(); + const auto nextTimestamp = interactivity->_multiClickTimer + 10; + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, nextTimestamp, modifiers, start); + interactivity->PointerMoved(leftMouseDown, WM_MOUSEMOVE, modifiers, true, Core::Point{ start.X + 1, start.Y }, true); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, start); + VERIFY_ARE_EQUAL(1u, copyCount, L"Sub-threshold jitter must not create a phantom CopyOnSelect candidate"); + VERIFY_IS_FALSE(core->HasSelection()); + VERIFY_IS_FALSE(interactivity->_selectionNeedsToBeCopied); + VERIFY_IS_FALSE(sent.empty(), L"CopyOnSelect must not prevent a real plain click"); + } + + void ControlInteractivityTests::CursorRepositionRecoversFromStaleCopyState() + { + auto [settings, conn] = _createSettingsAndConnection(); + settings->RepositionCursorWithMouse(true); + auto [core, interactivity] = _createCoreAndInteractivity(*settings, *conn); + _standardInit(core, interactivity); + conn->WriteInput(winrt_wstring_to_array_view(L"\x1b]133;A\aPS> \x1b]133;B\aabcdef")); + + std::wstring sent; + conn->TerminalOutput([&](const winrt::array_view value) { + sent.append(winrt_array_to_wstring_view(value)); + }); + + VERIFY_IS_FALSE(core->HasSelection()); + interactivity->_selectionNeedsToBeCopied = true; + + const auto font = core->FontSizeInDips(); + const Core::Point click{ static_cast(font.Width * 5.5f), static_cast(font.Height * 0.5f) }; + const auto modifiers = ControlKeyStates{}; + const auto leftMouseDown = Control::MouseButtonState::IsLeftButtonDown; + const Control::MouseButtonState noMouseDown{}; + + interactivity->PointerPressed(leftMouseDown, WM_LBUTTONDOWN, 1, modifiers, click); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, click); + VERIFY_ARE_EQUAL(std::wstring{ L"\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D" }, sent, L"Stale copy state must not veto a real click"); + VERIFY_IS_FALSE(interactivity->_selectionNeedsToBeCopied, L"No-selection release must normalize stale copy state"); + } + void ControlInteractivityTests::CursorRepositionDragAndSelectionPriority() { auto [settings, conn] = _createSettingsAndConnection(); @@ -1130,6 +1404,7 @@ namespace ControlUnitTests const auto font = core->FontSizeInDips(); const Core::Point start{ static_cast(font.Width * 5.5f), static_cast(font.Height * 0.5f) }; const Core::Point end{ static_cast(font.Width * 8.5f), static_cast(font.Height * 0.5f) }; + const Core::Point fartherEnd{ static_cast(font.Width * 9.5f), static_cast(font.Height * 0.5f) }; const auto modifiers = ControlKeyStates{}; const auto leftMouseDown = Control::MouseButtonState::IsLeftButtonDown; const Control::MouseButtonState noMouseDown{}; @@ -1138,7 +1413,10 @@ namespace ControlUnitTests interactivity->PointerMoved(leftMouseDown, WM_LBUTTONDOWN, modifiers, true, end, true); VERIFY_IS_TRUE(core->HasSelection()); VERIFY_IS_FALSE(interactivity->_cursorRepositionPending); - interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, end); + const auto firstSelectionEnd = core->_terminal->GetSelectionEnd(); + interactivity->PointerMoved(leftMouseDown, WM_MOUSEMOVE, modifiers, true, fartherEnd, true); + VERIFY_ARE_NOT_EQUAL(firstSelectionEnd.x, core->_terminal->GetSelectionEnd().x, L"Selection end must continue updating after the drag starts"); + interactivity->PointerReleased(noMouseDown, WM_LBUTTONUP, modifiers, fartherEnd); VERIFY_IS_TRUE(sent.empty(), L"A drag selection must never move the command-line cursor first"); core->ClearSelection(); diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.rc b/src/cascadia/WindowsTerminal/WindowsTerminal.rc index af8f7886f..91d0e3e0b 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.rc +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.rc @@ -83,8 +83,8 @@ IDI_APPICON_HC_WHITE ICON "..\\..\\..\\res\\terminal\\imag #if defined(WT_BRANDING_WINTERM) 1 VERSIONINFO - FILEVERSION 1,4,2,0 - PRODUCTVERSION 1,4,2,0 + FILEVERSION 1,4,3,0 + PRODUCTVERSION 1,4,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG @@ -101,12 +101,12 @@ BEGIN BEGIN VALUE "CompanyName", "helloThisWorld\0" VALUE "FileDescription", "winTerm Terminal Host\0" - VALUE "FileVersion", "1.4.2.0\0" + VALUE "FileVersion", "1.4.3.0\0" VALUE "InternalName", "WindowsTerminal\0" VALUE "LegalCopyright", "Copyright (c) winTerm contributors. Portions copyright Microsoft Corporation.\0" VALUE "OriginalFilename", "WindowsTerminal.exe\0" VALUE "ProductName", "winTerm\0" - VALUE "ProductVersion", "1.4.2\0" + VALUE "ProductVersion", "1.4.3\0" END END BLOCK "VarFileInfo" diff --git a/src/cascadia/wt/wt.rc b/src/cascadia/wt/wt.rc index f8f1f5c26..78ccacfea 100644 --- a/src/cascadia/wt/wt.rc +++ b/src/cascadia/wt/wt.rc @@ -58,8 +58,8 @@ IDI_APPICON ICON "..\\..\\..\\res\\terminal.ico" #if defined(WT_BRANDING_WINTERM) 1 VERSIONINFO - FILEVERSION 1,4,2,0 - PRODUCTVERSION 1,4,2,0 + FILEVERSION 1,4,3,0 + PRODUCTVERSION 1,4,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG @@ -76,12 +76,12 @@ BEGIN BEGIN VALUE "CompanyName", "helloThisWorld\0" VALUE "FileDescription", "winTerm Launcher\0" - VALUE "FileVersion", "1.4.2.0\0" + VALUE "FileVersion", "1.4.3.0\0" VALUE "InternalName", "winTerm\0" VALUE "LegalCopyright", "Copyright (c) winTerm contributors. Portions copyright Microsoft Corporation.\0" VALUE "OriginalFilename", "winTerm.exe\0" VALUE "ProductName", "winTerm\0" - VALUE "ProductVersion", "1.4.2\0" + VALUE "ProductVersion", "1.4.3\0" END END BLOCK "VarFileInfo" diff --git a/src/winterm-tools/winterm-shim/winterm-shim.rc b/src/winterm-tools/winterm-shim/winterm-shim.rc index 6f0e57f9f..bf7ed5e61 100644 --- a/src/winterm-tools/winterm-shim/winterm-shim.rc +++ b/src/winterm-tools/winterm-shim/winterm-shim.rc @@ -4,8 +4,8 @@ #include 1 VERSIONINFO - FILEVERSION 1,4,2,0 - PRODUCTVERSION 1,4,2,0 + FILEVERSION 1,4,3,0 + PRODUCTVERSION 1,4,3,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS VS_FF_DEBUG @@ -22,12 +22,12 @@ BEGIN BEGIN VALUE "CompanyName", "helloThisWorld\0" VALUE "FileDescription", "winTerm Shell Integration Helper\0" - VALUE "FileVersion", "1.4.2.0\0" + VALUE "FileVersion", "1.4.3.0\0" VALUE "InternalName", "winterm-shim\0" VALUE "LegalCopyright", "Copyright (c) winTerm contributors.\0" VALUE "OriginalFilename", "winterm-shim.exe\0" VALUE "ProductName", "winTerm\0" - VALUE "ProductVersion", "1.4.2\0" + VALUE "ProductVersion", "1.4.3\0" END END BLOCK "VarFileInfo" diff --git a/src/winterm/Branding/ReleaseMetadata.h b/src/winterm/Branding/ReleaseMetadata.h index 459e561f8..864f80279 100644 --- a/src/winterm/Branding/ReleaseMetadata.h +++ b/src/winterm/Branding/ReleaseMetadata.h @@ -25,7 +25,7 @@ namespace winTerm::Branding { inline constexpr std::wstring_view Publisher{ L"helloThisWorld" }; - inline constexpr std::wstring_view ApplicationVersion{ L"1.4.2" }; + inline constexpr std::wstring_view ApplicationVersion{ L"1.4.3" }; inline constexpr std::wstring_view ReleaseChannel{ L"Stable" }; inline constexpr std::wstring_view CommitSha{ WINTERM_BUILD_COMMIT_SHA }; inline constexpr std::wstring_view BuildTimestamp{ WINTERM_BUILD_TIMESTAMP }; diff --git a/src/winterm/Branding/version.json b/src/winterm/Branding/version.json index 018dfbb5b..e451ffe24 100644 --- a/src/winterm/Branding/version.json +++ b/src/winterm/Branding/version.json @@ -1,10 +1,10 @@ { - "applicationVersion": "1.4.2", - "packageVersion": "1.4.2.0", - "moduleVersion": "1.4.2", + "applicationVersion": "1.4.3", + "packageVersion": "1.4.3.0", + "moduleVersion": "1.4.3", "modulePrerelease": "", "channel": "stable", - "tag": "v1.4.2", + "tag": "v1.4.3", "workspaceSchemaVersion": 2, "dockingModelVersion": 1, "shellProtocolVersion": 1, diff --git a/src/winterm/Workspaces/Model/WorkspaceDescriptor.h b/src/winterm/Workspaces/Model/WorkspaceDescriptor.h index e6ab8a1ce..21eb4e3f4 100644 --- a/src/winterm/Workspaces/Model/WorkspaceDescriptor.h +++ b/src/winterm/Workspaces/Model/WorkspaceDescriptor.h @@ -219,7 +219,7 @@ namespace winTerm::Workspaces std::string createdAt; std::string updatedAt; WorkspaceSource source{ WorkspaceSource::User }; - std::string applicationVersion{ "1.4.2" }; + std::string applicationVersion{ "1.4.3" }; uint32_t protocolVersion{ 1 }; uint32_t dockingModelVersion{ DockingModelVersion }; WorkspaceStartupBehavior startupBehavior; diff --git a/src/winterm/Workspaces/Persistence/WorkspaceSerializer.cpp b/src/winterm/Workspaces/Persistence/WorkspaceSerializer.cpp index 67ef76cff..3ef38a502 100644 --- a/src/winterm/Workspaces/Persistence/WorkspaceSerializer.cpp +++ b/src/winterm/Workspaces/Persistence/WorkspaceSerializer.cpp @@ -618,7 +618,7 @@ WorkspaceDescriptor WorkspaceSerializer::FromJson(const Json::Value& json, const throw std::runtime_error("The workspace source is not supported."); } workspace.source = *source; - workspace.applicationVersion = StringOrDefault(json, "applicationVersion", "1.4.2"); + workspace.applicationVersion = StringOrDefault(json, "applicationVersion", "1.4.3"); workspace.protocolVersion = UIntOrDefault(json, "protocolVersion", 1); workspace.dockingModelVersion = UIntOrDefault(json, "dockingModelVersion", DockingModelVersion); if (const auto& startup = json["startupBehavior"]; !startup.isNull())