diff --git a/app/brave_generated_resources.grd b/app/brave_generated_resources.grd index 153aae5d1f02..549d728fcad2 100644 --- a/app/brave_generated_resources.grd +++ b/app/brave_generated_resources.grd @@ -797,15 +797,23 @@ Or change later at $2brave://settings/ext Brave is made available to you under the <a target="_blank" href="$1">Mozilla Public License 2.0</a> (MPL) and includes <a target="_blank" href="$2">open source software</a> under a variety of other licenses. You can read <a target="_blank" href="$3">instructions on how to download and build for yourself</a> the specific <a target="_blank" href="$4">source code used to create this copy</a>. + + Bookmark all tabs... + + Show title bar + Bookmark All Tabs... + + Show title bar + diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn index 8ac3f3384efb..7f5935273b60 100644 --- a/browser/ui/BUILD.gn +++ b/browser/ui/BUILD.gn @@ -217,6 +217,8 @@ source_set("ui") { "views/frame/brave_browser_view.h", "views/frame/brave_browser_view_layout.cc", "views/frame/brave_browser_view_layout.h", + "views/frame/brave_non_client_hit_test_helper.cc", + "views/frame/brave_non_client_hit_test_helper.h", "views/frame/brave_opaque_browser_frame_view.cc", "views/frame/brave_opaque_browser_frame_view.h", "views/frame/brave_window_frame_graphic.cc", @@ -290,6 +292,8 @@ source_set("ui") { if (is_mac) { sources += [ + "views/frame/brave_browser_frame_mac.h", + "views/frame/brave_browser_frame_mac.mm", "views/frame/brave_browser_non_client_frame_view_mac.h", "views/frame/brave_browser_non_client_frame_view_mac.mm", ] diff --git a/browser/ui/browser_commands.cc b/browser/ui/browser_commands.cc index 81b1fd8fbb25..6130d2807c92 100644 --- a/browser/ui/browser_commands.cc +++ b/browser/ui/browser_commands.cc @@ -11,6 +11,7 @@ #include "brave/app/brave_command_ids.h" #include "brave/browser/debounce/debounce_service_factory.h" #include "brave/browser/net/brave_query_filter.h" +#include "brave/browser/ui/tabs/brave_tab_prefs.h" #include "brave/browser/url_sanitizer/url_sanitizer_service_factory.h" #include "brave/components/brave_vpn/buildflags/buildflags.h" #include "brave/components/constants/pref_names.h" @@ -225,4 +226,11 @@ void CopyLinkWithStrictCleaning(Browser* browser, const GURL& url) { scw.WriteText(base::UTF8ToUTF16(final_url.spec())); } +void ToggleWindowTitleVisibilityForVerticalTabs(Browser* browser) { + auto* prefs = browser->profile()->GetOriginalProfile()->GetPrefs(); + prefs->SetBoolean( + brave_tabs::kVerticalTabsShowTitleOnWindow, + !prefs->GetBoolean(brave_tabs::kVerticalTabsShowTitleOnWindow)); +} + } // namespace brave diff --git a/browser/ui/browser_commands.h b/browser/ui/browser_commands.h index 2bc4dcd832df..24367061178c 100644 --- a/browser/ui/browser_commands.h +++ b/browser/ui/browser_commands.h @@ -31,6 +31,8 @@ void CopySanitizedURL(Browser* browser, const GURL& url); // - URLSanitizerService void CopyLinkWithStrictCleaning(Browser* browser, const GURL& url); +void ToggleWindowTitleVisibilityForVerticalTabs(Browser* browser); + } // namespace brave diff --git a/browser/ui/tabs/brave_tab_menu_model.cc b/browser/ui/tabs/brave_tab_menu_model.cc index 6c62caac6208..aee056dc046f 100644 --- a/browser/ui/tabs/brave_tab_menu_model.cc +++ b/browser/ui/tabs/brave_tab_menu_model.cc @@ -55,4 +55,5 @@ void BraveTabMenuModel::Build() { AddSeparator(ui::NORMAL_SEPARATOR); AddItemWithStringId(CommandRestoreTab, GetRestoreTabCommandStringId()); AddItemWithStringId(CommandBookmarkAllTabs, IDS_TAB_CXMENU_BOOKMARK_ALL_TABS); + AddCheckItemWithStringId(CommandShowTitleBar, IDS_TAB_CXMENU_SHOW_TITLE_BAR); } diff --git a/browser/ui/tabs/brave_tab_menu_model.h b/browser/ui/tabs/brave_tab_menu_model.h index 650660438d17..86d50c176ec4 100644 --- a/browser/ui/tabs/brave_tab_menu_model.h +++ b/browser/ui/tabs/brave_tab_menu_model.h @@ -24,6 +24,7 @@ class BraveTabMenuModel : public TabMenuModel { CommandStart = TabStripModel::CommandLast, CommandRestoreTab, CommandBookmarkAllTabs, + CommandShowTitleBar, CommandLast, }; diff --git a/browser/ui/tabs/brave_tab_prefs.cc b/browser/ui/tabs/brave_tab_prefs.cc index b11cb68a8e06..7923db9932ed 100644 --- a/browser/ui/tabs/brave_tab_prefs.cc +++ b/browser/ui/tabs/brave_tab_prefs.cc @@ -12,10 +12,13 @@ namespace brave_tabs { const char kTabHoverMode[] = "brave.tabs.hover_mode"; const char kVerticalTabsCollapsed[] = "brave.tabs.vertical_tabs_collapsed"; +const char kVerticalTabsShowTitleOnWindow[] = + "brave.tabs.vertical_tabs_show_title_on_window"; void RegisterBraveProfilePrefs(PrefRegistrySimple* registry) { registry->RegisterIntegerPref(kTabHoverMode, TabHoverMode::CARD); registry->RegisterBooleanPref(kVerticalTabsCollapsed, false); + registry->RegisterBooleanPref(kVerticalTabsShowTitleOnWindow, true); } bool AreTooltipsEnabled(PrefService* prefs) { diff --git a/browser/ui/tabs/brave_tab_prefs.h b/browser/ui/tabs/brave_tab_prefs.h index 8f1ebbeaabd1..6a4efa4bdaf8 100644 --- a/browser/ui/tabs/brave_tab_prefs.h +++ b/browser/ui/tabs/brave_tab_prefs.h @@ -15,6 +15,7 @@ enum TabHoverMode { TOOLTIP = 0, CARD = 1, CARD_WITH_PREVIEW = 2 }; extern const char kTabHoverMode[]; extern const char kVerticalTabsCollapsed[]; +extern const char kVerticalTabsShowTitleOnWindow[]; void RegisterBraveProfilePrefs(PrefRegistrySimple* registry); diff --git a/browser/ui/views/frame/brave_browser_frame_mac.h b/browser/ui/views/frame/brave_browser_frame_mac.h new file mode 100644 index 000000000000..38e3584fdf56 --- /dev/null +++ b/browser/ui/views/frame/brave_browser_frame_mac.h @@ -0,0 +1,26 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_BROWSER_FRAME_MAC_H_ +#define BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_BROWSER_FRAME_MAC_H_ + +#include "chrome/browser/ui/views/frame/browser_frame_mac.h" + +class Browser; + +class BraveBrowserFrameMac : public BrowserFrameMac { + public: + BraveBrowserFrameMac(BrowserFrame* browser_frame, BrowserView* browser_view); + ~BraveBrowserFrameMac() override; + + // BrowserFrameMac: + void GetWindowFrameTitlebarHeight(bool* override_titlebar_height, + float* titlebar_height) override; + + private: + raw_ptr browser_; +}; + +#endif // BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_BROWSER_FRAME_MAC_H_ diff --git a/browser/ui/views/frame/brave_browser_frame_mac.mm b/browser/ui/views/frame/brave_browser_frame_mac.mm new file mode 100644 index 000000000000..35170f56c9d9 --- /dev/null +++ b/browser/ui/views/frame/brave_browser_frame_mac.mm @@ -0,0 +1,29 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/ui/views/frame/brave_browser_frame_mac.h" + +#include "brave/browser/ui/views/tabs/features.h" +#include "chrome/browser/ui/views/frame/browser_view.h" + +BraveBrowserFrameMac::BraveBrowserFrameMac(BrowserFrame* browser_frame, + BrowserView* browser_view) + : BrowserFrameMac(browser_frame, browser_view), + browser_(browser_view->browser()) {} + +BraveBrowserFrameMac::~BraveBrowserFrameMac() = default; + +void BraveBrowserFrameMac::GetWindowFrameTitlebarHeight( + bool* override_titlebar_height, + float* titlebar_height) { + // Don't override titlebar height if the browser supports vertical tab strip + // so that it can overlay our client view. The visibility of title bar will be + // controlled by BrowserNonClientFrameViewMac::UpdateWindowTitleVisibility. + if (browser_->is_type_normal() && tabs::features::ShouldShowVerticalTabs()) + return; + + return BrowserFrameMac::GetWindowFrameTitlebarHeight(override_titlebar_height, + titlebar_height); +} diff --git a/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.h b/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.h index 49bb4a263698..f96b35075b89 100644 --- a/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.h +++ b/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.h @@ -24,11 +24,17 @@ class BraveBrowserNonClientFrameViewMac : public BrowserNonClientFrameViewMac { const BraveBrowserNonClientFrameViewMac&) = delete; private: + bool ShouldShowWindowTitleForVerticalTabs() const; + void UpdateWindowTitleVisibility(); + // BrowserNonClientFrameViewMac overrides: void OnPaint(gfx::Canvas* canvas) override; int GetTopInset(bool restored) const override; + int NonClientHitTest(const gfx::Point& point) override; std::unique_ptr frame_graphic_; + + BooleanPrefMember show_title_bar_on_vertical_tabs_; }; #endif // BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_BROWSER_NON_CLIENT_FRAME_VIEW_MAC_H_ diff --git a/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.mm b/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.mm index 09b3de506ff0..78316125a038 100644 --- a/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.mm +++ b/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.mm @@ -7,10 +7,14 @@ #include "brave/browser/ui/views/frame/brave_browser_non_client_frame_view_mac.h" +#include "brave/browser/ui/tabs/brave_tab_prefs.h" +#include "brave/browser/ui/views/frame/brave_non_client_hit_test_helper.h" #include "brave/browser/ui/views/frame/brave_window_frame_graphic.h" #include "brave/browser/ui/views/tabs/features.h" #include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/view_ids.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "ui/base/hit_test.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/scoped_canvas.h" @@ -20,6 +24,15 @@ : BrowserNonClientFrameViewMac(frame, browser_view) { frame_graphic_ = std::make_unique( browser_view->browser()->profile()); + + if (tabs::features::ShouldShowVerticalTabs()) { + show_title_bar_on_vertical_tabs_.Init( + brave_tabs::kVerticalTabsShowTitleOnWindow, + browser_view->browser()->profile()->GetOriginalProfile()->GetPrefs(), + base::BindRepeating( + &BraveBrowserNonClientFrameViewMac::UpdateWindowTitleVisibility, + base::Unretained(this))); + } } BraveBrowserNonClientFrameViewMac::~BraveBrowserNonClientFrameViewMac() = default; @@ -41,10 +54,33 @@ } int BraveBrowserNonClientFrameViewMac::GetTopInset(bool restored) const { - if (tabs::features::ShouldShowVerticalTabs()) { + if (ShouldShowWindowTitleForVerticalTabs()) { // Set minimum top inset to show caption buttons on frame. - return 18; + return 30; } return BrowserNonClientFrameViewMac::GetTopInset(restored); } + +bool BraveBrowserNonClientFrameViewMac::ShouldShowWindowTitleForVerticalTabs() + const { + return tabs::features::ShouldShowWindowTitleForVerticalTabs( + browser_view()->browser()); +} + +void BraveBrowserNonClientFrameViewMac::UpdateWindowTitleVisibility() { + if (!browser_view()->browser()->is_type_normal()) + return; + + frame()->SetWindowTitleVisibility(ShouldShowWindowTitleForVerticalTabs()); +} + +int BraveBrowserNonClientFrameViewMac::NonClientHitTest( + const gfx::Point& point) { + if (auto res = brave::NonClientHitTest(browser_view(), point); + res != HTNOWHERE) { + return res; + } + + return BrowserNonClientFrameViewMac::NonClientHitTest(point); +} diff --git a/browser/ui/views/frame/brave_browser_view.cc b/browser/ui/views/frame/brave_browser_view.cc index ab37f78cd676..aac5b7dc3f78 100644 --- a/browser/ui/views/frame/brave_browser_view.cc +++ b/browser/ui/views/frame/brave_browser_view.cc @@ -502,7 +502,7 @@ bool BraveBrowserView::ShouldShowWindowTitle() const { if (BrowserView::ShouldShowWindowTitle()) return true; - if (tabs::features::ShouldShowVerticalTabs() && browser_->is_type_normal()) + if (tabs::features::ShouldShowWindowTitleForVerticalTabs(browser())) return true; return false; diff --git a/browser/ui/views/frame/brave_glass_browser_frame_view.cc b/browser/ui/views/frame/brave_glass_browser_frame_view.cc index a7e031997ae9..591ee1502ba7 100644 --- a/browser/ui/views/frame/brave_glass_browser_frame_view.cc +++ b/browser/ui/views/frame/brave_glass_browser_frame_view.cc @@ -5,9 +5,12 @@ #include "brave/browser/ui/views/frame/brave_glass_browser_frame_view.h" +#include "brave/browser/ui/views/frame/brave_non_client_hit_test_helper.h" #include "brave/browser/ui/views/frame/brave_window_frame_graphic.h" +#include "brave/browser/ui/views/tabs/features.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/frame/browser_view.h" +#include "ui/base/hit_test.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/scoped_canvas.h" @@ -36,3 +39,21 @@ void BraveGlassBrowserFrameView::OnPaint(gfx::Canvas* canvas) { } frame_graphic_->Paint(canvas, bounds_to_frame_graphic); } + +int BraveGlassBrowserFrameView::GetTopInset(bool restored) const { + if (tabs::features::ShouldShowVerticalTabs()) { + if (!tabs::features::ShouldShowWindowTitleForVerticalTabs( + browser_view()->browser())) + return 0; + } + + return GlassBrowserFrameView::GetTopInset(restored); +} +int BraveGlassBrowserFrameView::NonClientHitTest(const gfx::Point& point) { + if (auto res = brave::NonClientHitTest(browser_view(), point); + res != HTNOWHERE) { + return res; + } + + return GlassBrowserFrameView::NonClientHitTest(point); +} diff --git a/browser/ui/views/frame/brave_glass_browser_frame_view.h b/browser/ui/views/frame/brave_glass_browser_frame_view.h index 813fdb2cf204..96b1b2f49d5b 100644 --- a/browser/ui/views/frame/brave_glass_browser_frame_view.h +++ b/browser/ui/views/frame/brave_glass_browser_frame_view.h @@ -24,6 +24,8 @@ class BraveGlassBrowserFrameView : public GlassBrowserFrameView { private: // GlassBrowserFrameView overrides: void OnPaint(gfx::Canvas* canvas) override; + int GetTopInset(bool restored) const override; + int NonClientHitTest(const gfx::Point& point) override; std::unique_ptr frame_graphic_; }; diff --git a/browser/ui/views/frame/brave_non_client_hit_test_helper.cc b/browser/ui/views/frame/brave_non_client_hit_test_helper.cc new file mode 100644 index 000000000000..deddd55a8947 --- /dev/null +++ b/browser/ui/views/frame/brave_non_client_hit_test_helper.cc @@ -0,0 +1,22 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/ui/views/frame/brave_non_client_hit_test_helper.h" + +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "ui/base/hit_test.h" +#include "ui/views/window/hit_test_utils.h" + +namespace brave { + +int NonClientHitTest(BrowserView* browser_view, const gfx::Point& point) { + if (!browser_view->toolbar() || !browser_view->toolbar()->GetVisible()) + return HTNOWHERE; + + return views::GetHitTestComponent(browser_view->toolbar(), point); +} + +} // namespace brave diff --git a/browser/ui/views/frame/brave_non_client_hit_test_helper.h b/browser/ui/views/frame/brave_non_client_hit_test_helper.h new file mode 100644 index 000000000000..fca90ac9f4b4 --- /dev/null +++ b/browser/ui/views/frame/brave_non_client_hit_test_helper.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_NON_CLIENT_HIT_TEST_HELPER_H_ +#define BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_NON_CLIENT_HIT_TEST_HELPER_H_ + +namespace gfx { +class Point; +} // namespace gfx + +class BrowserView; + +namespace brave { + +// Helper function to set additional draggable area in client view. +// Returns HTNOWHERE if the point is not what we're interested in. In that +// case, caller should depend on the default behavior. +int NonClientHitTest(BrowserView* browser_view, const gfx::Point& point); + +} // namespace brave + +#endif // BRAVE_BROWSER_UI_VIEWS_FRAME_BRAVE_NON_CLIENT_HIT_TEST_HELPER_H_ diff --git a/browser/ui/views/frame/brave_non_client_hit_test_helper_browsertest.cc b/browser/ui/views/frame/brave_non_client_hit_test_helper_browsertest.cc new file mode 100644 index 000000000000..35c1020732b5 --- /dev/null +++ b/browser/ui/views/frame/brave_non_client_hit_test_helper_browsertest.cc @@ -0,0 +1,38 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/toolbar/reload_button.h" +#include "chrome/browser/ui/views/toolbar/toolbar_view.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" +#include "ui/base/hit_test.h" + +using BraveNonClientHitTestHelperBrowserTest = InProcessBrowserTest; + +IN_PROC_BROWSER_TEST_F(BraveNonClientHitTestHelperBrowserTest, Toolbar) { + auto* browser_view = static_cast(browser()->window()); + auto* toolbar = browser_view->toolbar(); + auto* frame_view = browser_view->frame()->GetFrameView(); + + gfx::Point point; + views::View::ConvertPointToWidget(toolbar, &point); + + // Dragging a window with the toolbar on it should work. + EXPECT_EQ(HTCAPTION, frame_view->NonClientHitTest(point)); + + // It shouldn't be perceived as a HTCAPTION when it's not visible. + toolbar->SetVisible(false); + EXPECT_NE(HTCAPTION, frame_view->NonClientHitTest(point)); + + // A coordinate on children of toolbar shouldn't be HTCAPTION so that users + // can interact with them. Checks a typical child of toolbar as a sanity + // check. + toolbar->SetVisible(true); + point = gfx::Point(); + views::View::ConvertPointToWidget(toolbar->reload_button(), &point); + EXPECT_NE(HTCAPTION, frame_view->NonClientHitTest(point)); +} diff --git a/browser/ui/views/frame/brave_opaque_browser_frame_view.cc b/browser/ui/views/frame/brave_opaque_browser_frame_view.cc index 2e52863d9d95..7fe9452fae08 100644 --- a/browser/ui/views/frame/brave_opaque_browser_frame_view.cc +++ b/browser/ui/views/frame/brave_opaque_browser_frame_view.cc @@ -7,10 +7,12 @@ #include +#include "brave/browser/ui/views/frame/brave_non_client_hit_test_helper.h" #include "brave/browser/ui/views/frame/brave_window_frame_graphic.h" #include "chrome/browser/ui/browser.h" #include "chrome/browser/ui/views/frame/browser_view.h" #include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h" +#include "ui/base/hit_test.h" #include "ui/gfx/geometry/insets.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/scoped_canvas.h" @@ -40,3 +42,12 @@ void BraveOpaqueBrowserFrameView::OnPaint(gfx::Canvas* canvas) { } frame_graphic_->Paint(canvas, bounds_to_frame_graphic); } + +int BraveOpaqueBrowserFrameView::NonClientHitTest(const gfx::Point& point) { + if (auto res = brave::NonClientHitTest(browser_view(), point); + res != HTNOWHERE) { + return res; + } + + return OpaqueBrowserFrameView::NonClientHitTest(point); +} diff --git a/browser/ui/views/frame/brave_opaque_browser_frame_view.h b/browser/ui/views/frame/brave_opaque_browser_frame_view.h index 3d3cf5b6fed2..0e8e4fb090d8 100644 --- a/browser/ui/views/frame/brave_opaque_browser_frame_view.h +++ b/browser/ui/views/frame/brave_opaque_browser_frame_view.h @@ -25,6 +25,7 @@ class BraveOpaqueBrowserFrameView : public OpaqueBrowserFrameView { // OpaqueBrowserFrameView overrides: void OnPaint(gfx::Canvas* canvas) override; + int NonClientHitTest(const gfx::Point& point) override; private: std::unique_ptr frame_graphic_; diff --git a/browser/ui/views/tabs/brave_tab_context_menu_contents.cc b/browser/ui/views/tabs/brave_tab_context_menu_contents.cc index e22b49ab892a..12308d92f129 100644 --- a/browser/ui/views/tabs/brave_tab_context_menu_contents.cc +++ b/browser/ui/views/tabs/brave_tab_context_menu_contents.cc @@ -5,8 +5,11 @@ #include "brave/browser/ui/views/tabs/brave_tab_context_menu_contents.h" +#include "brave/browser/ui/browser_commands.h" #include "brave/browser/ui/tabs/brave_tab_menu_model.h" +#include "brave/browser/ui/tabs/brave_tab_prefs.h" #include "brave/browser/ui/views/tabs/brave_browser_tab_strip_controller.h" +#include "brave/browser/ui/views/tabs/features.h" #include "chrome/browser/defaults.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sessions/tab_restore_service_factory.h" @@ -48,6 +51,11 @@ void BraveTabContextMenuContents::RunMenuAt( } bool BraveTabContextMenuContents::IsCommandIdChecked(int command_id) const { + if (command_id == BraveTabMenuModel::CommandShowTitleBar) { + return tabs::features::ShouldShowWindowTitleForVerticalTabs( + controller_->browser()); + } + return false; } @@ -60,6 +68,13 @@ bool BraveTabContextMenuContents::IsCommandIdEnabled(int command_id) const { tab_); } +bool BraveTabContextMenuContents::IsCommandIdVisible(int command_id) const { + if (command_id == BraveTabMenuModel::CommandShowTitleBar) + return tabs::features::ShouldShowVerticalTabs(); + + return ui::SimpleMenuModel::Delegate::IsCommandIdVisible(command_id); +} + bool BraveTabContextMenuContents::GetAcceleratorForCommandId( int command_id, ui::Accelerator* accelerator) const { @@ -99,6 +114,8 @@ bool BraveTabContextMenuContents::IsBraveCommandIdEnabled( chrome::CanBookmarkAllTabs(browser_); } break; + case BraveTabMenuModel::CommandShowTitleBar: + return true; default: NOTREACHED(); break; @@ -115,6 +132,11 @@ void BraveTabContextMenuContents::ExecuteBraveCommand(int command_id) { case BraveTabMenuModel::CommandBookmarkAllTabs: chrome::BookmarkAllTabs(browser_); return; + case BraveTabMenuModel::CommandShowTitleBar: { + brave::ToggleWindowTitleVisibilityForVerticalTabs(browser_); + BrowserView::GetBrowserViewForBrowser(browser_)->InvalidateLayout(); + return; + } default: NOTREACHED(); return; diff --git a/browser/ui/views/tabs/brave_tab_context_menu_contents.h b/browser/ui/views/tabs/brave_tab_context_menu_contents.h index da570cb8ad8b..30c09d705f52 100644 --- a/browser/ui/views/tabs/brave_tab_context_menu_contents.h +++ b/browser/ui/views/tabs/brave_tab_context_menu_contents.h @@ -42,6 +42,7 @@ class BraveTabContextMenuContents : public ui::SimpleMenuModel::Delegate { // ui::SimpleMenuModel::Delegate overrides: bool IsCommandIdChecked(int command_id) const override; bool IsCommandIdEnabled(int command_id) const override; + bool IsCommandIdVisible(int command_id) const override; bool GetAcceleratorForCommandId(int command_id, ui::Accelerator* accelerator) const override; void ExecuteCommand(int command_id, int event_flags) override; diff --git a/browser/ui/views/tabs/brave_tab_strip.cc b/browser/ui/views/tabs/brave_tab_strip.cc index 98b8aff971d2..74d4eb367772 100644 --- a/browser/ui/views/tabs/brave_tab_strip.cc +++ b/browser/ui/views/tabs/brave_tab_strip.cc @@ -25,6 +25,9 @@ BraveTabStrip::BraveTabStrip(std::unique_ptr controller) BraveTabStrip::~BraveTabStrip() = default; bool BraveTabStrip::ShouldDrawStrokes() const { + if (tabs::features::ShouldShowVerticalTabs()) + return false; + if (!TabStrip::ShouldDrawStrokes()) return false; diff --git a/browser/ui/views/tabs/features.cc b/browser/ui/views/tabs/features.cc index 75758a4fc4ca..6a48ff1c6696 100644 --- a/browser/ui/views/tabs/features.cc +++ b/browser/ui/views/tabs/features.cc @@ -5,7 +5,22 @@ #include "brave/browser/ui/views/tabs/features.h" -#include "base/feature_list.h" +#include "brave/browser/ui/tabs/brave_tab_prefs.h" +#include "chrome/browser/profiles/profile.h" +#include "chrome/browser/ui/browser.h" +#include "components/prefs/pref_service.h" + +#if !BUILDFLAG(IS_MAC) +#include "chrome/browser/ui/frame/window_frame_util.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/browser/ui/views/frame/opaque_browser_frame_view_layout.h" +#include "ui/base/theme_provider.h" +#include "ui/views/resources/grit/views_resources.h" +#endif + +#if BUILDFLAG(IS_LINUX) +#include "ui/views/window/caption_button_layout_constants.h" +#endif namespace tabs { namespace features { @@ -19,5 +34,59 @@ bool ShouldShowVerticalTabs() { return base::FeatureList::IsEnabled(features::kBraveVerticalTabs); } +bool ShouldShowWindowTitleForVerticalTabs(const Browser* browser) { + DCHECK(browser); + + if (!ShouldShowVerticalTabs()) + return false; + + if (!browser->is_type_normal()) + return false; + + return browser->profile()->GetOriginalProfile()->GetPrefs()->GetBoolean( + brave_tabs::kVerticalTabsShowTitleOnWindow); +} + +std::pair GetLeadingTrailingCaptionButtonWidth( + const BrowserFrame* frame) { +#if BUILDFLAG(IS_MAC) + // On Mac, window caption buttons are drawn by the system. + return {80, 0}; +#elif BUILDFLAG(IS_LINUX) + // On Linux, we can't overlay caption buttons on toolbar. + return {0, 0}; +#elif BUILDFLAG(IS_WIN) + if (frame->ShouldUseNativeFrame()) { + // In this case, we usd GlassBrowserFrameView. Native frame will be set to + // the HWND and and GlassBrowserFrameView will draw frame and window caption + // button. + auto size = WindowFrameUtil::GetWindows10GlassCaptionButtonAreaSize(); + if (WindowFrameUtil::IsWin10TabSearchCaptionButtonEnabled( + BrowserView::GetBrowserViewForNativeWindow(frame->GetNativeWindow()) + ->browser())) { + size.set_width( + size.width() + WindowFrameUtil::kWindows10GlassCaptionButtonWidth + + WindowFrameUtil::kWindows10GlassCaptionButtonVisualSpacing); + } + return {0, size.width()}; + } + + // In this case, we use OpaqueBrowserFrameView. OpaqueBrowserFrameView has + // two types of frame button per platform but on Windows, it uses image + // buttons. See OpaqueBrowserFrameView::GetFrameButtonStyle(). + int width = 0; + // Uses image icons + const ui::ThemeProvider* tp = frame->GetThemeProvider(); + DCHECK(tp); + for (auto image_id : {IDR_MINIMIZE, IDR_MAXIMIZE, IDR_CLOSE}) { + if (const gfx::ImageSkia* image = tp->GetImageSkiaNamed(image_id)) + width += image->width(); + } + return {0, width}; +#else +#error "not handled platform" +#endif +} + } // namespace features } // namespace tabs diff --git a/browser/ui/views/tabs/features.h b/browser/ui/views/tabs/features.h index 08064b25fa3b..3d6348ad175b 100644 --- a/browser/ui/views/tabs/features.h +++ b/browser/ui/views/tabs/features.h @@ -6,12 +6,17 @@ #ifndef BRAVE_BROWSER_UI_VIEWS_TABS_FEATURES_H_ #define BRAVE_BROWSER_UI_VIEWS_TABS_FEATURES_H_ +#include + #include "base/compiler_specific.h" namespace base { struct LOGICALLY_CONST Feature; } // namespace base +class Browser; +class BrowserFrame; + namespace tabs { namespace features { @@ -20,6 +25,14 @@ extern const base::Feature kBraveVerticalTabs; // Returns true when users chose to use vertical tabs bool ShouldShowVerticalTabs(); +// Returns true when we should show window title on window frame when vertical +// tab strip is enabled. +bool ShouldShowWindowTitleForVerticalTabs(const Browser* browser); + +// Returns window caption buttons' width based on the current platform +std::pair GetLeadingTrailingCaptionButtonWidth( + const BrowserFrame* frame); + } // namespace features } // namespace tabs diff --git a/browser/ui/views/tabs/vertical_tab_strip_browsertest.cc b/browser/ui/views/tabs/vertical_tab_strip_browsertest.cc new file mode 100644 index 000000000000..eb18e5be45e8 --- /dev/null +++ b/browser/ui/views/tabs/vertical_tab_strip_browsertest.cc @@ -0,0 +1,119 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "base/test/scoped_feature_list.h" +#include "brave/browser/ui/browser_commands.h" +#include "brave/browser/ui/views/tabs/features.h" +#include "build/build_config.h" +#include "chrome/browser/ui/browser.h" +#include "chrome/browser/ui/views/frame/browser_non_client_frame_view.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "chrome/test/base/in_process_browser_test.h" +#include "content/public/test/browser_test.h" + +#if BUILDFLAG(IS_WIN) +#include "chrome/browser/ui/views/frame/glass_browser_frame_view.h" +#endif + +#if BUILDFLAG(IS_LINUX) +#include "chrome/common/pref_names.h" +#endif + +#if BUILDFLAG(IS_MAC) +#include "ui/views/widget/native_widget_mac.h" +#endif + +#if defined(USE_AURA) +#include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h" +#endif + +class VerticalTabStripBrowserTest : public InProcessBrowserTest { + public: + VerticalTabStripBrowserTest() + : feature_list_(tabs::features::kBraveVerticalTabs) {} + + ~VerticalTabStripBrowserTest() override = default; + + const BrowserView* browser_view() const { + return static_cast(browser()->window()); + } + BrowserView* browser_view() { + return static_cast(browser()->window()); + } + BrowserNonClientFrameView* browser_non_client_frame_view() { + return browser_view()->frame()->GetFrameView(); + } + const BrowserNonClientFrameView* browser_non_client_frame_view() const { + return browser_view()->frame()->GetFrameView(); + } + + // Returns the visibility of window title is actually changed by a frame or + // a widget. If we can't access to actual title view, returns a value which + // window title will be synchronized to. + bool IsWindowTitleViewVisible() const { +#if BUILDFLAG(IS_MAC) + auto* native_widget = static_cast( + browser_view()->GetWidget()->native_widget_private()); + if (!native_widget->has_overridden_window_title_visibility()) { + // Returns default visibility + return browser_view() + ->GetWidget() + ->widget_delegate() + ->ShouldShowWindowTitle(); + } + + return native_widget->GetOverriddenWindowTitleVisibility(); +#elif BUILDFLAG(IS_WIN) + if (browser_view()->GetWidget()->ShouldUseNativeFrame()) { + return static_cast( + browser_non_client_frame_view()) + ->window_title_for_testing() + ->GetVisible(); + } +#endif + +#if defined(USE_AURA) + return static_cast( + browser_non_client_frame_view()) + ->ShouldShowWindowTitle(); +#endif + } + + base::test::ScopedFeatureList feature_list_; +}; + +IN_PROC_BROWSER_TEST_F(VerticalTabStripBrowserTest, WindowTitle) { +#if BUILDFLAG(IS_LINUX) + browser()->profile()->GetPrefs()->SetBoolean(prefs::kUseCustomChromeFrame, + true); +#endif + // Pre-condition: Window title is "visible" by default on vertical tabs + ASSERT_TRUE(tabs::features::ShouldShowVerticalTabs()); + ASSERT_TRUE(tabs::features::ShouldShowWindowTitleForVerticalTabs(browser())); + ASSERT_TRUE(browser_view()->ShouldShowWindowTitle()); + ASSERT_TRUE(IsWindowTitleViewVisible()); + + // Hide window title bar + brave::ToggleWindowTitleVisibilityForVerticalTabs(browser()); + browser_non_client_frame_view()->Layout(); + EXPECT_FALSE(tabs::features::ShouldShowWindowTitleForVerticalTabs(browser())); + EXPECT_FALSE(browser_view()->ShouldShowWindowTitle()); +#if !BUILDFLAG(IS_LINUX) + // TODO(sko) For now, we can't hide window title bar entirely on Linux. + // We're using a minimum height for it. + EXPECT_EQ(0, + browser_non_client_frame_view()->GetTopInset(/*restored=*/false)); +#endif + EXPECT_FALSE(IsWindowTitleViewVisible()); + + // Show window title bar + brave::ToggleWindowTitleVisibilityForVerticalTabs(browser()); + browser_non_client_frame_view()->Layout(); + EXPECT_TRUE(tabs::features::ShouldShowWindowTitleForVerticalTabs(browser())); + EXPECT_TRUE(browser_view()->ShouldShowWindowTitle()); + EXPECT_GE(browser_non_client_frame_view()->GetTopInset(/*restored=*/false), + 0); + EXPECT_TRUE(IsWindowTitleViewVisible()); +} diff --git a/browser/ui/views/toolbar/brave_toolbar_view.cc b/browser/ui/views/toolbar/brave_toolbar_view.cc index e5240069789d..f42e85cee377 100644 --- a/browser/ui/views/toolbar/brave_toolbar_view.cc +++ b/browser/ui/views/toolbar/brave_toolbar_view.cc @@ -12,6 +12,8 @@ #include "base/bind.h" #include "brave/app/brave_command_ids.h" #include "brave/browser/brave_wallet/brave_wallet_context_utils.h" +#include "brave/browser/ui/tabs/brave_tab_prefs.h" +#include "brave/browser/ui/views/tabs/features.h" #include "brave/browser/ui/views/toolbar/bookmark_button.h" #include "brave/browser/ui/views/toolbar/wallet_button.h" #include "brave/components/brave_vpn/buildflags/buildflags.h" @@ -28,8 +30,10 @@ #include "chrome/browser/ui/views/bookmarks/bookmark_bubble_view.h" #include "components/bookmarks/common/bookmark_pref_names.h" #include "components/prefs/pref_service.h" +#include "ui/base/hit_test.h" #include "ui/base/window_open_disposition.h" #include "ui/events/event.h" +#include "ui/views/window/hit_test_utils.h" #if BUILDFLAG(ENABLE_BRAVE_VPN) #include "brave/browser/brave_vpn/vpn_utils.h" @@ -115,6 +119,9 @@ BraveToolbarView::~BraveToolbarView() = default; void BraveToolbarView::Init() { ToolbarView::Init(); + // This will allow us to move this window by dragging toolbar + views::SetHitTestComponent(this, HTCAPTION); + // For non-normal mode, we don't have to more. if (display_mode_ != DisplayMode::NORMAL) { brave_initialized_ = true; @@ -143,6 +150,16 @@ void BraveToolbarView::Init() { base::BindRepeating(&BraveToolbarView::OnLocationBarIsWideChanged, base::Unretained(this))); + if (tabs::features::ShouldShowVerticalTabs()) { + show_title_bar_on_vertical_tabs_.Init( + brave_tabs::kVerticalTabsShowTitleOnWindow, + profile->GetOriginalProfile()->GetPrefs(), + base::BindRepeating( + &BraveToolbarView::OnShowTitleBarOnVerticalTabsChanged, + base::Unretained(this))); + OnShowTitleBarOnVerticalTabsChanged(); + } + const auto callback = [](Browser* browser, int command, const ui::Event& event) { chrome::ExecuteCommandWithDisposition( @@ -265,6 +282,18 @@ void BraveToolbarView::UpdateBookmarkVisibility() { show_bookmarks_button_.GetValue()); } +void BraveToolbarView::OnShowTitleBarOnVerticalTabsChanged() { + if (tabs::features::ShouldShowWindowTitleForVerticalTabs(browser())) { + SetBorder(nullptr); + } else { + auto [leading, trailing] = + tabs::features::GetLeadingTrailingCaptionButtonWidth( + browser_view_->frame()); + SetBorder(views::CreateEmptyBorder( + gfx::Insets().set_left(leading).set_right(trailing))); + } +} + void BraveToolbarView::ShowBookmarkBubble( const GURL& url, bool already_bookmarked, @@ -284,6 +313,17 @@ void BraveToolbarView::ShowBookmarkBubble( browser_->profile(), url, already_bookmarked); } +void BraveToolbarView::ViewHierarchyChanged( + const views::ViewHierarchyChangedDetails& details) { + ToolbarView::ViewHierarchyChanged(details); + + if (details.is_add && details.parent == this) { + // Mark children of this view as client area so that they are not perceived + // as client area. + views::SetHitTestComponent(details.child, HTCLIENT); + } +} + void BraveToolbarView::Layout() { ToolbarView::Layout(); diff --git a/browser/ui/views/toolbar/brave_toolbar_view.h b/browser/ui/views/toolbar/brave_toolbar_view.h index f5fb097fddd3..abe1239405ca 100644 --- a/browser/ui/views/toolbar/brave_toolbar_view.h +++ b/browser/ui/views/toolbar/brave_toolbar_view.h @@ -44,12 +44,15 @@ class BraveToolbarView : public ToolbarView, void ShowBookmarkBubble(const GURL& url, bool already_bookmarked, bookmarks::BookmarkBubbleObserver* observer) override; + void ViewHierarchyChanged( + const views::ViewHierarchyChangedDetails& details) override; private: void LoadImages() override; void ResetLocationBarBounds(); void ResetButtonBounds(); void UpdateBookmarkVisibility(); + void OnShowTitleBarOnVerticalTabsChanged(); // ProfileAttributesStorage::Observer: void OnProfileAdded(const base::FilePath& profile_path) override; @@ -70,6 +73,9 @@ class BraveToolbarView : public ToolbarView, BooleanPrefMember show_bookmarks_button_; BooleanPrefMember location_bar_is_wide_; + + BooleanPrefMember show_title_bar_on_vertical_tabs_; + // Whether this toolbar has been initialized. bool brave_initialized_ = false; // Tracks profile count to determine whether profile switcher should be shown. diff --git a/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_layout_linux.cc b/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_layout_linux.cc index db3b10a0a638..b401c437974d 100644 --- a/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_layout_linux.cc +++ b/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_layout_linux.cc @@ -3,14 +3,46 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include "base/check_is_test.h" #include "brave/browser/ui/views/tabs/features.h" +#include "chrome/browser/ui/views/frame/browser_view.h" +#include "ui/views/window/caption_button_layout_constants.h" #include "src/chrome/browser/ui/views/frame/browser_frame_view_layout_linux.cc" int BrowserFrameViewLayoutLinux::NonClientTopHeight(bool restored) const { - if (tabs::features::ShouldShowVerticalTabs()) { - // Set minimum height to show caption buttons. - return 50; + if (!view_) { + CHECK_IS_TEST(); + return OpaqueBrowserFrameViewLayout::NonClientTopHeight(restored); + } + + if (view_->browser_view()->browser()->is_type_normal() && + tabs::features::ShouldShowVerticalTabs()) { + if (!view_->ShouldShowCaptionButtons()) { + // In this case, the window manager might be forcibly providing system + // window title or it's in fullscreen mode. We shouldn't show title bar + // in this case. + return OpaqueBrowserFrameViewLayout::NonClientTopHeight(restored); + } + + // TODO(sko) For now, I couldn't find a way to overlay caption buttons + // on toolbar. Once it gets possible, we shouldn't reserve non client top + // height when window title isn't visible. + + // Adding 2px of vertical padding puts at least 1 px of space on the top and + // bottom of the element. + constexpr int kVerticalPadding = 2; + // delegate_->GetIconSize() also considers the default font's height so + // title will be visible. + const int icon_height = FrameEdgeInsets(restored).top() + + delegate_->GetIconSize() + kVerticalPadding; + + const int caption_button_height = + DefaultCaptionButtonY(restored) + + 18 /*kCaptionButtonHeight in OpaqueBrowserFrameView*/ + + kCaptionButtonBottomPadding; + return std::max(icon_height, caption_button_height) + + kCaptionButtonBottomPadding; } return OpaqueBrowserFrameViewLayout::NonClientTopHeight(restored); diff --git a/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_linux.cc b/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_linux.cc new file mode 100644 index 000000000000..61728bbfa759 --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_linux.cc @@ -0,0 +1,14 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "chrome/browser/ui/views/frame/browser_frame_view_linux.h" +#include "brave/browser/ui/views/frame/brave_opaque_browser_frame_view.h" + +#define OpaqueBrowserFrameView(frame, browser_view, layout) \ + BraveOpaqueBrowserFrameView(frame, browser_view, layout) + +#include "src/chrome/browser/ui/views/frame/browser_frame_view_linux.cc" + +#undef OpaqueBrowserFrameView diff --git a/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_linux.h b/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_linux.h new file mode 100644 index 000000000000..8d4d087bcbc0 --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/frame/browser_frame_view_linux.h @@ -0,0 +1,24 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_VIEW_LINUX_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_VIEW_LINUX_H_ + +#include "chrome/browser/ui/views/frame/opaque_browser_frame_view.h" + +// Make BrowserFrameViewLinux extends our BraveOpaqueBrowserFrameView +#include "brave/browser/ui/views/frame/brave_opaque_browser_frame_view.h" +#define OpaqueBrowserFrameView BraveOpaqueBrowserFrameView + +#include "src/chrome/browser/ui/views/frame/browser_frame_view_linux.h" + +#undef OpaqueBrowserFrameView + +// Sanity check at compile time. +static_assert( + std::is_base_of_v, + "BrowserFrameViewLinux should be a child of BraveOpaqueBrowserFrameView"); + +#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_FRAME_VIEW_LINUX_H_ diff --git a/chromium_src/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc b/chromium_src/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc index 5b4449f063e7..f42435020d29 100644 --- a/chromium_src/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc +++ b/chromium_src/chrome/browser/ui/views/frame/browser_non_client_frame_view_factory_views.cc @@ -3,6 +3,9 @@ * License, v. 2.0. If a copy of the MPL was not distributed with this file, * You can obtain one at http://mozilla.org/MPL/2.0/. */ +#include +#include + #include "build/build_config.h" #if BUILDFLAG(IS_WIN) @@ -10,6 +13,10 @@ #define GlassBrowserFrameView BraveGlassBrowserFrameView #endif +// This file is included for all platform by upstream source code and we need +// to include this first to avoid #define conflicts. +#include "chrome/browser/ui/views/frame/browser_frame_view_linux.h" + #include "brave/browser/ui/views/frame/brave_opaque_browser_frame_view.h" #define OpaqueBrowserFrameView BraveOpaqueBrowserFrameView @@ -17,6 +24,14 @@ #undef OpaqueBrowserFrameView +// A sanity check for our macro +static_assert( + std::is_same_v, + decltype(std::function{ + chrome::CreateOpaqueBrowserFrameView})::result_type>, + "CreateOpaqueBrowserFrameView is not returning " + "BraveOpaqueBrowserFrameView"); + #if BUILDFLAG(IS_WIN) #undef GlassBrowserFrameView #endif diff --git a/chromium_src/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h b/chromium_src/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h new file mode 100644 index 000000000000..4205e315c551 --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_MAC_H_ +#define BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_MAC_H_ + +#define PaintThemedFrame \ + PaintThemedFrame_Unused() {} \ + friend class BraveBrowserNonClientFrameViewMac; \ + void PaintThemedFrame + +#include "src/chrome/browser/ui/views/frame/browser_non_client_frame_view_mac.h" + +#undef PaintThemedFrame + +#endif // BRAVE_CHROMIUM_SRC_CHROME_BROWSER_UI_VIEWS_FRAME_BROWSER_NON_CLIENT_FRAME_VIEW_MAC_H_ diff --git a/chromium_src/chrome/browser/ui/views/frame/native_browser_frame_factory_mac.mm b/chromium_src/chrome/browser/ui/views/frame/native_browser_frame_factory_mac.mm new file mode 100644 index 000000000000..3009d2263c6a --- /dev/null +++ b/chromium_src/chrome/browser/ui/views/frame/native_browser_frame_factory_mac.mm @@ -0,0 +1,12 @@ +/* Copyright 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/ui/views/frame/brave_browser_frame_mac.h" + +#define BrowserFrameMac BraveBrowserFrameMac + +#include "src/chrome/browser/ui/views/frame/native_browser_frame_factory_mac.mm" + +#undef BrowserFrameMac diff --git a/chromium_src/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h b/chromium_src/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h new file mode 100644 index 000000000000..def28564a064 --- /dev/null +++ b/chromium_src/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h @@ -0,0 +1,18 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_NS_WINDOW_BRIDGE_H_ +#define BRAVE_CHROMIUM_SRC_COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_NS_WINDOW_BRIDGE_H_ + +// Override a method from our NativeWidgetNSWindow mojo extension +#define OnSizeChanged \ + SetWindowTitleVisibility(bool visible) override; \ + void OnSizeChanged + +#include "src/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h" + +#undef OnSizeChanged + +#endif // BRAVE_CHROMIUM_SRC_COMPONENTS_REMOTE_COCOA_APP_SHIM_NATIVE_WIDGET_NS_WINDOW_BRIDGE_H_ diff --git a/chromium_src/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm b/chromium_src/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm new file mode 100644 index 000000000000..3871e71dee08 --- /dev/null +++ b/chromium_src/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm @@ -0,0 +1,28 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "src/components/remote_cocoa/app_shim/native_widget_ns_window_bridge.mm" + +namespace remote_cocoa { + +void NativeWidgetNSWindowBridge::SetWindowTitleVisibility(bool visible) { + NSUInteger style_mask = [window_ styleMask]; + if (visible) + style_mask |= NSWindowStyleMaskTitled; + else + style_mask &= ~NSWindowStyleMaskTitled; + + [window_ setStyleMask:style_mask]; + + // Sometimes title is not visible until window is resized. In order to avoid + // this, reset title to force it to be visible. + if (visible) { + NSString* title = window_.get().title; + window_.get().title = @""; + window_.get().title = title; + } +} + +} // namespace remote_cocoa diff --git a/chromium_src/components/remote_cocoa/common/native_widget_ns_window.mojom b/chromium_src/components/remote_cocoa/common/native_widget_ns_window.mojom new file mode 100644 index 000000000000..8dafb1654935 --- /dev/null +++ b/chromium_src/components/remote_cocoa/common/native_widget_ns_window.mojom @@ -0,0 +1,11 @@ +// Copyright (c) 2022 The Brave Authors. All rights reserved. +// This Source Code Form is subject to the terms of the Mozilla Public +// License, v. 2.0. If a copy of the MPL was not distributed with this file, +// You can obtain one at http://mozilla.org/MPL/2.0/. + +module remote_cocoa.mojom; + +[BraveExtend] +interface NativeWidgetNSWindow { + SetWindowTitleVisibility(bool visible); +}; diff --git a/chromium_src/ui/views/cocoa/native_widget_mac_ns_window_host.h b/chromium_src/ui/views/cocoa/native_widget_mac_ns_window_host.h new file mode 100644 index 000000000000..a51013bbb0da --- /dev/null +++ b/chromium_src/ui/views/cocoa/native_widget_mac_ns_window_host.h @@ -0,0 +1,17 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NS_WINDOW_HOST_H_ +#define BRAVE_CHROMIUM_SRC_UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NS_WINDOW_HOST_H_ + +#define OnWidgetInitDone \ + SetWindowTitleVisibility(bool visible); \ + void OnWidgetInitDone + +#include "src/ui/views/cocoa/native_widget_mac_ns_window_host.h" + +#undef OnWidgetInitDone + +#endif // BRAVE_CHROMIUM_SRC_UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NS_WINDOW_HOST_H_ diff --git a/chromium_src/ui/views/cocoa/native_widget_mac_ns_window_host.mm b/chromium_src/ui/views/cocoa/native_widget_mac_ns_window_host.mm new file mode 100644 index 000000000000..8c549ad77fce --- /dev/null +++ b/chromium_src/ui/views/cocoa/native_widget_mac_ns_window_host.mm @@ -0,0 +1,14 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "src/ui/views/cocoa/native_widget_mac_ns_window_host.mm" + +namespace views { + +void NativeWidgetMacNSWindowHost::SetWindowTitleVisibility(bool visible) { + GetNSWindowMojo()->SetWindowTitleVisibility(visible); +} + +} // namespace views diff --git a/chromium_src/ui/views/widget/native_widget_mac.h b/chromium_src/ui/views/widget/native_widget_mac.h new file mode 100644 index 000000000000..b04733190615 --- /dev/null +++ b/chromium_src/ui/views/widget/native_widget_mac.h @@ -0,0 +1,28 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_UI_VIEWS_WIDGET_NATIVE_WIDGET_MAC_H_ +#define BRAVE_CHROMIUM_SRC_UI_VIEWS_WIDGET_NATIVE_WIDGET_MAC_H_ + +#include "ui/views/widget/native_widget_private.h" + +#define SetWindowIcons \ + SetWindowTitleVisibility(bool visible); \ + bool has_overridden_window_title_visibility() const { \ + return overridden_window_title_visibility_.has_value(); \ + } \ + bool GetOverriddenWindowTitleVisibility() const; \ + \ + private: \ + absl::optional overridden_window_title_visibility_; \ + \ + public: \ + void SetWindowIcons + +#include "src/ui/views/widget/native_widget_mac.h" + +#undef SetWindowIcons + +#endif // BRAVE_CHROMIUM_SRC_UI_VIEWS_WIDGET_NATIVE_WIDGET_MAC_H_ diff --git a/chromium_src/ui/views/widget/native_widget_mac.mm b/chromium_src/ui/views/widget/native_widget_mac.mm new file mode 100644 index 000000000000..d6e2c5ec29eb --- /dev/null +++ b/chromium_src/ui/views/widget/native_widget_mac.mm @@ -0,0 +1,27 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "src/ui/views/widget/native_widget_mac.mm" + +namespace views { + +void NativeWidgetMac::SetWindowTitleVisibility(bool visible) { + if (overridden_window_title_visibility_.has_value() && + visible == *overridden_window_title_visibility_) { + return; + } + + GetNSWindowMojo()->SetWindowTitleVisibility(visible); + overridden_window_title_visibility_ = visible; +} + +bool NativeWidgetMac::GetOverriddenWindowTitleVisibility() const { + DCHECK(has_overridden_window_title_visibility()) + << "Didn't call SetWindowTitleVisibility(). Use " + "WidgetDelegate::ShouldShowWindowTitle() instead."; + return *overridden_window_title_visibility_; +} + +} // namespace views diff --git a/chromium_src/ui/views/widget/widget.cc b/chromium_src/ui/views/widget/widget.cc new file mode 100644 index 000000000000..aa7f9d765709 --- /dev/null +++ b/chromium_src/ui/views/widget/widget.cc @@ -0,0 +1,21 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "src/ui/views/widget/widget.cc" + +#if BUILDFLAG(IS_MAC) + +#include "ui/views/widget/native_widget_mac.h" + +namespace views { + +void Widget::SetWindowTitleVisibility(bool visible) { + static_cast(native_widget_) + ->SetWindowTitleVisibility(visible); +} + +} // namespace views + +#endif // defined(OS_MAC) diff --git a/chromium_src/ui/views/widget/widget.h b/chromium_src/ui/views/widget/widget.h new file mode 100644 index 000000000000..65e7e3e1489f --- /dev/null +++ b/chromium_src/ui/views/widget/widget.h @@ -0,0 +1,23 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_CHROMIUM_SRC_UI_VIEWS_WIDGET_WIDGET_H_ +#define BRAVE_CHROMIUM_SRC_UI_VIEWS_WIDGET_WIDGET_H_ + +#include "build/build_config.h" + +#if BUILDFLAG(IS_MAC) +#define UnlockPaintAsActive \ + SetWindowTitleVisibility(bool visible); \ + void UnlockPaintAsActive +#else +#define UnlockPaintAsActive UnlockPaintAsActive +#endif + +#include "src/ui/views/widget/widget.h" + +#undef UnlockPaintAsActive + +#endif // BRAVE_CHROMIUM_SRC_UI_VIEWS_WIDGET_WIDGET_H_ diff --git a/test/BUILD.gn b/test/BUILD.gn index b08678970722..509726b4d2bd 100644 --- a/test/BUILD.gn +++ b/test/BUILD.gn @@ -1067,11 +1067,13 @@ test("brave_browser_tests") { "//brave/browser/ui/views/brave_actions/brave_actions_container_browsertest.cc", "//brave/browser/ui/views/brave_ads/notification_ad_popup_browsertest.cc", "//brave/browser/ui/views/brave_shields/cookie_list_opt_in_browsertest.cc", + "//brave/browser/ui/views/frame/brave_non_client_hit_test_helper_browsertest.cc", "//brave/browser/ui/views/frame/brave_tabs_search_button_browsertest.cc", "//brave/browser/ui/views/omnibox/brave_omnibox_view_views_browsertest.cc", "//brave/browser/ui/views/omnibox/omnibox_autocomplete_browsertest.cc", "//brave/browser/ui/views/profiles/brave_profile_menu_view_browsertest.cc", "//brave/browser/ui/views/tabs/brave_tab_context_menu_contents_browsertest.cc", + "//brave/browser/ui/views/tabs/vertical_tab_strip_browsertest.cc", "//brave/browser/ui/views/toolbar/brave_toolbar_view_browsertest.cc", "//brave/browser/ui/views/toolbar/wallet_button_browsertest.cc", ]