| // Copyright 2023 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <algorithm> |
| |
| #include "base/check.h" |
| #include "chrome/browser/ui/sad_tab_helper.h" |
| #include "chrome/browser/ui/views/frame/browser_view.h" |
| #include "chrome/browser/ui/views/frame/browser_view_ash.h" |
| #include "chrome/browser/ui/views/sad_tab_view.h" |
| #include "chrome/browser/ui/views/side_panel/side_panel.h" |
| #include "ui/gfx/geometry/rounded_corners_f.h" |
| #include "ui/views/controls/webview/webview.h" |
| |
| BrowserViewAsh::BrowserViewAsh(std::unique_ptr<Browser> browser) |
| : BrowserView(std::move(browser)) {} |
| |
| void BrowserViewAsh::Layout(PassKey) { |
| LayoutSuperclass<BrowserView>(this); |
| |
| // In ChromeOS ash we round the bottom two corners of the browser frame by |
| // rounding the respective corners of visible client contents i.e main web |
| // contents, devtools web contents and side panel. When ever there is change |
| // in the layout or visibility of these contents (devtools opened, devtools |
| // docked placement change, side panel open etc), we might need to update |
| // which corners are currently rounded. See |
| // `BrowserNonClientFrameViewChromeOS::UpdateWindowRoundedCorners()` for more |
| // details. |
| DCHECK(GetWidget()); |
| GetWidget()->non_client_view()->frame_view()->UpdateWindowRoundedCorners(); |
| } |
| |
| void BrowserViewAsh::UpdateWindowRoundedCorners(int corner_radius) { |
| SidePanel* side_panel = unified_side_panel(); |
| const bool right_aligned_side_panel_showing = |
| side_panel->GetVisible() && side_panel->IsRightAligned(); |
| const bool left_aligned_side_panel_showing = |
| side_panel->GetVisible() && !side_panel->IsRightAligned(); |
| |
| // If side panel is visible, round one of the bottom two corners of the side |
| // panel based on its alignment w.r.t to web contents. |
| const gfx::RoundedCornersF side_panel_radii( |
| 0, 0, right_aligned_side_panel_showing ? corner_radius : 0, |
| left_aligned_side_panel_showing ? corner_radius : 0); |
| |
| if (side_panel_radii != side_panel->background_radii()) { |
| side_panel->SetBackgroundRadii(side_panel_radii); |
| } |
| |
| views::WebView* devtools_webview = devtools_web_view(); |
| CHECK(devtools_webview); |
| CHECK(devtools_webview->holder()); |
| |
| // If devtools are visible, round one of the bottom two corners of the |
| // the devtools context based on the alignment of the side panel. Since |
| // devtools cover the full bounds of the web contents container, if the side |
| // panel is not visible, we have to round the bottom two corners of side panel |
| // irrespective of its docked placement. |
| const gfx::RoundedCornersF devtools_webview_radii( |
| 0, 0, right_aligned_side_panel_showing ? 0 : corner_radius, |
| left_aligned_side_panel_showing ? 0 : corner_radius); |
| |
| if (devtools_webview_radii_ != devtools_webview_radii) { |
| devtools_webview_radii_ = devtools_webview_radii; |
| devtools_webview->holder()->SetCornerRadii(devtools_webview_radii_); |
| } |
| |
| const DevToolsDockedPlacement devtools_placement = |
| devtools_docked_placement(); |
| CHECK_NE(devtools_placement, DevToolsDockedPlacement::kUnknown); |
| |
| // Rounded the contents webview. |
| ContentsWebView* contents_webview = contents_web_view(); |
| const views::View* container = contents_container(); |
| |
| const bool devtools_showing = |
| contents_webview->bounds() != container->GetLocalBounds(); |
| |
| // With window controls overlay enabled, the web content extends over the |
| // entire window height, overlapping the window's top-two rounded corners. |
| // Consequently, we need to make the top two corners of the web_view |
| // rounded as well. |
| const bool round_content_webview_top_corner = |
| IsWindowControlsOverlayEnabled(); |
| |
| const gfx::RoundedCornersF contents_webview_radii( |
| round_content_webview_top_corner ? corner_radius : 0, |
| round_content_webview_top_corner ? corner_radius : 0, |
| right_aligned_side_panel_showing || |
| (devtools_showing && |
| devtools_placement != DevToolsDockedPlacement::kLeft) |
| ? 0 |
| : corner_radius, |
| left_aligned_side_panel_showing || |
| (devtools_showing && |
| devtools_placement != DevToolsDockedPlacement::kRight) |
| ? 0 |
| : corner_radius); |
| |
| CHECK(contents_webview); |
| CHECK(contents_webview->holder()); |
| |
| if (contents_webview->web_contents()) { |
| // SideTabView is shown when the renderer crashes. Initially the SabTabView |
| // gets the same corners as the contents webview it gets attached to but its |
| // radii needs to be updated as it is unaware of the client view layout |
| // changes. |
| if (auto* sad_tab_helper = |
| SadTabHelper::FromWebContents(contents_webview->web_contents()); |
| sad_tab_helper->sad_tab()) { |
| SadTabView* sad_tab_view = |
| static_cast<SadTabView*>(sad_tab_helper->sad_tab()); |
| if (sad_tab_view->GetBackgroundRadii() != contents_webview_radii) { |
| sad_tab_view->SetBackgroundRadii(contents_webview_radii); |
| } |
| } else { |
| // We only round contents_webview, if SadTabView is not showing. |
| if (contents_webview_radii_ != contents_webview_radii) { |
| contents_webview_radii_ = contents_webview_radii; |
| contents_webview->holder()->SetCornerRadii(contents_webview_radii); |
| } |
| } |
| } |
| |
| if (contents_webview->background_radii() != contents_webview_radii) { |
| contents_webview->SetBackgroundRadii(contents_webview_radii); |
| } |
| } |