James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 1 | // Copyright 2016 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #ifndef ASH_FRAME_HEADER_VIEW_H_ |
| 6 | #define ASH_FRAME_HEADER_VIEW_H_ |
| 7 | |
| 8 | #include <memory> |
| 9 | |
| 10 | #include "ash/ash_export.h" |
Mitsuru Oshima | a6adca4f | 2019-07-10 23:30:46 | [diff] [blame] | 11 | #include "ash/public/cpp/tablet_mode_observer.h" |
Peter Kasting | ce84135 | 2019-11-04 22:53:03 | [diff] [blame] | 12 | #include "base/callback.h" |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 13 | #include "base/macros.h" |
Sigurdur Asgeirsson | e592c48 | 2021-01-28 16:17:29 | [diff] [blame] | 14 | #include "base/scoped_observation.h" |
Antonio Gomes | 448bc6a5 | 2020-11-09 23:13:17 | [diff] [blame] | 15 | #include "chromeos/ui/frame/frame_header.h" |
Antonio Gomes | 5da18e7 | 2020-10-16 15:28:28 | [diff] [blame] | 16 | #include "chromeos/ui/frame/immersive/immersive_fullscreen_controller_delegate.h" |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 17 | #include "third_party/skia/include/core/SkColor.h" |
Evan Stade | 71facea1 | 2019-08-29 21:59:22 | [diff] [blame] | 18 | #include "ui/aura/window.h" |
Evan Stade | 4a97119 | 2018-05-09 00:47:40 | [diff] [blame] | 19 | #include "ui/aura/window_observer.h" |
Qiang Xu | a34f3f9 | 2018-04-11 02:37:08 | [diff] [blame] | 20 | #include "ui/base/ui_base_types.h" |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 21 | #include "ui/views/view.h" |
| 22 | |
Antonio Gomes | 5c83325 | 2020-10-13 18:42:19 | [diff] [blame] | 23 | namespace chromeos { |
Antonio Gomes | 3a07658 | 2020-11-11 18:03:11 | [diff] [blame] | 24 | class DefaultFrameHeader; |
Antonio Gomes | 5c83325 | 2020-10-13 18:42:19 | [diff] [blame] | 25 | class FrameCaptionButtonContainerView; |
| 26 | } |
| 27 | |
xiyuan | 317fdbe | 2017-05-31 15:02:02 | [diff] [blame] | 28 | namespace gfx { |
| 29 | class ImageSkia; |
| 30 | } |
| 31 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 32 | namespace views { |
Tom Anderson | f4c383b1 | 2018-12-05 02:45:38 | [diff] [blame] | 33 | class FrameCaptionButton; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 34 | class ImageView; |
| 35 | class Widget; |
Mitsuru Oshima | 843a15b4 | 2020-10-01 11:31:39 | [diff] [blame] | 36 | class NonClientFrameView; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 37 | } |
| 38 | |
| 39 | namespace ash { |
| 40 | |
Mitsuru Oshima | 40338d6 | 2017-10-26 20:00:42 | [diff] [blame] | 41 | enum class FrameBackButtonState; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 42 | |
| 43 | // View which paints the frame header (title, caption buttons...). It slides off |
| 44 | // and on screen in immersive fullscreen. |
Antonio Gomes | 5da18e7 | 2020-10-16 15:28:28 | [diff] [blame] | 45 | class ASH_EXPORT HeaderView |
| 46 | : public views::View, |
| 47 | public chromeos::ImmersiveFullscreenControllerDelegate, |
| 48 | public TabletModeObserver, |
| 49 | public aura::WindowObserver { |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 50 | public: |
| 51 | // |target_widget| is the widget that the caption buttons act on. |
| 52 | // |target_widget| is not necessarily the same as the widget the header is |
| 53 | // placed in. For example, in immersive fullscreen this view may be painted in |
| 54 | // a widget that slides in and out on top of the main app or browser window. |
| 55 | // However, clicking a caption button should act on the target widget. |
Mitsuru Oshima | 843a15b4 | 2020-10-01 11:31:39 | [diff] [blame] | 56 | HeaderView(views::Widget* target_widget, |
| 57 | views::NonClientFrameView* frame_view); |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 58 | ~HeaderView() override; |
| 59 | |
Mitsuru Oshima | 9d0c217 | 2020-08-07 16:09:36 | [diff] [blame] | 60 | METADATA_HEADER(HeaderView); |
| 61 | |
Peter Kasting | ce84135 | 2019-11-04 22:53:03 | [diff] [blame] | 62 | void set_immersive_mode_changed_callback(base::RepeatingClosure callback) { |
| 63 | immersive_mode_changed_callback_ = std::move(callback); |
| 64 | } |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 65 | |
Sammie Quon | 35c25b6 | 2017-12-01 23:22:50 | [diff] [blame] | 66 | bool should_paint() { return should_paint_; } |
| 67 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 68 | // Schedules a repaint for the entire title. |
| 69 | void SchedulePaintForTitle(); |
| 70 | |
| 71 | // Tells the window controls to reset themselves to the normal state. |
| 72 | void ResetWindowControls(); |
| 73 | |
| 74 | // Returns the amount of the view's pixels which should be on screen. |
| 75 | int GetPreferredOnScreenHeight(); |
| 76 | |
| 77 | // Returns the view's preferred height. |
| 78 | int GetPreferredHeight(); |
| 79 | |
| 80 | // Returns the view's minimum width. |
| 81 | int GetMinimumWidth() const; |
| 82 | |
xiyuan | 317fdbe | 2017-05-31 15:02:02 | [diff] [blame] | 83 | // Sets the avatar icon to be displayed on the frame header. |
| 84 | void SetAvatarIcon(const gfx::ImageSkia& avatar); |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 85 | |
Mitsuru Oshima | c310549 | 2018-03-26 18:22:30 | [diff] [blame] | 86 | void UpdateCaptionButtons(); |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 87 | |
Mitsuru Oshima | 29b93df | 2018-05-25 01:18:48 | [diff] [blame] | 88 | void SetWidthInPixels(int width_in_pixels); |
| 89 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 90 | // views::View: |
| 91 | void Layout() override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 92 | void ChildPreferredSizeChanged(views::View* child) override; |
Mitsuru Oshima | 7ea9753 | 2019-05-16 16:43:27 | [diff] [blame] | 93 | bool IsDrawn() const override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 94 | |
Sammie Quon | b9057f7 | 2017-07-20 23:44:02 | [diff] [blame] | 95 | // TabletModeObserver: |
Mitsuru Oshima | 0e9b7a6 | 2017-07-19 18:23:03 | [diff] [blame] | 96 | void OnTabletModeStarted() override; |
| 97 | void OnTabletModeEnded() override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 98 | |
Evan Stade | 4a97119 | 2018-05-09 00:47:40 | [diff] [blame] | 99 | // aura::WindowObserver: |
| 100 | void OnWindowPropertyChanged(aura::Window* window, |
| 101 | const void* key, |
| 102 | intptr_t old) override; |
| 103 | void OnWindowDestroying(aura::Window* window) override; |
| 104 | |
Antonio Gomes | 5c83325 | 2020-10-13 18:42:19 | [diff] [blame] | 105 | chromeos::FrameCaptionButtonContainerView* caption_button_container() { |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 106 | return caption_button_container_; |
| 107 | } |
| 108 | |
| 109 | views::View* avatar_icon() const; |
| 110 | |
Mitsuru Oshima | eee84c3b | 2018-04-12 05:56:24 | [diff] [blame] | 111 | bool in_immersive_mode() const { return in_immersive_mode_; } |
Mitsuru Oshima | c2327d0 | 2018-05-01 00:29:00 | [diff] [blame] | 112 | bool is_revealed() const { return fullscreen_visible_fraction_ > 0.0; } |
Mitsuru Oshima | eee84c3b | 2018-04-12 05:56:24 | [diff] [blame] | 113 | |
wutao | b32762a | 2017-11-14 22:35:30 | [diff] [blame] | 114 | void SetShouldPaintHeader(bool paint); |
| 115 | |
Tom Anderson | f4c383b1 | 2018-12-05 02:45:38 | [diff] [blame] | 116 | views::FrameCaptionButton* GetBackButton(); |
Mitsuru Oshima | c310549 | 2018-03-26 18:22:30 | [diff] [blame] | 117 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 118 | // ImmersiveFullscreenControllerDelegate: |
| 119 | void OnImmersiveRevealStarted() override; |
| 120 | void OnImmersiveRevealEnded() override; |
Mitsuru Oshima | eee84c3b | 2018-04-12 05:56:24 | [diff] [blame] | 121 | void OnImmersiveFullscreenEntered() override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 122 | void OnImmersiveFullscreenExited() override; |
| 123 | void SetVisibleFraction(double visible_fraction) override; |
| 124 | std::vector<gfx::Rect> GetVisibleBoundsInScreen() const override; |
Mitsuru Oshima | 49b451e | 2019-08-13 10:51:13 | [diff] [blame] | 125 | void Relayout() override; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 126 | |
Antonio Gomes | 3a07658 | 2020-11-11 18:03:11 | [diff] [blame] | 127 | chromeos::DefaultFrameHeader* GetFrameHeader() { return frame_header_.get(); } |
Mitsuru Oshima | 6d7f5b7 | 2018-05-19 21:43:50 | [diff] [blame] | 128 | |
Mitsuru Oshima | 7a789e59 | 2018-04-13 00:46:41 | [diff] [blame] | 129 | private: |
Mitsuru Oshima | 29b93df | 2018-05-25 01:18:48 | [diff] [blame] | 130 | class HeaderContentView; |
| 131 | friend class HeaderContentView; |
| 132 | |
| 133 | // Paint the header content. |
| 134 | void PaintHeaderContent(gfx::Canvas* canvas); |
| 135 | |
Evan Stade | e90c93d | 2018-06-26 21:27:28 | [diff] [blame] | 136 | void UpdateBackButton(); |
Kazuki Takise | 5e6a32e6 | 2021-06-03 07:22:46 | [diff] [blame] | 137 | void UpdateCenterButton(); |
Evan Stade | 6a49ef0 | 2018-08-14 22:35:22 | [diff] [blame] | 138 | void UpdateCaptionButtonsVisibility(); |
Evan Stade | e90c93d | 2018-06-26 21:27:28 | [diff] [blame] | 139 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 140 | // The widget that the caption buttons act on. |
| 141 | views::Widget* target_widget_; |
| 142 | |
Peter Kasting | ce84135 | 2019-11-04 22:53:03 | [diff] [blame] | 143 | // A callback to run when |in_immersive_mode_| changes. |
| 144 | base::RepeatingClosure immersive_mode_changed_callback_; |
| 145 | |
Evan Stade | 4a97119 | 2018-05-09 00:47:40 | [diff] [blame] | 146 | // Helper for painting the header. The exact type of FrameHeader will depend |
| 147 | // on the type of window: In Mash, Chrome Browser windows use |
| 148 | // CustomFrameHeader which is aware of theming. In classic Ash, Chrome Browser |
| 149 | // windows won't use HeaderView at all. In either configuration, non Browser |
| 150 | // windows will use DefaultFrameHeader. |
Antonio Gomes | 3a07658 | 2020-11-11 18:03:11 | [diff] [blame] | 151 | std::unique_ptr<chromeos::DefaultFrameHeader> frame_header_; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 152 | |
Peter Kasting | ce84135 | 2019-11-04 22:53:03 | [diff] [blame] | 153 | views::ImageView* avatar_icon_ = nullptr; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 154 | |
Mitsuru Oshima | 29b93df | 2018-05-25 01:18:48 | [diff] [blame] | 155 | // View which draws the content of the frame. |
| 156 | HeaderContentView* header_content_view_ = nullptr; |
| 157 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 158 | // View which contains the window caption buttons. |
Antonio Gomes | 5c83325 | 2020-10-13 18:42:19 | [diff] [blame] | 159 | chromeos::FrameCaptionButtonContainerView* caption_button_container_ = |
| 160 | nullptr; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 161 | |
| 162 | // The fraction of the header's height which is visible while in fullscreen. |
| 163 | // This value is meaningless when not in fullscreen. |
Peter Kasting | ce84135 | 2019-11-04 22:53:03 | [diff] [blame] | 164 | double fullscreen_visible_fraction_ = 0; |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 165 | |
Evan Stade | 0b22a42 | 2018-09-05 17:03:01 | [diff] [blame] | 166 | // True if a layer should be used for the immersive mode reveal. Some code |
| 167 | // needs HeaderView to always paint to a layer instead of only during |
| 168 | // immersive reveal (see WmNativeWidgetAura). |
| 169 | bool add_layer_for_immersive_ = false; |
| 170 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 171 | bool did_layout_ = false; |
| 172 | |
wutao | b32762a | 2017-11-14 22:35:30 | [diff] [blame] | 173 | // False to skip painting. Used for overview mode to hide the header. |
Peter Kasting | ce84135 | 2019-11-04 22:53:03 | [diff] [blame] | 174 | bool should_paint_ = true; |
wutao | b32762a | 2017-11-14 22:35:30 | [diff] [blame] | 175 | |
Mitsuru Oshima | eee84c3b | 2018-04-12 05:56:24 | [diff] [blame] | 176 | bool in_immersive_mode_ = false; |
| 177 | |
Mitsuru Oshima | 7ea9753 | 2019-05-16 16:43:27 | [diff] [blame] | 178 | // This is used to compute visible bounds. |
| 179 | mutable bool is_drawn_override_ = false; |
| 180 | |
Evan Stade | 4a97119 | 2018-05-09 00:47:40 | [diff] [blame] | 181 | // Observes property changes to |target_widget_|'s window. |
Sigurdur Asgeirsson | e592c48 | 2021-01-28 16:17:29 | [diff] [blame] | 182 | base::ScopedObservation<aura::Window, aura::WindowObserver> |
| 183 | window_observation_{this}; |
Evan Stade | 4a97119 | 2018-05-09 00:47:40 | [diff] [blame] | 184 | |
James Cook | b0bf8e8 | 2017-04-09 17:01:44 | [diff] [blame] | 185 | DISALLOW_COPY_AND_ASSIGN(HeaderView); |
| 186 | }; |
| 187 | |
| 188 | } // namespace ash |
| 189 | |
| 190 | #endif // ASH_FRAME_HEADER_VIEW_H_ |