Skip to content

Commit 5085b57

Browse files
authored
helium/zen: keep top bar open for bubbles, delay mouse-exit collapse (#1397)
1 parent 9dc3fd3 commit 5085b57

1 file changed

Lines changed: 105 additions & 22 deletions

File tree

patches/helium/ui/experiments/zen-mode.patch

Lines changed: 105 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -8,18 +8,31 @@
88
#include "ui/gfx/animation/animation_runner.h"
99
#include "ui/gfx/canvas.h"
1010
#include "ui/gfx/color_utils.h"
11-
@@ -410,6 +411,10 @@ namespace {
11+
@@ -330,6 +331,8 @@
12+
#include "ui/views/accessibility/view_accessibility.h"
13+
#include "ui/views/accessibility/view_accessibility_utils.h"
14+
#include "ui/views/animation/compositor_animation_runner.h"
15+
+#include "ui/views/animation/ink_drop.h"
16+
+#include "ui/views/animation/ink_drop_state.h"
17+
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
18+
#include "ui/views/controls/button/menu_button.h"
19+
#include "ui/views/controls/textfield/textfield.h"
20+
@@ -410,6 +413,14 @@ namespace {
1221
// The visible height of the shadow above the tabs. Clicks in this area are
1322
// treated as clicks to the frame, rather than clicks to the tab.
1423
const int kTabShadowSize = 2;
1524
+constexpr int kZenModeRevealTriggerThickness = 10;
1625
+constexpr int kZenModeChromeHoverLeeway = 8;
1726
+constexpr base::TimeDelta kZenModeRevealAnimationDuration =
1827
+ base::Milliseconds(100);
28+
+constexpr base::TimeDelta kZenModeCursorExitGracePeriod =
29+
+ base::Milliseconds(1000);
30+
+constexpr base::TimeDelta kZenModeHoverExitGracePeriod =
31+
+ base::Milliseconds(250);
1932

2033
#if BUILDFLAG(IS_CHROMEOS)
2134
// UMA histograms that record animation smoothness for tab loading animation.
22-
@@ -955,7 +960,9 @@ BrowserView::BrowserView(Browser* browse
35+
@@ -955,7 +966,9 @@ BrowserView::BrowserView(Browser* browse
2336
std::make_unique<ExclusiveAccessContextImpl>(*this)),
2437
browser_(browser),
2538
accessibility_mode_observer_(
@@ -30,28 +43,30 @@
3043
if (auto* manager = InitialWebUIWindowMetricsManager::From(browser_.get())) {
3144
manager->OnBrowserWindowCreated();
3245
}
33-
@@ -983,6 +990,12 @@ BrowserView::BrowserView(Browser* browse
46+
@@ -983,6 +996,14 @@ BrowserView::BrowserView(Browser* browse
3447
}
3548

3649
SetProperty(views::kElementIdentifierKey, kBrowserViewElementId);
3750
+ zen_top_chrome_animation_.SetSlideDuration(
3851
+ gfx::Animation::RichAnimationDuration(kZenModeRevealAnimationDuration));
52+
+ zen_top_chrome_animation_.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_3);
3953
+ zen_top_chrome_animation_.Reset(1);
4054
+ zen_side_chrome_animation_.SetSlideDuration(
4155
+ gfx::Animation::RichAnimationDuration(kZenModeRevealAnimationDuration));
56+
+ zen_side_chrome_animation_.SetTweenType(gfx::Tween::FAST_OUT_SLOW_IN_3);
4257
+ zen_side_chrome_animation_.Reset(1);
4358

4459
// Add any legal notices required for the user to the queue.
4560
QueueLegalAndPrivacyNotices(browser_->GetProfile());
46-
@@ -1174,6 +1187,7 @@ BrowserView::~BrowserView() {
61+
@@ -1174,6 +1195,7 @@ BrowserView::~BrowserView() {
4762
// Stop the animation timer explicitly here to avoid running it in a nested
4863
// message loop, which may run by Browser destructor.
4964
loading_animation_timer_.Stop();
5065
+ zen_mode_event_monitor_.reset();
5166

5267
// Reset autofill bubble handler to make sure it does not out-live toolbar,
5368
// since it is responsible for showing autofill related bubbles from toolbar's
54-
@@ -1392,6 +1406,13 @@ bool BrowserView::GetTabStripVisible() c
69+
@@ -1392,6 +1414,13 @@ bool BrowserView::GetTabStripVisible() c
5570
return false;
5671
}
5772

@@ -65,7 +80,7 @@
6580
// In non-fullscreen the tabstrip should always be visible.
6681
auto* const immersive_mode_controller =
6782
ImmersiveModeController::From(browser());
68-
@@ -1578,6 +1599,52 @@ float BrowserView::GetTopControlsSlideBe
83+
@@ -1578,6 +1607,52 @@ float BrowserView::GetTopControlsSlideBe
6984
return 1.f;
7085
}
7186

@@ -118,15 +133,15 @@
118133
views::Widget* BrowserView::GetWidgetForAnchoring() {
119134
#if BUILDFLAG(IS_MAC)
120135
if (UsesImmersiveFullscreenMode()) {
121-
@@ -1602,6 +1669,7 @@ void BrowserView::OnVerticalTabStripMode
136+
@@ -1602,6 +1677,7 @@ void BrowserView::OnVerticalTabStripMode
122137
const bool should_be_vertical = controller->ShouldDisplayVerticalTabs();
123138
if (vertical_initialized == should_be_vertical) {
124139
// Mode is unchanged; just re-layout so alignment-dependent views update.
125140
+ UpdateZenCollapseButtonVisibility();
126141
InvalidateLayout();
127142
return;
128143
}
129-
@@ -1641,10 +1709,208 @@ void BrowserView::OnToolbarTabStripState
144+
@@ -1641,10 +1717,263 @@ void BrowserView::OnToolbarTabStripState
130145
toolbar_->UpdateToolbarLayout();
131146
}
132147

@@ -205,9 +220,18 @@
205220
+ }
206221
+
207222
+ gfx::Point cursor;
223+
+ // When the cursor leaves the window, start a timer before collapsing.
224+
+ // Brief cursor excursions outside the window shouldn't collapse
225+
+ // the chrome.
208226
+ if (!GetCursorLocationInBrowserView(&cursor) ||
209227
+ !GetLocalBounds().Contains(cursor)) {
210-
+ UpdateZenModeReveal(/*reveal_top=*/false, /*reveal_side=*/false);
228+
+ if (!zen_cursor_exit_timer_.IsRunning()) {
229+
+ zen_cursor_exit_timer_.Start(
230+
+ FROM_HERE, kZenModeCursorExitGracePeriod,
231+
+ base::BindOnce(&BrowserView::UpdateZenModeReveal,
232+
+ base::Unretained(this), /*reveal_top=*/false,
233+
+ /*reveal_side=*/false));
234+
+ }
211235
+ return;
212236
+ }
213237
+
@@ -221,6 +245,20 @@
221245
+ const bool in_side_chrome = IsPointInZenSideChromeBounds(cursor);
222246
+ bool reveal_side = !reveal_top && (in_side_trigger || in_side_chrome);
223247
+
248+
+ // Defer the collapse briefly so quick excursions don't cause the
249+
+ // chrome to snap closed.
250+
+ if (!reveal_top && !reveal_side) {
251+
+ if (!zen_cursor_exit_timer_.IsRunning()) {
252+
+ zen_cursor_exit_timer_.Start(
253+
+ FROM_HERE, kZenModeHoverExitGracePeriod,
254+
+ base::BindOnce(&BrowserView::UpdateZenModeReveal,
255+
+ base::Unretained(this), /*reveal_top=*/false,
256+
+ /*reveal_side=*/false));
257+
+ }
258+
+ return;
259+
+ }
260+
+
261+
+ zen_cursor_exit_timer_.Stop();
224262
+ UpdateZenModeReveal(reveal_top, reveal_side);
225263
+}
226264
+
@@ -245,6 +283,12 @@
245283
+ reveal_top = true;
246284
+ }
247285
+
286+
+ // Keep the top chrome visible while a bubble/popup anchored inside
287+
+ // the top container is open (e.g. extensions menu, page info bubble).
288+
+ if (HasOpenBubbleAnchoredInTopContainer()) {
289+
+ reveal_top = true;
290+
+ }
291+
+
248292
+ if (reveal_top) {
249293
+ if (!zen_top_chrome_animation_.IsShowing()) {
250294
+ zen_top_chrome_animation_.Show();
@@ -293,6 +337,32 @@
293337
+ return point.x() < kZenModeRevealTriggerThickness;
294338
+}
295339
+
340+
+namespace {
341+
+
342+
+bool HasActivatedInkDropInSubtree(views::View* view) {
343+
+ if (auto* host = views::InkDrop::Get(view)) {
344+
+ auto* ink_drop = host->GetInkDrop();
345+
+ if (ink_drop &&
346+
+ ink_drop->GetTargetInkDropState() == views::InkDropState::ACTIVATED) {
347+
+ return true;
348+
+ }
349+
+ }
350+
+
351+
+ for (views::View* child : view->children()) {
352+
+ if (HasActivatedInkDropInSubtree(child)) {
353+
+ return true;
354+
+ }
355+
+ }
356+
+
357+
+ return false;
358+
+}
359+
+
360+
+} // namespace
361+
+
362+
+bool BrowserView::HasOpenBubbleAnchoredInTopContainer() const {
363+
+ return top_container_ && HasActivatedInkDropInSubtree(top_container_);
364+
+}
365+
+
296366
+bool BrowserView::IsPointInZenTopChromeBounds(const gfx::Point& point) const {
297367
+ if (!top_container_ || !top_container_->parent()) {
298368
+ return false;
@@ -335,7 +405,7 @@
335405
void BrowserView::OnProjectsPanelStateChanged(
336406
ProjectsPanelStateController* controller) {
337407
projects_panel_container_->OnProjectsPanelStateChanged(controller);
338-
@@ -2397,6 +2663,8 @@ void BrowserView::FullscreenStateChanged
408+
@@ -2397,6 +2726,8 @@ void BrowserView::FullscreenStateChanged
339409
ShowSplitView(GetActiveContentsWebView()->HasFocus());
340410
}
341411
}
@@ -344,7 +414,7 @@
344414
}
345415

346416
void BrowserView::SetToolbarButtonProvider(ToolbarButtonProvider* provider) {
347-
@@ -2449,6 +2717,17 @@ void BrowserView::SetFocusToLocationBar(
417+
@@ -2449,6 +2780,17 @@ void BrowserView::SetFocusToLocationBar(
348418
return;
349419
}
350420

@@ -362,7 +432,7 @@
362432
LocationBar* location_bar = GetLocationBar();
363433
location_bar->FocusLocation(is_user_initiated,
364434
/*clear_focus_if_failed=*/true);
365-
@@ -3203,7 +3482,7 @@ bool BrowserView::IsToolbarVisible() con
435+
@@ -3203,7 +3545,7 @@ bool BrowserView::IsToolbarVisible() con
366436
}
367437

368438
bool BrowserView::IsToolbarShowing() const {
@@ -371,7 +441,19 @@
371441
}
372442

373443
bool BrowserView::IsLocationBarVisible() const {
374-
@@ -5239,6 +5518,8 @@ void BrowserView::AddedToWidget() {
444+
@@ -4400,6 +4742,11 @@ void BrowserView::OnWidgetActivationChan
445+
}
446+
}
447+
448+
+ // Collapse zen mode chrome when the window is deactivated.
449+
+ if (!active && zen_mode_enabled_) {
450+
+ UpdateZenModeReveal(/*reveal_top=*/false, /*reveal_side=*/false);
451+
+ }
452+
+
453+
browser_->GetFeatures()
454+
.extension_keybinding_registry()
455+
->OnHostActivationChanged(active);
456+
@@ -5239,6 +5586,8 @@ void BrowserView::AddedToWidget() {
375457
base::BindRepeating(&BrowserView::OnToolbarTabStripStateChanged,
376458
base::Unretained(this)));
377459
OnToolbarTabStripStateChanged(helium_layout_controller);
@@ -380,15 +462,15 @@
380462
}
381463

382464
UpdateTabSearchBubbleHost();
383-
@@ -5388,6 +5669,7 @@ void BrowserView::AddedToWidget() {
465+
@@ -5388,6 +5737,7 @@ void BrowserView::AddedToWidget() {
384466
}
385467

386468
void BrowserView::RemovedFromWidget() {
387469
+ zen_mode_event_monitor_.reset();
388470
CHECK(GetFocusManager());
389471
focus_manager_observation_.Reset();
390472
}
391-
@@ -5416,6 +5698,14 @@ void BrowserView::OnThemeChanged() {
473+
@@ -5416,6 +5766,14 @@ void BrowserView::OnThemeChanged() {
392474
}
393475

394476
FrameColorsChanged();
@@ -403,7 +485,7 @@
403485
}
404486

405487
bool BrowserView::GetDropFormats(
406-
@@ -5746,6 +6036,9 @@ void BrowserView::UpdateFastResizeForCon
488+
@@ -5746,6 +6104,9 @@ void BrowserView::UpdateFastResizeForCon
407489
}
408490

409491
int BrowserView::GetClientAreaTop() {
@@ -413,7 +495,7 @@
413495
views::View* top_view = toolbar_;
414496
#if BUILDFLAG(ENABLE_WEBUI_TAB_STRIP)
415497
// If webui_tab_strip is displayed, the client area starts at its top,
416-
@@ -6300,6 +6593,42 @@ void BrowserView::OnWillChangeFocus(View
498+
@@ -6300,6 +6661,42 @@ void BrowserView::OnWillChangeFocus(View
417499
}
418500
void BrowserView::OnDidChangeFocus(View* focused_before, View* focused_now) {
419501
UpdateAccessibleNameForRootView();
@@ -523,7 +605,7 @@
523605
// Testing interface:
524606
views::View* GetContentsContainerForTest() { return contents_container_; }
525607
BrowserViewLayout* GetBrowserViewLayoutForTesting() {
526-
@@ -953,6 +978,19 @@ class BrowserView : public BrowserWindow
608+
@@ -953,6 +978,20 @@ class BrowserView : public BrowserWindow
527609

528610
void OnProjectsPanelStateChanged(ProjectsPanelStateController* controller);
529611

@@ -538,19 +620,21 @@
538620
+ bool IsPointInZenSideTrigger(const gfx::Point& point) const;
539621
+ bool IsPointInZenTopChromeBounds(const gfx::Point& point) const;
540622
+ bool IsPointInZenSideChromeBounds(const gfx::Point& point) const;
623+
+ bool HasOpenBubbleAnchoredInTopContainer() const;
541624
+ bool GetCursorLocationInBrowserView(gfx::Point* cursor_location) const;
542625
+
543626
// Make sure the WebUI tab strip exists if it should.
544627
void MaybeInitializeWebUITabStrip();
545628

546-
@@ -1468,6 +1506,12 @@ class BrowserView : public BrowserWindow
629+
@@ -1468,6 +1507,13 @@ class BrowserView : public BrowserWindow
547630

548631
std::unique_ptr<TabCyclingEventHandler> tab_cycling_event_handler_;
549632

550633
+ // Zen mode state.
551634
+ std::unique_ptr<views::EventMonitor> zen_mode_event_monitor_;
552635
+ gfx::SlideAnimation zen_top_chrome_animation_;
553636
+ gfx::SlideAnimation zen_side_chrome_animation_;
637+
+ base::OneShotTimer zen_cursor_exit_timer_;
554638
+ bool zen_mode_enabled_ = false;
555639
+
556640
mutable base::WeakPtrFactory<BrowserView> weak_ptr_factory_{this};
@@ -655,19 +739,18 @@
655739

656740
--- a/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc
657741
+++ b/chrome/browser/ui/views/frame/layout/browser_view_tabbed_layout_impl.cc
658-
@@ -34,10 +34,12 @@
742+
@@ -34,9 +34,11 @@
659743
#include "chrome/browser/ui/views/tabs/projects/layout_constants.h"
660744
#include "chrome/browser/ui/views/tabs/projects/projects_panel_utils.h"
661745
#include "chrome/browser/ui/views/tabs/projects/projects_panel_view.h"
662746
+#include "ui/compositor/layer.h"
663747
#include "ui/gfx/geometry/outsets.h"
664748
#include "ui/gfx/geometry/size.h"
665749
#include "ui/views/controls/separator.h"
666-
#include "ui/views/view_class_properties.h"
667750
+#include "ui/views/layout/layout_provider.h"
751+
#include "ui/views/view_class_properties.h"
668752
#include "ui/views/view_utils.h"
669753

670-
#if BUILDFLAG(IS_MAC)
671754
@@ -59,6 +61,28 @@ constexpr int kVerticalTabsGrabHandleSiz
672755
// against the frame controls when it is the top-most row.
673756
constexpr int kTopToolbarExclusion = 10;

0 commit comments

Comments
 (0)