Skip to content

fix: don't return a nullptr from TargetForRect#51586

Merged
VerteDinde merged 3 commits into
mainfrom
nmg/better-view-targeter-delegate
May 13, 2026
Merged

fix: don't return a nullptr from TargetForRect#51586
VerteDinde merged 3 commits into
mainfrom
nmg/better-view-targeter-delegate

Conversation

@nmggithub

@nmggithub nmggithub commented May 11, 2026

Copy link
Copy Markdown
Contributor

Description of Change

Resolves #51576.

The above bug was introduced by this PR: #50330.

While well-intentioned, the choice to return nullptr from a function whose contract does not explicitly allow it caused a nullptr-dereference exception inside Chromium.

  1. RootView::UpdateCursor
  2. View* View::GetEventHandlerForPoint
  3. View* View::GetEventHandlerForRect
  4. ViewTargeter:TargetForRect returns nullptr
  5. RootView::UpdateCursor attempts to dereference the nullptr

Checklist

Release Notes

Notes: Fixed a crash on MacOS when a user clicked into a title bar or top view.

@electron-cation electron-cation Bot added the new-pr 🌱 PR opened recently label May 11, 2026

@jkleinsc jkleinsc left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@nmggithub

Copy link
Copy Markdown
Contributor Author

I forgot to escape my backticks in my last commit message. It was supposed to be fix: address \clang-tidy` concerns`. Oh well!

@ckerr ckerr requested review from ckerr and jkleinsc May 13, 2026 16:48
@ckerr ckerr added target/42-x-y PR should also be added to the "42-x-y" branch. target/43-x-y PR should also be added to the "43-x-y" branch. labels May 13, 2026
@ckerr

ckerr commented May 13, 2026

Copy link
Copy Markdown
Member

Marking as target/43-x-y + target/42-x-y since #50330 has landed in those branches.

It's also marked as needing manual for 41-x-y. If/when that happens, this should get backported to that branch too.

@VerteDinde VerteDinde added the semver/patch backwards-compatible bug fixes label May 13, 2026
@electron-cation electron-cation Bot removed the new-pr 🌱 PR opened recently label May 13, 2026
@VerteDinde VerteDinde added new-pr 🌱 PR opened recently fast-track 🚅 Indicates that this PR is intended to bypass the 24 hour rule. Needs approval from Releases labels May 13, 2026
@electron-cation electron-cation Bot removed the new-pr 🌱 PR opened recently label May 13, 2026
@VerteDinde

Copy link
Copy Markdown
Member

Fast-tracking this, as it fixes an active crash in a production build

@VerteDinde VerteDinde merged commit 30a43bd into main May 13, 2026
132 of 134 checks passed
@VerteDinde VerteDinde deleted the nmg/better-view-targeter-delegate branch May 13, 2026 20:45
@release-clerk

release-clerk Bot commented May 13, 2026

Copy link
Copy Markdown

Release Notes Persisted

Fixed a crash on MacOS when a user clicked into a title bar or top view.

@trop

trop Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "42-x-y", please check out #51605

@trop trop Bot added in-flight/42-x-y and removed target/42-x-y PR should also be added to the "42-x-y" branch. labels May 13, 2026
@trop

trop Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

I have automatically backported this PR to "43-x-y", please check out #51606

@trop trop Bot removed the target/43-x-y PR should also be added to the "43-x-y" branch. label May 13, 2026
@VerteDinde VerteDinde added the target/41-x-y PR should also be added to the "41-x-y" branch. label May 13, 2026
@VerteDinde

Copy link
Copy Markdown
Member

/trop run backport-to 41-x-y

@trop

trop Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

The backport process for this PR has been manually initiated - sending your PR to 41-x-y!

@trop

trop Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

I was unable to backport this PR to "41-x-y" cleanly;
you will need to perform this backport manually.

@trop trop Bot added needs-manual-bp/41-x-y and removed target/41-x-y PR should also be added to the "41-x-y" branch. labels May 13, 2026
@trop

trop Bot commented May 13, 2026

Copy link
Copy Markdown
Contributor

@VerteDinde has manually backported this PR to "41-x-y", please check out #51611

@VerteDinde

Copy link
Copy Markdown
Member

@ckerr Correct me if I'm wrong, but I don't think the original issue ever landed in 41-x-y? Looks like it was slated to be backported, but never was

MarshallOfSound added a commit that referenced this pull request May 14, 2026
fix: simplify content_view_ hit-test transparency on macOS

Replace the RootViewMac-level TargetForRect override added in #51586 with
a DoesIntersectRect override on content_view_'s own targeter, restoring
the structure of #50330 but fixing its actual defect.

The original bug (#51576) was that ContentViewTargeterDelegate::TargetForRect
returned nullptr when no descendant covered the hit rect, violating the
ViewTargeterDelegate contract. RootView::UpdateCursor and
RootView::HandleMouseEnteredOrMoved dereference GetEventHandlerForPoint()
without null checks, so the nullptr crashed with SIGSEGV when a right-click
in a -webkit-app-region: drag region disabled the HTCAPTION early-exit.

#51586 fixed the crash by moving the transparency logic to RootViewMac and
re-implementing the parent targeter's child-walk loop so it could skip
content_view_ and return a sibling instead. That re-implementation duplicates
~25 lines of upstream logic with a subtle rounding divergence
(ToEnclosedRectIgnoringError vs ToEnclosingRect), and threads a new
content_view_hit_test_transparent_ flag through the platform-neutral
NativeWindow/BrowserWindow headers.

The same fall-through can be achieved with the existing hit-test hook:
override DoesIntersectRect on content_view_ to return false when no
visible, processable child intersects the rect. The parent's default
TargetForRect loop already skips children whose HitTestRect is false, so
hit-testing naturally continues to the WebContentsView sibling and resolves
to its NativeViewHost (kSubView) without ever returning nullptr from
TargetForRect or re-implementing the walk.

This reverts the NativeWindow flag, the BrowserWindow constructor change,
and the RootViewMacTargeterDelegate, leaving the fix entirely in
native_window_mac.mm at the same install site as #50330.
@trop trop Bot added merged/42-x-y PR was merged to the "42-x-y" branch. and removed in-flight/42-x-y labels May 14, 2026
@trop trop Bot added merged/43-x-y PR was merged to the "43-x-y" branch. and removed in-flight/43-x-y labels May 14, 2026
VerteDinde added a commit that referenced this pull request May 14, 2026
Backport of #51617 to 42-x-y.

Replace the RootViewMac-level TargetForRect override added in #51586 with
a DoesIntersectRect override on content_view_'s own targeter, restoring
the structure of #50330 but fixing its actual defect.

The original bug (#51576) was that ContentViewTargeterDelegate::TargetForRect
returned nullptr when no descendant covered the hit rect, violating the
ViewTargeterDelegate contract. RootView::UpdateCursor and
RootView::HandleMouseEnteredOrMoved dereference GetEventHandlerForPoint()
without null checks, so the nullptr crashed with SIGSEGV when a right-click
in a -webkit-app-region: drag region disabled the HTCAPTION early-exit.

#51586 fixed the crash by moving the transparency logic to RootViewMac and
re-implementing the parent targeter's child-walk loop so it could skip
content_view_ and return a sibling instead. That re-implementation duplicates
~25 lines of upstream logic with a subtle rounding divergence
(ToEnclosedRectIgnoringError vs ToEnclosingRect), and threads a new
content_view_hit_test_transparent_ flag through the platform-neutral
NativeWindow/BrowserWindow headers.

The same fall-through can be achieved with the existing hit-test hook:
override DoesIntersectRect on content_view_ to return false when no
visible, processable child intersects the rect. The parent's default
TargetForRect loop already skips children whose HitTestRect is false, so
hit-testing naturally continues to the WebContentsView sibling and resolves
to its NativeViewHost (kSubView) without ever returning nullptr from
TargetForRect or re-implementing the walk.

This reverts the NativeWindow flag, the BrowserWindow constructor change,
and the RootViewMacTargeterDelegate, leaving the fix entirely in
native_window_mac.mm at the same install site as #50330.

Co-authored-by: Claude <svc-devxp-claude@slack-corp.com>
VerteDinde added a commit that referenced this pull request May 15, 2026
Backport of #51617 to 43-x-y.

Replace the RootViewMac-level TargetForRect override added in #51586 with
a DoesIntersectRect override on content_view_'s own targeter, restoring
the structure of #50330 but fixing its actual defect.

The original bug (#51576) was that ContentViewTargeterDelegate::TargetForRect
returned nullptr when no descendant covered the hit rect, violating the
ViewTargeterDelegate contract. RootView::UpdateCursor and
RootView::HandleMouseEnteredOrMoved dereference GetEventHandlerForPoint()
without null checks, so the nullptr crashed with SIGSEGV when a right-click
in a -webkit-app-region: drag region disabled the HTCAPTION early-exit.

#51586 fixed the crash by moving the transparency logic to RootViewMac and
re-implementing the parent targeter's child-walk loop so it could skip
content_view_ and return a sibling instead. That re-implementation duplicates
~25 lines of upstream logic with a subtle rounding divergence
(ToEnclosedRectIgnoringError vs ToEnclosingRect), and threads a new
content_view_hit_test_transparent_ flag through the platform-neutral
NativeWindow/BrowserWindow headers.

The same fall-through can be achieved with the existing hit-test hook:
override DoesIntersectRect on content_view_ to return false when no
visible, processable child intersects the rect. The parent's default
TargetForRect loop already skips children whose HitTestRect is false, so
hit-testing naturally continues to the WebContentsView sibling and resolves
to its NativeViewHost (kSubView) without ever returning nullptr from
TargetForRect or re-implementing the walk.

This reverts the NativeWindow flag, the BrowserWindow constructor change,
and the RootViewMacTargeterDelegate, leaving the fix entirely in
native_window_mac.mm at the same install site as #50330.

Co-authored-by: Claude <svc-devxp-claude@slack-corp.com>
ckerr pushed a commit that referenced this pull request May 19, 2026
fix: simplify content_view_ hit-test transparency on macOS

Replace the RootViewMac-level TargetForRect override added in #51586 with
a DoesIntersectRect override on content_view_'s own targeter, restoring
the structure of #50330 but fixing its actual defect.

The original bug (#51576) was that ContentViewTargeterDelegate::TargetForRect
returned nullptr when no descendant covered the hit rect, violating the
ViewTargeterDelegate contract. RootView::UpdateCursor and
RootView::HandleMouseEnteredOrMoved dereference GetEventHandlerForPoint()
without null checks, so the nullptr crashed with SIGSEGV when a right-click
in a -webkit-app-region: drag region disabled the HTCAPTION early-exit.

re-implementing the parent targeter's child-walk loop so it could skip
content_view_ and return a sibling instead. That re-implementation duplicates
~25 lines of upstream logic with a subtle rounding divergence
(ToEnclosedRectIgnoringError vs ToEnclosingRect), and threads a new
content_view_hit_test_transparent_ flag through the platform-neutral
NativeWindow/BrowserWindow headers.

The same fall-through can be achieved with the existing hit-test hook:
override DoesIntersectRect on content_view_ to return false when no
visible, processable child intersects the rect. The parent's default
TargetForRect loop already skips children whose HitTestRect is false, so
hit-testing naturally continues to the WebContentsView sibling and resolves
to its NativeViewHost (kSubView) without ever returning nullptr from
TargetForRect or re-implementing the walk.

This reverts the NativeWindow flag, the BrowserWindow constructor change,
and the RootViewMacTargeterDelegate, leaving the fix entirely in
native_window_mac.mm at the same install site as #50330.

Co-authored-by: GitHub Copilot <copilot@github.com>
jkleinsc pushed a commit that referenced this pull request May 27, 2026
* chore: remove macos hittest workaround patch

Reverts the temporary Chromium patch and restores the original macOS hit-test workaround behavior in Electron.

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* fix: do not return root from TargetForRect

Restore the macOS hit-testing behavior that keeps BrowserWindow web contents interactive when content_view_ has no matching child.

Co-authored-by: Charles Kerr <charles@charleskerr.com>

* refactor: simplify content_view_ hit-test transparency on macOS (#51617)

fix: simplify content_view_ hit-test transparency on macOS

Replace the RootViewMac-level TargetForRect override added in #51586 with
a DoesIntersectRect override on content_view_'s own targeter, restoring
the structure of #50330 but fixing its actual defect.

The original bug (#51576) was that ContentViewTargeterDelegate::TargetForRect
returned nullptr when no descendant covered the hit rect, violating the
ViewTargeterDelegate contract. RootView::UpdateCursor and
RootView::HandleMouseEnteredOrMoved dereference GetEventHandlerForPoint()
without null checks, so the nullptr crashed with SIGSEGV when a right-click
in a -webkit-app-region: drag region disabled the HTCAPTION early-exit.

re-implementing the parent targeter's child-walk loop so it could skip
content_view_ and return a sibling instead. That re-implementation duplicates
~25 lines of upstream logic with a subtle rounding divergence
(ToEnclosedRectIgnoringError vs ToEnclosingRect), and threads a new
content_view_hit_test_transparent_ flag through the platform-neutral
NativeWindow/BrowserWindow headers.

The same fall-through can be achieved with the existing hit-test hook:
override DoesIntersectRect on content_view_ to return false when no
visible, processable child intersects the rect. The parent's default
TargetForRect loop already skips children whose HitTestRect is false, so
hit-testing naturally continues to the WebContentsView sibling and resolves
to its NativeViewHost (kSubView) without ever returning nullptr from
TargetForRect or re-implementing the walk.

This reverts the NativeWindow flag, the BrowserWindow constructor change,
and the RootViewMacTargeterDelegate, leaving the fix entirely in
native_window_mac.mm at the same install site as #50330.

Co-authored-by: GitHub Copilot <copilot@github.com>

---------

Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
Co-authored-by: Noah Gregory <nmggithub@electronjs.org>
Co-authored-by: Samuel Attard <sam@electronjs.org>
Co-authored-by: GitHub Copilot <copilot@github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fast-track 🚅 Indicates that this PR is intended to bypass the 24 hour rule. Needs approval from Releases merged/42-x-y PR was merged to the "42-x-y" branch. merged/43-x-y PR was merged to the "43-x-y" branch. semver/patch backwards-compatible bug fixes

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Crash (SIGSEGV) on right-click in -webkit-app-region: drag on macOS 26 (Tahoe)

4 participants