Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't merge - this is a CI run for https://github.com/brave/brave-core/pull/19785 #20081

Merged
merged 12 commits into from
Sep 19, 2023
2 changes: 2 additions & 0 deletions browser/ui/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -798,6 +798,8 @@ source_set("ui") {
"views/brave_actions/brave_shields_action_view.h",
"views/frame/vertical_tab_strip_region_view.cc",
"views/frame/vertical_tab_strip_region_view.h",
"views/frame/vertical_tab_strip_root_view.cc",
"views/frame/vertical_tab_strip_root_view.h",
"views/frame/vertical_tab_strip_widget_delegate_view.cc",
"views/frame/vertical_tab_strip_widget_delegate_view.h",
"views/location_bar/brave_location_bar_view.cc",
Expand Down
71 changes: 71 additions & 0 deletions browser/ui/views/frame/vertical_tab_strip_root_view.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/* Copyright (c) 2023 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 https://mozilla.org/MPL/2.0/. */

#include "brave/browser/ui/views/frame/vertical_tab_strip_root_view.h"

#include "chrome/browser/ui/views/frame/browser_root_view.h"
#include "ui/base/metadata/metadata_impl_macros.h"
#include "ui/views/view_utils.h"

VerticalTabStripRootView::VerticalTabStripRootView(BrowserView* browser_view,
views::Widget* widget)
: BrowserRootView(browser_view, widget) {}

VerticalTabStripRootView::~VerticalTabStripRootView() = default;

bool VerticalTabStripRootView::OnMousePressed(const ui::MouseEvent& event) {
#if defined(USE_AURA)
const bool result = RootView::OnMousePressed(event);
auto* focus_manager = GetFocusManager();
DCHECK(focus_manager);

// When vertical tab strip area is clicked, shortcut handling process
// could get broken on Windows. There are 2 paths where shortcut is handled.
// One is BrowserView::AcceleratorPressed(), and the other is
// BrowserView::PreHandleKeyboardEvent(). When web view has focus, the
// first doesn't deal with it and the latter is responsible for the
// shortcuts. when users click the vertical tab strip area with web view
// focused, both path don't handle it. This is because focused view state of
// views/ framework and focused native window state of Aura is out of sync.
// So as a workaround, resets the focused view state so that shortcuts can
// be handled properly. This shouldn't change the actually focused view, and
// is just reset the status.
// https://github.com/brave/brave-browser/issues/28090
// https://github.com/brave/brave-browser/issues/27812
if (auto* focused_view = focus_manager->GetFocusedView();
focused_view && views::IsViewClass<views::WebView>(focused_view)) {
focus_manager->ClearFocus();
focus_manager->RestoreFocusedView();
}

return result;
#else
// On Mac, the parent widget doesn't get activated in this case. Then
// shortcut handling could malfunction. So activate it.
// https://github.com/brave/brave-browser/issues/29993
auto* widget = GetWidget();
DCHECK(widget);
widget = widget->GetTopLevelWidget();
widget->Activate();

return RootView::OnMousePressed(event);
#endif
}

bool VerticalTabStripRootView::OnMouseWheel(const ui::MouseWheelEvent& event) {
return views::internal::RootView::OnMouseWheel(event);
}

void VerticalTabStripRootView::OnMouseExited(const ui::MouseEvent& event) {
views::internal::RootView::OnMouseExited(event);
}

void VerticalTabStripRootView::PaintChildren(
const views::PaintInfo& paint_info) {
views::internal::RootView::PaintChildren(paint_info);
}

BEGIN_METADATA(VerticalTabStripRootView, BrowserRootView)
END_METADATA
32 changes: 32 additions & 0 deletions browser/ui/views/frame/vertical_tab_strip_root_view.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/* Copyright (c) 2023 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 https://mozilla.org/MPL/2.0/. */

#ifndef BRAVE_BROWSER_UI_VIEWS_FRAME_VERTICAL_TAB_STRIP_ROOT_VIEW_H_
#define BRAVE_BROWSER_UI_VIEWS_FRAME_VERTICAL_TAB_STRIP_ROOT_VIEW_H_

#include "chrome/browser/ui/views/frame/browser_root_view.h"

// `VerticalTabStripRootView` extends `BrowserRootView` to support link
// drag-and-drop feature. In order to avoid features other than that, replaces
// mouse event callbacks and bypass the `BrowserRootView`'s implementation. e.g.
// OnMouseWheel()
class VerticalTabStripRootView : public BrowserRootView {
public:
METADATA_HEADER(VerticalTabStripRootView);

VerticalTabStripRootView(BrowserView* browser_view, views::Widget* widget);

~VerticalTabStripRootView() override;

// BrowserRootView:
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseWheel(const ui::MouseWheelEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;

protected:
void PaintChildren(const views::PaintInfo& paint_info) override;
};

#endif // BRAVE_BROWSER_UI_VIEWS_FRAME_VERTICAL_TAB_STRIP_ROOT_VIEW_H_
158 changes: 158 additions & 0 deletions browser/ui/views/frame/vertical_tab_strip_root_view_browsertest.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
/* Copyright (c) 2023 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 https://mozilla.org/MPL/2.0/. */

#include "brave/browser/ui/browser_commands.h"
#include "brave/browser/ui/views/frame/brave_browser_view.h"
#include "brave/browser/ui/views/frame/vertical_tab_strip_region_view.h"
#include "brave/browser/ui/views/frame/vertical_tab_strip_root_view.h"
#include "brave/browser/ui/views/frame/vertical_tab_strip_widget_delegate_view.h"
#include "brave/browser/ui/views/tabs/vertical_tab_utils.h"
#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/tabs/tab_strip.h"
#include "chrome/test/base/in_process_browser_test.h"
#include "content/public/test/browser_test.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drop_target_event.h"
#include "ui/base/dragdrop/mojom/drag_drop_types.mojom.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/compositor/layer_tree_owner.h"

class VerticalTabStripRootViewBrowserTest : public InProcessBrowserTest {
public:
VerticalTabStripRootViewBrowserTest() = default;
VerticalTabStripRootViewBrowserTest(
const VerticalTabStripRootViewBrowserTest&) = delete;
VerticalTabStripRootViewBrowserTest& operator=(
const VerticalTabStripRootViewBrowserTest&) = delete;
~VerticalTabStripRootViewBrowserTest() override = default;

Tab* GetTabAt(int index) { return tab_strip()->tab_at(index); }

BrowserView* browser_view() {
return BrowserView::GetBrowserViewForBrowser(browser());
}

TabStrip* tab_strip() { return browser_view()->tabstrip(); }

VerticalTabStripRootView* vtab_strip_root_view() {
if (vtab_tab_strip_widget_delegate_view()) {
return static_cast<VerticalTabStripRootView*>(
vtab_tab_strip_widget_delegate_view()->GetWidget()->GetRootView());
}
return nullptr;
}

BrowserNonClientFrameView* browser_non_client_frame_view() {
return browser_view()->frame()->GetFrameView();
}

void ToggleVerticalTabStrip() {
brave::ToggleVerticalTabStrip(browser());
browser_non_client_frame_view()->Layout();
}

VerticalTabStripWidgetDelegateView* vtab_tab_strip_widget_delegate_view() {
auto* browser_view = static_cast<BraveBrowserView*>(
BrowserView::GetBrowserViewForBrowser(browser()));
if (browser_view) {
return browser_view->vertical_tab_strip_widget_delegate_view();
}
return nullptr;
}
};

#if BUILDFLAG(IS_WIN)
// This test is flaky on Windows.
#define MAYBE_DragAfterCurrentTab DISABLED_DragAfterCurrentTab
#else
#define MAYBE_DragAfterCurrentTab DragAfterCurrentTab
#endif

IN_PROC_BROWSER_TEST_F(VerticalTabStripRootViewBrowserTest,
MAYBE_DragAfterCurrentTab) {
ToggleVerticalTabStrip();

ASSERT_TRUE(tabs::utils::ShouldShowVerticalTabs(browser()));

auto* tab_strip_model = browser()->tab_strip_model();
EXPECT_EQ(tab_strip_model->count(), 1);

ui::OSExchangeData data;
GURL url("https://brave.com/");
data.SetURL(url, std::u16string());

Tab* current_tab = GetTabAt(0);
gfx::Point location;
views::View::ConvertPointToWidget(current_tab, &location);

// To drag after current tab.
location.Offset(0, current_tab->height());
ui::DropTargetEvent event(data, gfx::PointF(location), gfx::PointF(location),
ui::DragDropTypes::DRAG_COPY);

VerticalTabStripRootView* root_view = vtab_strip_root_view();

EXPECT_NE(root_view, nullptr);
root_view->OnDragUpdated(event);
auto drop_cb = root_view->GetDropCallback(event);
ui::mojom::DragOperation output_drag_op = ui::mojom::DragOperation::kNone;
std::move(drop_cb).Run(event, output_drag_op,
/*drag_image_layer_owner=*/nullptr);

EXPECT_EQ(output_drag_op, ui::mojom::DragOperation::kCopy);
EXPECT_EQ(tab_strip_model->count(), 2);
EXPECT_TRUE(browser()
->tab_strip_model()
->GetWebContentsAt(1)
->GetURL()
.EqualsIgnoringRef(url));
}

#if BUILDFLAG(IS_WIN)
// This test is flaky on Windows.
#define MAYBE_DragOnCurrentTab DISABLED_DragOnCurrentTab
#else
#define MAYBE_DragOnCurrentTab DragOnCurrentTab
#endif
IN_PROC_BROWSER_TEST_F(VerticalTabStripRootViewBrowserTest,
MAYBE_DragOnCurrentTab) {
ToggleVerticalTabStrip();

ASSERT_TRUE(tabs::utils::ShouldShowVerticalTabs(browser()));

auto* tab_strip_model = browser()->tab_strip_model();
EXPECT_EQ(tab_strip_model->count(), 1);

ui::OSExchangeData data;
GURL url("https://brave.com/");
data.SetURL(url, std::u16string());

Tab* current_tab = GetTabAt(0);
gfx::Point location;
views::View::ConvertPointToWidget(current_tab, &location);

// To drag on the same tab.
location.Offset(0, current_tab->height() / 2);
ui::DropTargetEvent event(data, gfx::PointF(location), gfx::PointF(location),
ui::DragDropTypes::DRAG_COPY);

VerticalTabStripRootView* root_view = vtab_strip_root_view();

EXPECT_NE(root_view, nullptr);
root_view->OnDragUpdated(event);
auto drop_cb = root_view->GetDropCallback(event);
ui::mojom::DragOperation output_drag_op = ui::mojom::DragOperation::kNone;
std::move(drop_cb).Run(event, output_drag_op,
/*drag_image_layer_owner=*/nullptr);

EXPECT_EQ(output_drag_op, ui::mojom::DragOperation::kCopy);
EXPECT_EQ(tab_strip_model->count(), 1);
EXPECT_TRUE(browser()
->tab_strip_model()
->GetWebContentsAt(0)
->GetURL()
.EqualsIgnoringRef(url));
}
Loading