blob: 2b9fdfe8ad9841612e8f5b366ee4e94616228b77 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_MAC_H_
#define CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_MAC_H_
#include <memory>
#include "base/memory/raw_ptr.h"
#include "base/memory/weak_ptr.h"
#include "chrome/browser/ui/views/frame/browser_view.h"
#include "chrome/browser/ui/views/frame/immersive_mode_controller.h"
#include "components/remote_cocoa/common/native_widget_ns_window.mojom.h"
#include "ui/views/cocoa/immersive_mode_reveal_client.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/view_observer.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
std::unique_ptr<ImmersiveModeController> CreateImmersiveModeControllerMac(
const BrowserView* browser_view);
class ImmersiveModeControllerMac;
// This class notifies the browser view to refresh layout whenever the overlay
// widget moves. This is necessary for positioning web dialogs.
class ImmersiveModeOverlayWidgetObserver : public views::WidgetObserver {
public:
explicit ImmersiveModeOverlayWidgetObserver(
ImmersiveModeControllerMac* controller);
ImmersiveModeOverlayWidgetObserver(
const ImmersiveModeOverlayWidgetObserver&) = delete;
ImmersiveModeOverlayWidgetObserver& operator=(
const ImmersiveModeOverlayWidgetObserver&) = delete;
~ImmersiveModeOverlayWidgetObserver() override;
// views::WidgetObserver:
void OnWidgetBoundsChanged(views::Widget* widget,
const gfx::Rect& new_bounds) override;
private:
raw_ptr<ImmersiveModeControllerMac> controller_;
};
class ImmersiveModeControllerMac : public ImmersiveModeController,
public views::FocusChangeListener,
public views::ViewObserver,
public views::WidgetObserver,
public views::FocusTraversable,
public views::ImmersiveModeRevealClient {
public:
class RevealedLock : public ImmersiveRevealedLock {
public:
explicit RevealedLock(base::WeakPtr<ImmersiveModeControllerMac> controller);
RevealedLock(const RevealedLock&) = delete;
RevealedLock& operator=(const RevealedLock&) = delete;
~RevealedLock() override;
private:
base::WeakPtr<ImmersiveModeControllerMac> controller_;
};
// If `separate_tab_strip` is true, the tab strip is split out into its own
// widget separate from the overlay view so that it can live in the title bar.
explicit ImmersiveModeControllerMac(bool separate_tab_strip);
ImmersiveModeControllerMac(const ImmersiveModeControllerMac&) = delete;
ImmersiveModeControllerMac& operator=(const ImmersiveModeControllerMac&) =
delete;
~ImmersiveModeControllerMac() override;
// ImmersiveModeController overrides:
void Init(BrowserView* browser_view) override;
void SetEnabled(bool enabled) override;
bool IsEnabled() const override;
bool ShouldHideTopViews() const override;
bool IsRevealed() const override;
int GetTopContainerVerticalOffset(
const gfx::Size& top_container_size) const override;
std::unique_ptr<ImmersiveRevealedLock> GetRevealedLock(
AnimateReveal animate_reveal) override;
void OnFindBarVisibleBoundsChanged(
const gfx::Rect& new_visible_bounds_in_screen) override;
bool ShouldStayImmersiveAfterExitingFullscreen() override;
void OnWidgetActivationChanged(views::Widget* widget, bool active) override;
int GetMinimumContentOffset() const override;
int GetExtraInfobarOffset() const override;
void OnContentFullscreenChanged(bool is_content_fullscreen) override;
// Set the widget id of the tab hosting widget. Set before calling SetEnabled.
void SetTabNativeWidgetID(uint64_t widget_id);
// views::FocusChangeListener implementation.
void OnWillChangeFocus(views::View* focused_before,
views::View* focused_now) override;
void OnDidChangeFocus(views::View* focused_before,
views::View* focused_now) override;
// views::ViewObserver implementation
void OnViewBoundsChanged(views::View* observed_view) override;
// views::WidgetObserver implementation
void OnWidgetDestroying(views::Widget* widget) override;
// views::Traversable:
views::FocusSearch* GetFocusSearch() override;
views::FocusTraversable* GetFocusTraversableParent() override;
views::View* GetFocusTraversableParentView() override;
// views::ImmersiveModeRevealClient:
void OnImmersiveModeToolbarRevealChanged(bool is_revealed) override;
void OnImmersiveModeMenuBarRevealChanged(float reveal_amount) override;
void OnAutohidingMenuBarHeightChanged(int menu_bar_height) override;
BrowserView* browser_view() { return browser_view_; }
private:
friend class RevealedLock;
void LockDestroyed();
// Move children from `from_widget` to `to_widget`. Certain child widgets will
// be held back from the move, see `ShouldMoveChild` for details.
void MoveChildren(views::Widget* from_widget, views::Widget* to_widget);
// Returns true if the child should be moved.
bool ShouldMoveChild(views::Widget* child);
raw_ptr<BrowserView> browser_view_ = nullptr; // weak
std::unique_ptr<ImmersiveRevealedLock> focus_lock_;
bool enabled_ = false;
base::ScopedObservation<views::View, views::ViewObserver>
top_container_observation_{this};
base::ScopedObservation<views::Widget, views::WidgetObserver>
browser_frame_observation_{this};
ImmersiveModeOverlayWidgetObserver overlay_widget_observer_{this};
base::ScopedObservation<views::Widget, views::WidgetObserver>
overlay_widget_observation_{&overlay_widget_observer_};
remote_cocoa::mojom::NativeWidgetNSWindow* GetNSWindowMojo();
std::unique_ptr<views::FocusSearch> focus_search_;
// Used to hold the widget id for the tab hosting widget. This will be passed
// to the remote_cocoa immersive mode controller where the tab strip will be
// placed in the titlebar.
uint64_t tab_native_widget_id_ = 0;
// Whether the tab strip should be a separate widget.
bool separate_tab_strip_ = false;
// Height of the tab widget, used when resizing. Only non-zero if
// `separate_tab_strip_` is true.
int tab_widget_height_ = 0;
// Total height of the overlay (including the separate tab strip if relevant).
int overlay_height_ = 0;
// Whether the find bar is currently visible.
bool find_bar_visible_ = false;
// Whether the toolbar is currently visible.
bool is_revealed_ = false;
// The proportion of the menubar/topchrome that has been revealed as a result
// of the user mousing to the top of the screen.
float reveal_amount_ = 0;
// The height of the menubar, if the menubar should be accounted for when
// compensating for reveal animations, otherwise 0. Situations where it is
// not accounted for include screens with notches (where there is always
// space reserved for it) and the "Always Show Menu Bar" system setting.
int menu_bar_height_ = 0;
base::WeakPtrFactory<ImmersiveModeControllerMac> weak_ptr_factory_;
};
#endif // CHROME_BROWSER_UI_VIEWS_FRAME_IMMERSIVE_MODE_CONTROLLER_MAC_H_