Resizing a text box by one edge handle incorrectly locks both Max Width and Max Height, silently clipping text

Open Beginner friendly
#4,396 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
78/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Quiet
Tech stack
rust

Research direction

Start in editor/src/messages/tool/tool_messages/text_tool.rs at the ResizingBounds → PointerMove handler around lines 851-920, and read the nearby TODO. Then inspect SelectedEdges in transformation_cage.rs and how new_size() handles single-edge drags. Done means a left/right drag activates only width constraints, a top/bottom drag only height constraints, and a corner drag activates both without clipping rewrapped text.

Written by the indexing model from the issue text.

Description

Dragging a single edge handle to resize a text layer's bounding box incorrectly enables and locks both the Max Width and Max Height constraints together, even when only one axis was actually resized. Since Max Height causes any text beyond it to not be drawn, this can silently clip text that should still be auto-growing.

Steps to reproduce:

  1. Select the Text tool and click (don't drag) to create point text, then type several lines — this creates auto-sized text with neither Max Width nor Max Height enabled
  2. Switch to resizing and drag only the right-edge handle of the bounding box to set a width (so the text wraps)
  3. Expected: only Max Width becomes active; height keeps auto-growing to fit the rewrapped text
  4. Actual: Max Height also gets switched on and frozen to whatever the box's height happened to be before the rewrap — any lines that end up pushed past that frozen height are silently not drawn

Cause:
In editor/src/messages/tool/tool_messages/text_tool.rs, the ResizingBoundsPointerMove handler (around lines 851-920) unconditionally sets both HasMaxWidthInput/MaxWidthInput and HasMaxHeightInput/MaxHeightInput, regardless of which edge is being dragged. There's actually a TODO comment already sitting right above this code:

// TODO: Don't set both max_width and max_height to true at the same time, only do one based on which edge is being dragged (or both if a corner is being dragged)

The information needed to fix it is already available and just unused: SelectedEdges { top, bottom, left, right } in transformation_cage.rs records exactly which edge(s) are being dragged, and new_size() already leaves size.y untouched (equal to the pre-drag height) when only a left/right edge is dragged — that stale value is what's getting wrongly frozen into MaxHeightInput.

Suggested fix:
Gate the two pairs of SetInput calls on which axis was actually touched, per the existing TODO:

let (touches_width, touches_height) = (movement.left || movement.right, movement.top || movement.bottom);

if touches_width {
    // set HasMaxWidthInput / MaxWidthInput
}
if touches_height {
    // set HasMaxHeightInput / MaxHeightInput
}

A corner-handle drag naturally sets both pairs of edges, so both branches fire together there, matching the "(or both if a corner is being dragged)" note in the TODO.

Dominant language
Rust
Stars
27.3k
Forks
1.3k
Avg merge
1d 7h
Merged PRs (30d)
54

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from GraphiteEditor/Graphite

All issues in GraphiteEditor/Graphite

Similar issues

More Rust issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.