Skip to content

Fix caption button click issues and improve hit-testing - #5305

Merged
Gabriel Dufresne (GabrielDuf) merged 2 commits into
mainfrom
fix/caption-buttons-top-edge
Aug 20, 2026
Merged

Fix caption button click issues and improve hit-testing#5305
Gabriel Dufresne (GabrielDuf) merged 2 commits into
mainfrom
fix/caption-buttons-top-edge

Conversation

@GabrielDuf

Copy link
Copy Markdown
Contributor

This pull request improves the handling and hit-testing of caption buttons (such as minimize, maximize, and close) in the MainWindow of the Avalonia UI project. The changes enhance the accuracy of mouse hit detection for these buttons and ensure consistent visual feedback when interacting with them.

Hit-testing improvements for caption buttons:

  • Added a new HitTestCaptionButtons method to accurately determine if mouse events occur over any of the window's caption buttons. This centralizes and simplifies the hit-testing logic for these UI elements.
  • Refactored coordinate extraction from window messages by introducing the ScreenPointFromLParam helper method, which is now used in both maximize and caption button hit-testing.
  • Updated the window message handler to use the new HitTestCaptionButtons method, returning the appropriate hit-test value when a caption button is detected under the cursor.
  • Added the HTCLIENT constant for clarity and correctness in hit-testing return values.

Visual feedback improvements:

  • Added a style for Button.caption:pressed in MainWindow.axaml to ensure pressed caption buttons do not apply a render transform, maintaining consistent appearance.

Fluent's Button style applies RenderTransform scale(0.98) on :pressed with
a 75 ms TransformOperationsTransition, and Button.OnPointerReleased only
raises Click when the release position still hit-tests onto the button. On
a 46x44 caption button that shrink pulls every edge ~0.45 DIP inward while
the button is held, so a press on the outermost pixel row or column lands
on the button, the geometry moves out from under the stationary pointer,
and the release finds TitleBarDragArea instead: the button keeps its
pressed fill and nothing happens.

Measured on a maximized window, minimize on the top row: the button's clip
goes from (1590, 0, 46, 44) at press to (1590.36, 0.34, 45.28, 43.31) at
release, with IsPointerOver false. Injected clicks on that row went 0/8
before this change and 8/8 after.

Native caption buttons don't shrink on press, so opt ours out of the
transform and keep the background-only state change. The outcome depended
on how far the 75 ms transition had run at release, which is why it
reproduced on one monitor and not another.

Fixes #5269

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Avalonia's HitTestNCA hands the WS_THICKFRAME border to HTTOP / HTRIGHT /
HTTOPRIGHT and CustomCaptionProc never lets the visual tree override those
results, so wherever that border overlaps our custom caption buttons the
pixels are non-client: clicks there start a resize instead of pressing the
button, and no pointer-leave is synthesised, so the button keeps its hover
fill and looks live. The border is skipped only while the window is
natively maximized (Windows then places the frame outside the work area),
so it bites floating and snapped windows.

Measured on a floating window at 200%: the top 12 px reported TOP and the
rightmost 13 px of the close button reported RIGHT, swallowing every click,
while 20 px in worked.

Claim the whole WindowButtons rect as HTCLIENT from the existing
WM_NCHITTEST hook, which runs before Avalonia's WndProc, so the buttons own
their own pixels in every window state. Resizing stays available along the
rest of the top edge and down the right edge below the strip, and the
maximize button keeps its HTMAXBUTTON claim so Snap Layouts still attach.
Injected clicks on a floating window close 3/3 at 1, 6 and 13 px from the
right edge, versus 0/3 at 1 px before.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Improves Windows caption-button hit-testing and pressed-state visuals in the Avalonia main window.

Changes:

  • Centralizes screen-coordinate extraction and caption-button hit-testing.
  • Returns client-area hits for minimize/close while preserving native maximize behavior.
  • Prevents pressed caption buttons from transforming.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/UniGetUI.Avalonia/Views/MainWindow.axaml.cs Refines native caption-button hit-testing.
src/UniGetUI.Avalonia/Views/MainWindow.axaml Stabilizes pressed-button visuals.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@GabrielDuf
Gabriel Dufresne (GabrielDuf) merged commit b04a026 into main Aug 20, 2026
6 of 7 checks passed
@GabrielDuf
Gabriel Dufresne (GabrielDuf) deleted the fix/caption-buttons-top-edge branch August 20, 2026 20:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Clicking title bar close button along top edge of screen does not close window

3 participants