[PR #3181] [MERGED] Snap to character grid when resizing window #25261

Open
opened 2026-01-31 09:08:22 +00:00 by claunia · 0 comments
Owner

📋 Pull Request Information

Original PR: https://github.com/microsoft/terminal/pull/3181
Author: @mcpiroman
Created: 10/13/2019
Status: Merged
Merged: 1/8/2020
Merged by: @DHowett-MSFT

Base: masterHead: 2834-snap-to-char-grid


📝 Commits (10+)

  • b8a5725 Kinda works, no splitted panes
  • 68f613b Calc sizes more accurately
  • 5d0f1d3 General work, add resolution for children along resize axis
  • 90649b2 Partially fix child displacement
  • cbda911 Change child layout algorithm, now 100% correct
  • d69f8ed Cache padding and scrollbar width, fix infinite loop
  • b732e74 (drastically) optimize layout algorithm ( O(n^m) -> O(n) )
  • 0ecbec5 Fix minimum pane size calculation
  • 3dcd00f Style, comments, format; fix layout just after split
  • 583541d Review changes

📊 Changes

20 files changed (+765 additions, -81 deletions)

View changed files

📝 src/cascadia/TerminalApp/AppLogic.cpp (+7 -0)
📝 src/cascadia/TerminalApp/AppLogic.h (+1 -0)
📝 src/cascadia/TerminalApp/AppLogic.idl (+1 -0)
src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp (+73 -0)
📝 src/cascadia/TerminalApp/Pane.cpp (+369 -55)
📝 src/cascadia/TerminalApp/Pane.h (+52 -5)
📝 src/cascadia/TerminalApp/Tab.cpp (+21 -0)
📝 src/cascadia/TerminalApp/Tab.h (+2 -0)
📝 src/cascadia/TerminalApp/TerminalPage.cpp (+8 -0)
📝 src/cascadia/TerminalApp/TerminalPage.h (+2 -0)
📝 src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj (+1 -0)
📝 src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters (+4 -0)
📝 src/cascadia/TerminalControl/TermControl.cpp (+40 -5)
📝 src/cascadia/TerminalControl/TermControl.h (+4 -2)
📝 src/cascadia/TerminalControl/TermControl.idl (+3 -0)
📝 src/cascadia/WindowsTerminal/AppHost.cpp (+10 -14)
📝 src/cascadia/WindowsTerminal/IslandWindow.cpp (+135 -0)
📝 src/cascadia/WindowsTerminal/IslandWindow.h (+4 -0)
📝 src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp (+26 -0)
📝 src/cascadia/WindowsTerminal/NonClientIslandWindow.h (+2 -0)

📄 Description

When user resizes window, snap the size to align with the character grid (like e.g. putty, mintty and most unix terminals). Properly resolves arbitrary pane configuration (even with different font sizes and padding) trying to align each pane as close as possible.

It also fixes terminal minimum size enforcement which was not quite well handled, especially with multiple panes.

This PR does not however try to keep the terminals aligned at other user actions (e.g. font change or pane split). That is to be tracked by some other activity.

term_snapping

References

#3060 introduces some differences in size calculations by moving from separator to borders, but it should be easy to adopt to that.

PR Checklist

  • Closes #2834, Closes make Windows Terminal available to v1809 (#2277)
  • CLA signed. If not, go over here and sign the CLA
  • Tests added/passed - do we have UI tests yet?
  • Requires documentation to be updated
  • I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

Detailed Description of the Pull Request / Additional comments

Snapping is resolved in the pane tree, recursively, so it (hopefully) works for any possible layout.

Along the way I had to clean up some things as so to make the resulting code not so cumbersome:

  1. Pane.cpp: Replaced _firstPercent and _secondPercent with single _desiredSplitPosition to reduce invariants - these had to be kept in sync so their sum always gives 1 (and were not really a percent). The desired part refers to fact that since panes are aligned, there is usually some deviation from that ratio.
  2. Pane.cpp: Fixed _GetMinSize() - it was improperly accounting for split direction
  3. TerminalControl: Made dedicated member for padding instead of reading it from a control itself. This is because the winrt property functions turned out to be slow and this algorithm needs to access it many times. I also cached scrollbar width for the same reason.
  4. AppHost: Moved window to client size resolution to virtual method, where IslandWinow and NonClientIslandWindow have their own implementations (as opposite to pointer casting).

One problem with current implementation is I had to make a long call chain from the window that requests snapping to the (root) pane that implements it:
IslandWindow -> AppHost's callback -> App -> TerminalPage -> Tab -> Pane
Idk if this can be done better.

Validation Steps Performed

Spam split pane buttons, randomly change font sizes with ctrl+mouse wheel and drag the window back and forth.


🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.

## 📋 Pull Request Information **Original PR:** https://github.com/microsoft/terminal/pull/3181 **Author:** [@mcpiroman](https://github.com/mcpiroman) **Created:** 10/13/2019 **Status:** ✅ Merged **Merged:** 1/8/2020 **Merged by:** [@DHowett-MSFT](https://github.com/DHowett-MSFT) **Base:** `master` ← **Head:** `2834-snap-to-char-grid` --- ### 📝 Commits (10+) - [`b8a5725`](https://github.com/microsoft/terminal/commit/b8a5725a8e8e3bf1b7511f030c334b4ab0a0bb8a) Kinda works, no splitted panes - [`68f613b`](https://github.com/microsoft/terminal/commit/68f613b7c483e65434db5e8f2b61ae77702f95bc) Calc sizes more accurately - [`5d0f1d3`](https://github.com/microsoft/terminal/commit/5d0f1d3eca3bbfbcb52ddc16929769e47e9b2122) General work, add resolution for children along resize axis - [`90649b2`](https://github.com/microsoft/terminal/commit/90649b2bdf18eadef506c28cfec235227128ece3) Partially fix child displacement - [`cbda911`](https://github.com/microsoft/terminal/commit/cbda9118dab9ca1e31ed8ede7d17f3a4dde23104) Change child layout algorithm, now 100% correct - [`d69f8ed`](https://github.com/microsoft/terminal/commit/d69f8ed40310a658e3ca281f723d0eaed625c712) Cache padding and scrollbar width, fix infinite loop - [`b732e74`](https://github.com/microsoft/terminal/commit/b732e745b5afa9510a647948633375eb40797289) (drastically) optimize layout algorithm ( O(n^m) -> O(n) ) - [`0ecbec5`](https://github.com/microsoft/terminal/commit/0ecbec551c12cc8035545aedec37872912704f52) Fix minimum pane size calculation - [`3dcd00f`](https://github.com/microsoft/terminal/commit/3dcd00f2920b4a45e807ea0e2a318578e3a7c4c1) Style, comments, format; fix layout just after split - [`583541d`](https://github.com/microsoft/terminal/commit/583541d976b43546892a3aa912dd3654a2007350) Review changes ### 📊 Changes **20 files changed** (+765 additions, -81 deletions) <details> <summary>View changed files</summary> 📝 `src/cascadia/TerminalApp/AppLogic.cpp` (+7 -0) 📝 `src/cascadia/TerminalApp/AppLogic.h` (+1 -0) 📝 `src/cascadia/TerminalApp/AppLogic.idl` (+1 -0) ➕ `src/cascadia/TerminalApp/Pane.LayoutSizeNode.cpp` (+73 -0) 📝 `src/cascadia/TerminalApp/Pane.cpp` (+369 -55) 📝 `src/cascadia/TerminalApp/Pane.h` (+52 -5) 📝 `src/cascadia/TerminalApp/Tab.cpp` (+21 -0) 📝 `src/cascadia/TerminalApp/Tab.h` (+2 -0) 📝 `src/cascadia/TerminalApp/TerminalPage.cpp` (+8 -0) 📝 `src/cascadia/TerminalApp/TerminalPage.h` (+2 -0) 📝 `src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj` (+1 -0) 📝 `src/cascadia/TerminalApp/lib/TerminalAppLib.vcxproj.filters` (+4 -0) 📝 `src/cascadia/TerminalControl/TermControl.cpp` (+40 -5) 📝 `src/cascadia/TerminalControl/TermControl.h` (+4 -2) 📝 `src/cascadia/TerminalControl/TermControl.idl` (+3 -0) 📝 `src/cascadia/WindowsTerminal/AppHost.cpp` (+10 -14) 📝 `src/cascadia/WindowsTerminal/IslandWindow.cpp` (+135 -0) 📝 `src/cascadia/WindowsTerminal/IslandWindow.h` (+4 -0) 📝 `src/cascadia/WindowsTerminal/NonClientIslandWindow.cpp` (+26 -0) 📝 `src/cascadia/WindowsTerminal/NonClientIslandWindow.h` (+2 -0) </details> ### 📄 Description When user resizes window, snap the size to align with the character grid (like e.g. putty, mintty and most unix terminals). Properly resolves arbitrary pane configuration (even with different font sizes and padding) trying to align each pane as close as possible. It also fixes terminal minimum size enforcement which was not quite well handled, especially with multiple panes. This PR does not however try to keep the terminals aligned at other user actions (e.g. font change or pane split). That is to be tracked by some other activity. ![term_snapping](https://user-images.githubusercontent.com/38111589/66719323-858b2980-edee-11e9-9709-a6e1c5e473d2.gif) ## References #3060 introduces some differences in size calculations by moving from separator to borders, but it should be easy to adopt to that. <!-- Please review the items on the PR checklist before submitting--> ## PR Checklist * [X] Closes #2834, Closes #2277 * [X] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA * [ ] Tests added/passed - do we have UI tests yet? * [ ] Requires documentation to be updated * [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx ## Detailed Description of the Pull Request / Additional comments Snapping is resolved in the pane tree, recursively, so it (hopefully) works for any possible layout. Along the way I had to clean up some things as so to make the resulting code not so cumbersome: 1. `Pane.cpp`: Replaced `_firstPercent` and `_secondPercent` with single `_desiredSplitPosition` to reduce invariants - these had to be kept in sync so their sum always gives 1 (and were not really a percent). The `desired` part refers to fact that since panes are aligned, there is usually some deviation from that ratio. 2. `Pane.cpp`: Fixed `_GetMinSize()` - it was improperly accounting for split direction 3. `TerminalControl`: Made dedicated member for padding instead of reading it from a control itself. This is because the winrt property functions turned out to be slow and this algorithm needs to access it many times. I also cached scrollbar width for the same reason. 4. `AppHost`: Moved window to client size resolution to virtual method, where `IslandWinow` and `NonClientIslandWindow` have their own implementations (as opposite to pointer casting). One problem with current implementation is I had to make a long call chain from the window that requests snapping to the (root) pane that implements it: `IslandWindow` -> `AppHost`'s callback -> `App` -> `TerminalPage` -> `Tab` -> `Pane` Idk if this can be done better. ## Validation Steps Performed Spam split pane buttons, randomly change font sizes with ctrl+mouse wheel and drag the window back and forth. --- <sub>🔄 This issue represents a GitHub Pull Request. It cannot be merged through Gitea due to API limitations.</sub>
claunia added the pull-request label 2026-01-31 09:08:22 +00:00
Sign in to join this conversation.
No Label pull-request
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#25261