Commit b405799a authored by Collin Baker's avatar Collin Baker Committed by Commit Bot

Autoclose tab strip container on events outside the container

Bug: 1009122
Change-Id: I64e48c638b403911a8879ff1fa7b290628373bd9
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1877454
Commit-Queue: Collin Baker <collinbaker@chromium.org>
Reviewed-by: default avatarPeter Boström <pbos@chromium.org>
Cr-Commit-Position: refs/heads/master@{#709304}
parent 5a85445c
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#include <utility> #include <utility>
#include "base/logging.h" #include "base/logging.h"
#include "base/scoped_observer.h"
#include "chrome/app/chrome_command_ids.h" #include "chrome/app/chrome_command_ids.h"
#include "chrome/app/vector_icons/vector_icons.h" #include "chrome/app/vector_icons/vector_icons.h"
#include "chrome/browser/extensions/chrome_extension_web_contents_observer.h" #include "chrome/browser/extensions/chrome_extension_web_contents_observer.h"
...@@ -22,6 +23,7 @@ ...@@ -22,6 +23,7 @@
#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h" #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui_layout.h"
#include "chrome/common/webui_url_constants.h" #include "chrome/common/webui_url_constants.h"
#include "chrome/grit/generated_resources.h" #include "chrome/grit/generated_resources.h"
#include "ui/aura/window.h"
#include "ui/base/l10n/l10n_util.h" #include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h" #include "ui/gfx/color_palette.h"
#include "ui/gfx/paint_vector_icon.h" #include "ui/gfx/paint_vector_icon.h"
...@@ -31,6 +33,113 @@ ...@@ -31,6 +33,113 @@
#include "ui/views/layout/fill_layout.h" #include "ui/views/layout/fill_layout.h"
#include "ui/views/layout/flex_layout.h" #include "ui/views/layout/flex_layout.h"
#include "ui/views/view_class_properties.h" #include "ui/views/view_class_properties.h"
#include "ui/views/view_observer.h"
#include "ui/views/widget/widget.h"
namespace {
bool EventTypeCanCloseTabStrip(const ui::EventType& type) {
switch (type) {
case ui::ET_MOUSE_PRESSED:
case ui::ET_TOUCH_PRESSED:
case ui::ET_GESTURE_TAP:
case ui::ET_GESTURE_DOUBLE_TAP:
return true;
default:
return false;
}
}
} // namespace
// When enabled, closes the container upon any event in the window not
// destined for the container and cancels the event. If an event is
// destined for the container, it passes it through.
class WebUITabStripContainerView::AutoCloser : public ui::EventHandler,
public views::ViewObserver {
public:
AutoCloser(views::View* container,
base::RepeatingClosure close_container_callback)
: container_(container),
close_container_callback_(std::move(close_container_callback)),
view_observer_(this) {
view_observer_.Add(container);
WidgetChanged();
// Our observed Widget's NativeView may be destroyed before us. We
// have no reasonable way of un-registering our pre-target handler
// from the NativeView while the Widget is destroying. This disables
// EventHandler's check that it has been removed from all
// EventTargets.
DisableCheckTargets();
}
~AutoCloser() override {
// If |container_| was in a Widget and that Widget still has its
// NativeView, remove ourselves from it. Otherwise, the NativeView
// is already destroying so we don't need to do anything.
if (last_widget_ && last_widget_->GetNativeView())
last_widget_->GetNativeView()->RemovePreTargetHandler(this);
}
// Sets whether to inspect events. If not enabled, all events are
// ignored and passed through as usual.
void set_enabled(bool enabled) { enabled_ = enabled; }
// ui::EventHandler:
void OnEvent(ui::Event* event) override {
if (!enabled_)
return;
if (!event->IsLocatedEvent())
return;
ui::LocatedEvent* located_event = event->AsLocatedEvent();
// Let any events destined for |container_| pass through.
const gfx::Rect container_bounds_in_window =
container_->ConvertRectToWidget(container_->GetLocalBounds());
if (container_bounds_in_window.Contains(located_event->root_location()))
return;
// Upon any user action outside |container_|, cancel the event and close the
// container.
if (EventTypeCanCloseTabStrip(located_event->type())) {
located_event->StopPropagation();
close_container_callback_.Run();
}
}
// views::ViewObserver:
void OnViewAddedToWidget(views::View* observed_view) override {
DCHECK_EQ(container_, observed_view);
WidgetChanged();
}
void OnViewRemovedFromWidget(views::View* observed_view) override {
DCHECK_EQ(container_, observed_view);
WidgetChanged();
}
private:
// Handle when |container_| is added to a new Widget or removed from
// its Widget.
void WidgetChanged() {
views::Widget* new_widget = container_->GetWidget();
if (new_widget == last_widget_)
return;
if (last_widget_)
last_widget_->GetNativeView()->RemovePreTargetHandler(this);
if (new_widget)
new_widget->GetNativeView()->AddPreTargetHandler(this);
last_widget_ = new_widget;
}
views::View* const container_;
base::RepeatingClosure close_container_callback_;
views::Widget* last_widget_ = nullptr;
ScopedObserver<View, ViewObserver> view_observer_;
bool enabled_ = false;
};
WebUITabStripContainerView::WebUITabStripContainerView( WebUITabStripContainerView::WebUITabStripContainerView(
Browser* browser, Browser* browser,
...@@ -38,7 +147,11 @@ WebUITabStripContainerView::WebUITabStripContainerView( ...@@ -38,7 +147,11 @@ WebUITabStripContainerView::WebUITabStripContainerView(
: browser_(browser), : browser_(browser),
web_view_( web_view_(
AddChildView(std::make_unique<views::WebView>(browser->profile()))), AddChildView(std::make_unique<views::WebView>(browser->profile()))),
tab_contents_container_(tab_contents_container) { tab_contents_container_(tab_contents_container),
auto_closer_(std::make_unique<AutoCloser>(
this,
base::Bind(&WebUITabStripContainerView::CloseContainer,
base::Unretained(this)))) {
SetVisible(false); SetVisible(false);
// TODO(crbug.com/1010589) WebContents are initially assumed to be visible by // TODO(crbug.com/1010589) WebContents are initially assumed to be visible by
// default unless explicitly hidden. The WebContents need to be set to hidden // default unless explicitly hidden. The WebContents need to be set to hidden
...@@ -95,6 +208,7 @@ void WebUITabStripContainerView::CloseContainer() { ...@@ -95,6 +208,7 @@ void WebUITabStripContainerView::CloseContainer() {
if (!GetVisible()) if (!GetVisible())
return; return;
SetVisible(false); SetVisible(false);
auto_closer_->set_enabled(false);
InvalidateLayout(); InvalidateLayout();
} }
...@@ -125,6 +239,7 @@ void WebUITabStripContainerView::ButtonPressed(views::Button* sender, ...@@ -125,6 +239,7 @@ void WebUITabStripContainerView::ButtonPressed(views::Button* sender,
if (sender->GetID() == VIEW_ID_WEBUI_TAB_STRIP_TOGGLE_BUTTON) { if (sender->GetID() == VIEW_ID_WEBUI_TAB_STRIP_TOGGLE_BUTTON) {
// TODO(pbos): Trigger a slide animation here. // TODO(pbos): Trigger a slide animation here.
SetVisible(!GetVisible()); SetVisible(!GetVisible());
auto_closer_->set_enabled(GetVisible());
InvalidateLayout(); InvalidateLayout();
} else if (sender->GetID() == VIEW_ID_WEBUI_TAB_STRIP_NEW_TAB_BUTTON) { } else if (sender->GetID() == VIEW_ID_WEBUI_TAB_STRIP_NEW_TAB_BUTTON) {
chrome::ExecuteCommand(browser_, IDC_NEW_TAB); chrome::ExecuteCommand(browser_, IDC_NEW_TAB);
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "chrome/browser/ui/views/toolbar/toolbar_button.h" #include "chrome/browser/ui/views/toolbar/toolbar_button.h"
#include "chrome/browser/ui/webui/tab_strip/tab_strip_ui.h" #include "chrome/browser/ui/webui/tab_strip/tab_strip_ui.h"
#include "chrome/common/buildflags.h" #include "chrome/common/buildflags.h"
#include "ui/events/event_handler.h"
#include "ui/views/view.h" #include "ui/views/view.h"
#if !BUILDFLAG(ENABLE_WEBUI_TAB_STRIP) #if !BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
...@@ -45,6 +46,8 @@ class WebUITabStripContainerView : public TabStripUI::Embedder, ...@@ -45,6 +46,8 @@ class WebUITabStripContainerView : public TabStripUI::Embedder,
std::unique_ptr<ToolbarButton> CreateToggleButton(); std::unique_ptr<ToolbarButton> CreateToggleButton();
private: private:
class AutoCloser;
// TabStripUI::Embedder: // TabStripUI::Embedder:
void CloseContainer() override; void CloseContainer() override;
void ShowContextMenuAtPoint( void ShowContextMenuAtPoint(
...@@ -67,6 +70,8 @@ class WebUITabStripContainerView : public TabStripUI::Embedder, ...@@ -67,6 +70,8 @@ class WebUITabStripContainerView : public TabStripUI::Embedder,
int desired_height_ = 0; int desired_height_ = 0;
std::unique_ptr<AutoCloser> auto_closer_;
std::unique_ptr<views::MenuRunner> context_menu_runner_; std::unique_ptr<views::MenuRunner> context_menu_runner_;
std::unique_ptr<ui::MenuModel> context_menu_model_; std::unique_ptr<ui::MenuModel> context_menu_model_;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment