From fb534c927ae3ca696f0de3a10f90d447dd4fd52c Mon Sep 17 00:00:00 2001 From: Shelley Vohr Date: Fri, 29 Apr 2022 02:34:12 +0200 Subject: [PATCH] refactor: better solution for resizable frameless DCHECK (#33790) * refactor: better solution for resizable frameless DCHECK * fix: also implement TargetForRectin WinFrameView --- shell/browser/ui/views/frameless_view.cc | 10 +++++++++ shell/browser/ui/views/frameless_view.h | 5 ++++- shell/browser/ui/views/win_frame_view.cc | 27 +++++++++++++++++------- shell/browser/ui/views/win_frame_view.h | 3 +++ 4 files changed, 36 insertions(+), 9 deletions(-) diff --git a/shell/browser/ui/views/frameless_view.cc b/shell/browser/ui/views/frameless_view.cc index d2d0b2fdc5e8..e171a7e5049b 100644 --- a/shell/browser/ui/views/frameless_view.cc +++ b/shell/browser/ui/views/frameless_view.cc @@ -112,6 +112,16 @@ void FramelessView::UpdateWindowTitle() {} void FramelessView::SizeConstraintsChanged() {} +views::View* FramelessView::TargetForRect(views::View* root, + const gfx::Rect& rect) { + CHECK_EQ(root, this); + + if (NonClientHitTest(rect.origin()) != HTCLIENT) + return this; + + return NonClientFrameView::TargetForRect(root, rect); +} + gfx::Size FramelessView::CalculatePreferredSize() const { return frame_->non_client_view() ->GetWindowBoundsForClientBounds( diff --git a/shell/browser/ui/views/frameless_view.h b/shell/browser/ui/views/frameless_view.h index 80868f90c89c..f88f543757e1 100644 --- a/shell/browser/ui/views/frameless_view.h +++ b/shell/browser/ui/views/frameless_view.h @@ -47,7 +47,10 @@ class FramelessView : public views::NonClientFrameView { void UpdateWindowTitle() override; void SizeConstraintsChanged() override; - // Overridden from View: + // views::ViewTargeterDelegate: + views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override; + + // views::View: gfx::Size CalculatePreferredSize() const override; gfx::Size GetMinimumSize() const override; gfx::Size GetMaximumSize() const override; diff --git a/shell/browser/ui/views/win_frame_view.cc b/shell/browser/ui/views/win_frame_view.cc index b5d56fa75148..8a25bcdd73e8 100644 --- a/shell/browser/ui/views/win_frame_view.cc +++ b/shell/browser/ui/views/win_frame_view.cc @@ -34,14 +34,6 @@ void WinFrameView::Init(NativeWindowViews* window, views::Widget* frame) { window_ = window; frame_ = frame; - // Prevent events from trickling down the views hierarchy here, since - // when a given resizable window is frameless we only want to use - // FramelessView's ResizingBorderHitTest in - // ShouldDescendIntoChildForEventHandling. See - // https://chromium-review.googlesource.com/c/chromium/src/+/3251980. - if (!window_->has_frame() && window_->IsResizable()) - frame_->client_view()->SetCanProcessEventsWithinSubtree(false); - if (window->IsWindowControlsOverlayEnabled()) { caption_button_container_ = AddChildView(std::make_unique(this)); @@ -83,6 +75,25 @@ int WinFrameView::FrameBorderThickness() const { : display::win::ScreenWin::GetSystemMetricsInDIP(SM_CXSIZEFRAME); } +views::View* WinFrameView::TargetForRect(views::View* root, + const gfx::Rect& rect) { + if (NonClientHitTest(rect.origin()) != HTCLIENT) { + // Custom system titlebar returns non HTCLIENT value, however event should + // be handled by the view, not by the system, because there are no system + // buttons underneath. + if (!ShouldCustomDrawSystemTitlebar()) { + return this; + } + auto local_point = rect.origin(); + ConvertPointToTarget(parent(), caption_button_container_, &local_point); + if (!caption_button_container_->HitTestPoint(local_point)) { + return this; + } + } + + return NonClientFrameView::TargetForRect(root, rect); +} + int WinFrameView::NonClientHitTest(const gfx::Point& point) { if (window_->has_frame()) return frame_->client_view()->NonClientHitTest(point); diff --git a/shell/browser/ui/views/win_frame_view.h b/shell/browser/ui/views/win_frame_view.h index 76b8e64bd184..460474e03bb6 100644 --- a/shell/browser/ui/views/win_frame_view.h +++ b/shell/browser/ui/views/win_frame_view.h @@ -61,6 +61,9 @@ class WinFrameView : public FramelessView { int FrameBorderThickness() const; + // views::ViewTargeterDelegate: + views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override; + // Returns the thickness of the window border for the top edge of the frame, // which is sometimes different than FrameBorderThickness(). Does not include // the titlebar/tabstrip area. If |restored| is true, this is calculated as if