Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 1 | // Copyright 2017 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 | |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 5 | #include "ash/wm/splitview/split_view_drag_indicators.h" |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 6 | |
Ahmed Fakhry | 4acdf65 | 2019-09-05 18:53:06 | [diff] [blame] | 7 | #include <utility> |
| 8 | |
Avery Musbach | 08062d85 | 2019-11-09 01:41:39 | [diff] [blame] | 9 | #include "ash/display/screen_orientation_controller.h" |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 10 | #include "ash/public/cpp/shell_window_ids.h" |
Avery Musbach | ca25838 | 2019-03-26 22:27:33 | [diff] [blame] | 11 | #include "ash/public/cpp/window_animation_types.h" |
Sammie Quon | dc78278 | 2017-11-15 23:33:15 | [diff] [blame] | 12 | #include "ash/screen_util.h" |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 13 | #include "ash/shelf/shelf.h" |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 14 | #include "ash/shell.h" |
| 15 | #include "ash/strings/grit/ash_strings.h" |
Cattalyya Nuengsigkapian | 69d6cc5 | 2020-10-15 19:26:03 | [diff] [blame] | 16 | #include "ash/style/ash_color_provider.h" |
| 17 | #include "ash/style/default_color_constants.h" |
| 18 | #include "ash/style/default_colors.h" |
Sammie Quon | 6c5cf1a | 2017-12-12 01:11:37 | [diff] [blame] | 19 | #include "ash/wm/splitview/split_view_constants.h" |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 20 | #include "ash/wm/splitview/split_view_highlight_view.h" |
Sammie Quon | 6c5cf1a | 2017-12-12 01:11:37 | [diff] [blame] | 21 | #include "ash/wm/splitview/split_view_utils.h" |
Avery Musbach | ca25838 | 2019-03-26 22:27:33 | [diff] [blame] | 22 | #include "ash/wm/window_animations.h" |
James Cook | 00e65e9 | 2019-07-25 03:19:08 | [diff] [blame] | 23 | #include "ash/wm/window_util.h" |
Sammie Quon | 7e6f269 | 2017-10-27 16:42:52 | [diff] [blame] | 24 | #include "base/i18n/rtl.h" |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 25 | #include "base/strings/utf_string_conversions.h" |
| 26 | #include "ui/aura/window.h" |
Avery Musbach | c32f919e | 2019-10-30 20:36:53 | [diff] [blame] | 27 | #include "ui/aura/window_observer.h" |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 28 | #include "ui/base/l10n/l10n_util.h" |
Sammie Quon | 8250507f | 2018-02-23 00:08:28 | [diff] [blame] | 29 | #include "ui/compositor/scoped_layer_animation_settings.h" |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 30 | #include "ui/display/display_observer.h" |
minch | 29e3879d | 2020-11-11 21:25:14 | [diff] [blame] | 31 | #include "ui/views/background.h" |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 32 | #include "ui/views/controls/label.h" |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 33 | #include "ui/views/layout/box_layout.h" |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 34 | #include "ui/views/view.h" |
| 35 | #include "ui/views/widget/widget.h" |
Sammie Quon | dc78278 | 2017-11-15 23:33:15 | [diff] [blame] | 36 | #include "ui/wm/core/coordinate_conversion.h" |
Avery Musbach | ca25838 | 2019-03-26 22:27:33 | [diff] [blame] | 37 | #include "ui/wm/core/window_animations.h" |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 38 | |
| 39 | namespace ash { |
| 40 | |
| 41 | namespace { |
| 42 | |
Avery Musbach | 189df0e | 2019-04-01 23:21:06 | [diff] [blame] | 43 | // When a preview is shown, the opposite highlight shall contract to this ratio |
| 44 | // of the screen length. |
| 45 | constexpr float kOtherHighlightScreenPrimaryAxisRatio = 0.03f; |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 46 | |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 47 | // Creates the widget responsible for displaying the indicators. |
Avery Musbach | 8f34929 | 2019-11-12 17:29:53 | [diff] [blame] | 48 | std::unique_ptr<views::Widget> CreateWidget(aura::Window* root_window) { |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 49 | auto widget = std::make_unique<views::Widget>(); |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 50 | views::Widget::InitParams params; |
| 51 | params.type = views::Widget::InitParams::TYPE_POPUP; |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 52 | params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET; |
Hwanseung Lee | 787d0aa | 2019-11-22 00:31:08 | [diff] [blame] | 53 | params.opacity = views::Widget::InitParams::WindowOpacity::kTranslucent; |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 54 | params.accept_events = false; |
Sammie Quon | 45a1396 | 2020-02-03 17:50:58 | [diff] [blame] | 55 | params.layer_type = ui::LAYER_NOT_DRAWN; |
Avery Musbach | 8f34929 | 2019-11-12 17:29:53 | [diff] [blame] | 56 | params.parent = |
| 57 | Shell::GetContainer(root_window, kShellWindowId_OverlayContainer); |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 58 | widget->set_focus_on_creation(false); |
Ahmed Fakhry | 32f3c45 | 2019-08-01 16:36:34 | [diff] [blame] | 59 | widget->Init(std::move(params)); |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 60 | return widget; |
| 61 | } |
| 62 | |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 63 | // Computes the transform which rotates the labels |angle| degrees. The point |
| 64 | // of rotation is the relative center point of |bounds|. |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 65 | gfx::Transform ComputeRotateAroundCenterTransform(const gfx::Rect& bounds, |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 66 | double angle) { |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 67 | gfx::Transform transform; |
| 68 | const gfx::Vector2dF center_point_vector = |
| 69 | bounds.CenterPoint() - bounds.origin(); |
| 70 | transform.Translate(center_point_vector); |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 71 | transform.Rotate(angle); |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 72 | transform.Translate(-center_point_vector); |
| 73 | return transform; |
| 74 | } |
| 75 | |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 76 | // Returns the work area bounds that has no overlap with shelf. |
| 77 | gfx::Rect GetWorkAreaBoundsNoOverlapWithShelf(aura::Window* root_window) { |
| 78 | aura::Window* window = |
| 79 | root_window->GetChildById(kShellWindowId_OverlayContainer); |
| 80 | gfx::Rect bounds = screen_util::GetDisplayWorkAreaBoundsInParent(window); |
| 81 | ::wm::ConvertRectToScreen(root_window, &bounds); |
| 82 | |
| 83 | bounds.Subtract(Shelf::ForWindow(root_window)->GetIdealBounds()); |
| 84 | return bounds; |
| 85 | } |
| 86 | |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 87 | } // namespace |
| 88 | |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 89 | // static |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 90 | SplitViewController::SnapPosition SplitViewDragIndicators::GetSnapPosition( |
| 91 | WindowDraggingState window_dragging_state) { |
| 92 | switch (window_dragging_state) { |
| 93 | case WindowDraggingState::kToSnapLeft: |
| 94 | return SplitViewController::LEFT; |
| 95 | case WindowDraggingState::kToSnapRight: |
| 96 | return SplitViewController::RIGHT; |
| 97 | default: |
| 98 | return SplitViewController::NONE; |
| 99 | } |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 100 | } |
| 101 | |
| 102 | // static |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 103 | SplitViewDragIndicators::WindowDraggingState |
| 104 | SplitViewDragIndicators::ComputeWindowDraggingState( |
| 105 | bool is_dragging, |
| 106 | WindowDraggingState non_snap_state, |
| 107 | SplitViewController::SnapPosition snap_position) { |
| 108 | if (!is_dragging || !ShouldAllowSplitView()) |
| 109 | return WindowDraggingState::kNoDrag; |
| 110 | switch (snap_position) { |
| 111 | case SplitViewController::NONE: |
| 112 | return non_snap_state; |
| 113 | case SplitViewController::LEFT: |
| 114 | return WindowDraggingState::kToSnapLeft; |
| 115 | case SplitViewController::RIGHT: |
| 116 | return WindowDraggingState::kToSnapRight; |
| 117 | } |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 118 | } |
| 119 | |
Sammie Quon | 6c5cf1a | 2017-12-12 01:11:37 | [diff] [blame] | 120 | // View which contains a label and can be rotated. Used by and rotated by |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 121 | // SplitViewDragIndicatorsView. |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 122 | class SplitViewDragIndicators::RotatedImageLabelView : public views::View { |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 123 | public: |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 124 | explicit RotatedImageLabelView(bool is_right_or_bottom) |
| 125 | : is_right_or_bottom_(is_right_or_bottom) { |
Sammie Quon | 45a1396 | 2020-02-03 17:50:58 | [diff] [blame] | 126 | // TODO(sammiequon): Remove this extra intermediate layer. |
| 127 | SetPaintToLayer(ui::LAYER_NOT_DRAWN); |
| 128 | layer()->SetFillsBoundsOpaquely(false); |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 129 | |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 130 | // Use |label_parent_| to add padding and rounded edges to the text. Create |
| 131 | // this extra view so that we can rotate the label, while having a slide |
| 132 | // animation at times on the whole thing. |
minch | 29e3879d | 2020-11-11 21:25:14 | [diff] [blame] | 133 | label_parent_ = AddChildView(std::make_unique<views::View>()); |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 134 | label_parent_->SetPaintToLayer(); |
| 135 | label_parent_->layer()->SetFillsBoundsOpaquely(false); |
minch | 29e3879d | 2020-11-11 21:25:14 | [diff] [blame] | 136 | label_parent_->SetBackground(views::CreateRoundedRectBackground( |
| 137 | DeprecatedGetBaseLayerColor( |
| 138 | AshColorProvider::BaseLayerType::kTransparent80, |
| 139 | kSplitviewLabelBackgroundColor), |
| 140 | kSplitviewLabelRoundRectRadiusDp)); |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 141 | label_parent_->SetLayoutManager(std::make_unique<views::BoxLayout>( |
Hwanseung Lee | 5b9e43d | 2019-06-25 01:55:32 | [diff] [blame] | 142 | views::BoxLayout::Orientation::kVertical, |
Brett Wilson | bec75cd | 2017-12-15 20:47:34 | [diff] [blame] | 143 | gfx::Insets(kSplitviewLabelVerticalInsetDp, |
| 144 | kSplitviewLabelHorizontalInsetDp))); |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 145 | |
Sammie Quon | 45a1396 | 2020-02-03 17:50:58 | [diff] [blame] | 146 | label_ = label_parent_->AddChildView(std::make_unique<views::Label>( |
Jan Wilken Dörrie | 85285b0 | 2021-03-11 23:38:47 | [diff] [blame^] | 147 | std::u16string(), views::style::CONTEXT_LABEL)); |
Cattalyya Nuengsigkapian | 69d6cc5 | 2020-10-15 19:26:03 | [diff] [blame] | 148 | label_->SetEnabledColor(DeprecatedGetContentLayerColor( |
| 149 | AshColorProvider::ContentLayerType::kTextColorPrimary, |
| 150 | kSplitviewLabelEnabledColor)); |
| 151 | label_->SetBackgroundColor(DeprecatedGetBaseLayerColor( |
| 152 | AshColorProvider::BaseLayerType::kTransparent80, |
| 153 | kSplitviewLabelBackgroundColor)); |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 154 | } |
| 155 | |
| 156 | ~RotatedImageLabelView() override = default; |
| 157 | |
Jan Wilken Dörrie | 85285b0 | 2021-03-11 23:38:47 | [diff] [blame^] | 158 | void SetLabelText(const std::u16string& text) { label_->SetText(text); } |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 159 | |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 160 | // Called when the view's bounds are altered. Rotates the view by |angle| |
| 161 | // degrees. |
| 162 | void OnBoundsUpdated(const gfx::Rect& bounds, double angle) { |
Sammie Quon | 1d70db6 | 2017-10-11 17:59:38 | [diff] [blame] | 163 | SetBoundsRect(bounds); |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 164 | label_parent_->SetBoundsRect(gfx::Rect(bounds.size())); |
| 165 | label_parent_->SetTransform( |
| 166 | ComputeRotateAroundCenterTransform(bounds, angle)); |
| 167 | } |
| 168 | |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 169 | // Called to update the opacity of the labels view on |indicator_state|. |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 170 | void OnWindowDraggingStateChanged( |
| 171 | WindowDraggingState window_dragging_state, |
| 172 | WindowDraggingState previous_window_dragging_state, |
| 173 | bool can_dragged_window_be_snapped) { |
Avery Musbach | 8a91bee | 2019-11-06 19:57:42 | [diff] [blame] | 174 | // No top label for dragging from the top in portrait orientation. |
| 175 | if (window_dragging_state == WindowDraggingState::kFromTop && |
| 176 | !IsCurrentScreenOrientationLandscape() && !is_right_or_bottom_) { |
| 177 | return; |
| 178 | } |
| 179 | |
Avery Musbach | 8152017 | 2019-12-20 18:47:51 | [diff] [blame] | 180 | // If there is no drag currently in this display, any label that is showing |
| 181 | // shall fade out with the corresponding indicator. |
| 182 | if (window_dragging_state == WindowDraggingState::kNoDrag || |
| 183 | window_dragging_state == WindowDraggingState::kOtherDisplay) { |
Avery Musbach | a1fe801 | 2019-03-22 16:56:26 | [diff] [blame] | 184 | DoSplitviewOpacityAnimation( |
| 185 | layer(), SPLITVIEW_ANIMATION_TEXT_FADE_OUT_WITH_HIGHLIGHT); |
| 186 | return; |
| 187 | } |
| 188 | |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 189 | // When a snap preview is shown, any label that is showing shall fade out. |
| 190 | if (GetSnapPosition(window_dragging_state) != SplitViewController::NONE) { |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 191 | DoSplitviewOpacityAnimation(layer(), SPLITVIEW_ANIMATION_TEXT_FADE_OUT); |
| 192 | return; |
| 193 | } |
| 194 | |
Avery Musbach | fcf2cf6b | 2019-11-16 03:00:59 | [diff] [blame] | 195 | // Set the text according to |can_dragged_window_be_snapped|. |
| 196 | SetLabelText(l10n_util::GetStringUTF16( |
| 197 | can_dragged_window_be_snapped ? IDS_ASH_SPLIT_VIEW_GUIDANCE |
| 198 | : IDS_ASH_SPLIT_VIEW_CANNOT_SNAP)); |
| 199 | |
Avery Musbach | 8152017 | 2019-12-20 18:47:51 | [diff] [blame] | 200 | // When dragging begins in this display or comes in from another display, if |
| 201 | // there is now no snap preview, fade in with an indicator. |
| 202 | if (previous_window_dragging_state == WindowDraggingState::kNoDrag || |
| 203 | previous_window_dragging_state == WindowDraggingState::kOtherDisplay) { |
Avery Musbach | a1fe801 | 2019-03-22 16:56:26 | [diff] [blame] | 204 | DoSplitviewOpacityAnimation( |
| 205 | layer(), SPLITVIEW_ANIMATION_TEXT_FADE_IN_WITH_HIGHLIGHT); |
| 206 | return; |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 207 | } |
Avery Musbach | a1fe801 | 2019-03-22 16:56:26 | [diff] [blame] | 208 | |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 209 | // If a snap preview was shown, the labels shall now fade in. |
| 210 | if (GetSnapPosition(previous_window_dragging_state) != |
| 211 | SplitViewController::NONE) { |
Avery Musbach | a1fe801 | 2019-03-22 16:56:26 | [diff] [blame] | 212 | DoSplitviewOpacityAnimation(layer(), SPLITVIEW_ANIMATION_TEXT_FADE_IN); |
| 213 | return; |
| 214 | } |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 215 | } |
| 216 | |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 217 | protected: |
| 218 | gfx::Size CalculatePreferredSize() const override { |
| 219 | return label_parent_->GetPreferredSize(); |
Sammie Quon | 1d70db6 | 2017-10-11 17:59:38 | [diff] [blame] | 220 | } |
| 221 | |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 222 | private: |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 223 | // True if the label view is the right/bottom side one, false if it is the |
| 224 | // left/top one. |
| 225 | const bool is_right_or_bottom_; |
| 226 | |
minch | 29e3879d | 2020-11-11 21:25:14 | [diff] [blame] | 227 | views::View* label_parent_ = nullptr; |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 228 | views::Label* label_ = nullptr; |
| 229 | |
| 230 | DISALLOW_COPY_AND_ASSIGN(RotatedImageLabelView); |
| 231 | }; |
| 232 | |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 233 | // View which contains two highlights on each side indicator where a user should |
| 234 | // drag a selected window in order to initiate splitview. Each highlight has a |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 235 | // label with instructions to further guide users. The highlights are on the |
| 236 | // left and right of the display in landscape mode, and on the top and bottom of |
Sammie Quon | 8250507f | 2018-02-23 00:08:28 | [diff] [blame] | 237 | // the display in landscape mode. The highlights can expand and shrink if a |
| 238 | // window has entered a snap region to display the bounds of the window, if it |
| 239 | // were to get snapped. |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 240 | class SplitViewDragIndicators::SplitViewDragIndicatorsView |
Avery Musbach | c32f919e | 2019-10-30 20:36:53 | [diff] [blame] | 241 | : public views::View, |
| 242 | public aura::WindowObserver { |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 243 | public: |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 244 | SplitViewDragIndicatorsView() { |
Sammie Quon | 45a1396 | 2020-02-03 17:50:58 | [diff] [blame] | 245 | left_highlight_view_ = AddChildView( |
| 246 | std::make_unique<SplitViewHighlightView>(/*is_right_or_bottom=*/false)); |
| 247 | right_highlight_view_ = AddChildView( |
| 248 | std::make_unique<SplitViewHighlightView>(/*is_right_or_bottom=*/true)); |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 249 | |
Sammie Quon | 45a1396 | 2020-02-03 17:50:58 | [diff] [blame] | 250 | left_rotated_view_ = AddChildView( |
| 251 | std::make_unique<RotatedImageLabelView>(/*is_right_or_bottom=*/false)); |
| 252 | right_rotated_view_ = AddChildView( |
| 253 | std::make_unique<RotatedImageLabelView>(/*is_right_or_bottom=*/true)); |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 254 | |
| 255 | // Nothing is shown initially. |
Sammie Quon | 36ab97f | 2018-03-30 18:09:20 | [diff] [blame] | 256 | left_highlight_view_->layer()->SetOpacity(0.f); |
| 257 | right_highlight_view_->layer()->SetOpacity(0.f); |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 258 | left_rotated_view_->layer()->SetOpacity(0.f); |
| 259 | right_rotated_view_->layer()->SetOpacity(0.f); |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 260 | } |
| 261 | |
Avery Musbach | c32f919e | 2019-10-30 20:36:53 | [diff] [blame] | 262 | ~SplitViewDragIndicatorsView() override { |
| 263 | if (dragged_window_) |
| 264 | dragged_window_->RemoveObserver(this); |
| 265 | } |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 266 | |
Ahmed Fakhry | 4acdf65 | 2019-09-05 18:53:06 | [diff] [blame] | 267 | SplitViewHighlightView* left_highlight_view() { return left_highlight_view_; } |
| 268 | |
Avery Musbach | 847b36a | 2019-08-26 22:54:08 | [diff] [blame] | 269 | // Called by parent widget when the state machine changes. Handles setting the |
| 270 | // opacity and bounds of the highlights and labels. |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 271 | void OnWindowDraggingStateChanged(WindowDraggingState window_dragging_state) { |
| 272 | DCHECK_NE(window_dragging_state_, window_dragging_state); |
| 273 | previous_window_dragging_state_ = window_dragging_state_; |
| 274 | window_dragging_state_ = window_dragging_state; |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 275 | |
Friedrich [CET] | 7c79100 | 2019-12-03 15:35:35 | [diff] [blame] | 276 | SplitViewController* split_view_controller = |
| 277 | SplitViewController::Get(GetWidget()->GetNativeWindow()); |
Avery Musbach | 745a9ac | 2019-11-07 01:33:02 | [diff] [blame] | 278 | const bool previews_only = |
| 279 | window_dragging_state == WindowDraggingState::kFromShelf || |
Xiaoqian Dai | 7d128889 | 2019-11-20 20:17:47 | [diff] [blame] | 280 | window_dragging_state == WindowDraggingState::kFromTop || |
Friedrich [CET] | 7c79100 | 2019-12-03 15:35:35 | [diff] [blame] | 281 | split_view_controller->InSplitViewMode(); |
Avery Musbach | 329724e | 2019-10-31 21:10:37 | [diff] [blame] | 282 | const bool can_dragged_window_be_snapped = |
Friedrich [CET] | 7c79100 | 2019-12-03 15:35:35 | [diff] [blame] | 283 | dragged_window_ && |
| 284 | split_view_controller->CanSnapWindow(dragged_window_); |
Avery Musbach | 745a9ac | 2019-11-07 01:33:02 | [diff] [blame] | 285 | if (!previews_only) { |
| 286 | left_rotated_view_->OnWindowDraggingStateChanged( |
| 287 | window_dragging_state, previous_window_dragging_state_, |
| 288 | can_dragged_window_be_snapped); |
| 289 | right_rotated_view_->OnWindowDraggingStateChanged( |
| 290 | window_dragging_state, previous_window_dragging_state_, |
| 291 | can_dragged_window_be_snapped); |
| 292 | } |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 293 | left_highlight_view_->OnWindowDraggingStateChanged( |
Avery Musbach | 745a9ac | 2019-11-07 01:33:02 | [diff] [blame] | 294 | window_dragging_state, previous_window_dragging_state_, previews_only, |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 295 | can_dragged_window_be_snapped); |
| 296 | right_highlight_view_->OnWindowDraggingStateChanged( |
Avery Musbach | 745a9ac | 2019-11-07 01:33:02 | [diff] [blame] | 297 | window_dragging_state, previous_window_dragging_state_, previews_only, |
Avery Musbach | 329724e | 2019-10-31 21:10:37 | [diff] [blame] | 298 | can_dragged_window_be_snapped); |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 299 | |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 300 | if (window_dragging_state != WindowDraggingState::kNoDrag || |
| 301 | GetSnapPosition(previous_window_dragging_state_) != |
| 302 | SplitViewController::NONE) { |
| 303 | Layout(previous_window_dragging_state_ != WindowDraggingState::kNoDrag); |
| 304 | } |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 305 | } |
| 306 | |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 307 | views::View* GetViewForIndicatorType(IndicatorType type) { |
| 308 | switch (type) { |
| 309 | case IndicatorType::kLeftHighlight: |
Sammie Quon | 36ab97f | 2018-03-30 18:09:20 | [diff] [blame] | 310 | return left_highlight_view_; |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 311 | case IndicatorType::kLeftText: |
| 312 | return left_rotated_view_; |
| 313 | case IndicatorType::kRightHighlight: |
Sammie Quon | 36ab97f | 2018-03-30 18:09:20 | [diff] [blame] | 314 | return right_highlight_view_; |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 315 | case IndicatorType::kRightText: |
| 316 | return right_rotated_view_; |
| 317 | } |
| 318 | |
| 319 | NOTREACHED(); |
| 320 | return nullptr; |
| 321 | } |
| 322 | |
Avery Musbach | c32f919e | 2019-10-30 20:36:53 | [diff] [blame] | 323 | void SetDraggedWindow(aura::Window* dragged_window) { |
| 324 | if (dragged_window_) |
| 325 | dragged_window_->RemoveObserver(this); |
| 326 | dragged_window_ = dragged_window; |
| 327 | if (dragged_window) |
| 328 | dragged_window->AddObserver(this); |
| 329 | } |
| 330 | |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 331 | // views::View: |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 332 | void Layout() override { Layout(/*animate=*/false); } |
| 333 | |
Avery Musbach | c32f919e | 2019-10-30 20:36:53 | [diff] [blame] | 334 | // aura::WindowObserver: |
| 335 | void OnWindowDestroyed(aura::Window* window) override { |
| 336 | DCHECK_EQ(dragged_window_, window); |
| 337 | dragged_window_ = nullptr; |
| 338 | } |
| 339 | |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 340 | private: |
| 341 | // Layout the bounds of the highlight views and helper labels. One should |
| 342 | // animate when changing states, but not when bounds or orientation is |
| 343 | // changed. |
| 344 | void Layout(bool animate) { |
Ahmed Fakhry | 4acdf65 | 2019-09-05 18:53:06 | [diff] [blame] | 345 | // TODO(xdai|afakhry): Attempt to simplify this logic. |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 346 | const bool horizontal = SplitViewController::IsLayoutHorizontal(); |
| 347 | const int display_width = horizontal ? width() : height(); |
| 348 | const int display_height = horizontal ? height() : width(); |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 349 | |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 350 | // Calculate the bounds of the two highlight regions. |
Sammie Quon | 6c5cf1a | 2017-12-12 01:11:37 | [diff] [blame] | 351 | const int highlight_width = |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 352 | display_width * kHighlightScreenPrimaryAxisRatio; |
Sammie Quon | 6c5cf1a | 2017-12-12 01:11:37 | [diff] [blame] | 353 | const int highlight_height = |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 354 | display_height - 2 * kHighlightScreenEdgePaddingDp; |
| 355 | gfx::Size highlight_size(highlight_width, highlight_height); |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 356 | |
Avery Musbach | 189df0e | 2019-04-01 23:21:06 | [diff] [blame] | 357 | // When one highlight expands to become a preview area, the other highlight |
| 358 | // contracts to this width. |
| 359 | const int other_highlight_width = |
| 360 | display_width * kOtherHighlightScreenPrimaryAxisRatio; |
| 361 | |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 362 | // The origin of the right highlight view in horizontal split view layout, |
| 363 | // or the bottom highlight view in vertical split view layout. |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 364 | gfx::Point right_bottom_origin( |
| 365 | display_width - highlight_width - kHighlightScreenEdgePaddingDp, |
| 366 | kHighlightScreenEdgePaddingDp); |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 367 | |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 368 | const gfx::Point highlight_padding_point(kHighlightScreenEdgePaddingDp, |
| 369 | kHighlightScreenEdgePaddingDp); |
| 370 | gfx::Rect left_highlight_bounds(highlight_padding_point, highlight_size); |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 371 | gfx::Rect right_highlight_bounds(right_bottom_origin, highlight_size); |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 372 | if (!horizontal) { |
Min Chen | b99878d | 2018-09-04 23:52:52 | [diff] [blame] | 373 | left_highlight_bounds.Transpose(); |
| 374 | right_highlight_bounds.Transpose(); |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 375 | } |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 376 | |
| 377 | // True when the drag ends in a snap area, meaning that the dragged window |
| 378 | // actually becomes snapped. |
| 379 | const bool drag_ending_in_snap = |
| 380 | window_dragging_state_ == WindowDraggingState::kNoDrag && |
| 381 | GetSnapPosition(previous_window_dragging_state_) != |
| 382 | SplitViewController::NONE; |
| 383 | |
| 384 | SplitViewController::SnapPosition snap_position = |
| 385 | GetSnapPosition(window_dragging_state_); |
| 386 | if (snap_position == SplitViewController::NONE) |
| 387 | snap_position = GetSnapPosition(previous_window_dragging_state_); |
| 388 | |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 389 | gfx::Rect preview_area_bounds; |
Avery Musbach | 7a69bab | 2019-04-02 18:41:27 | [diff] [blame] | 390 | base::Optional<SplitviewAnimationType> left_highlight_animation_type; |
| 391 | base::Optional<SplitviewAnimationType> right_highlight_animation_type; |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 392 | if (GetSnapPosition(window_dragging_state_) != SplitViewController::NONE || |
| 393 | drag_ending_in_snap) { |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 394 | // Get the preview area bounds from the split view controller. |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 395 | preview_area_bounds = |
Avery Musbach | dfc1f32 | 2019-10-15 23:04:19 | [diff] [blame] | 396 | SplitViewController::Get(GetWidget()->GetNativeWindow()) |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 397 | ->GetSnappedWindowBoundsInScreen(snap_position, dragged_window_); |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 398 | |
| 399 | aura::Window* root_window = |
| 400 | GetWidget()->GetNativeWindow()->GetRootWindow(); |
Ahmed Fakhry | 4acdf65 | 2019-09-05 18:53:06 | [diff] [blame] | 401 | wm::ConvertRectFromScreen(root_window, &preview_area_bounds); |
| 402 | |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 403 | // Preview area should have no overlap with the shelf. |
| 404 | preview_area_bounds.Subtract( |
| 405 | Shelf::ForWindow(root_window)->GetIdealBounds()); |
| 406 | |
Ahmed Fakhry | 4acdf65 | 2019-09-05 18:53:06 | [diff] [blame] | 407 | gfx::Rect work_area_bounds = |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 408 | GetWorkAreaBoundsNoOverlapWithShelf(root_window); |
Ahmed Fakhry | 4acdf65 | 2019-09-05 18:53:06 | [diff] [blame] | 409 | wm::ConvertRectFromScreen(root_window, &work_area_bounds); |
Min Chen | ca9a3f3 | 2018-10-24 16:34:48 | [diff] [blame] | 410 | preview_area_bounds.set_y(preview_area_bounds.y() - work_area_bounds.y()); |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 411 | if (!drag_ending_in_snap) { |
Avery Musbach | 931f79f | 2019-03-08 23:49:36 | [diff] [blame] | 412 | preview_area_bounds.Inset(kHighlightScreenEdgePaddingDp, |
| 413 | kHighlightScreenEdgePaddingDp); |
| 414 | } |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 415 | |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 416 | // Calculate the bounds of the other highlight, which is the one that |
| 417 | // shrinks and fades away, while the other one, the preview area, expands |
| 418 | // and takes up half the screen. |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 419 | gfx::Rect other_bounds( |
Avery Musbach | 189df0e | 2019-04-01 23:21:06 | [diff] [blame] | 420 | display_width - other_highlight_width - kHighlightScreenEdgePaddingDp, |
| 421 | kHighlightScreenEdgePaddingDp, other_highlight_width, |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 422 | display_height - 2 * kHighlightScreenEdgePaddingDp); |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 423 | if (!horizontal) |
Min Chen | b99878d | 2018-09-04 23:52:52 | [diff] [blame] | 424 | other_bounds.Transpose(); |
Sammie Quon | 59159ca | 2018-03-01 06:05:14 | [diff] [blame] | 425 | |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 426 | if (SplitViewController::IsPhysicalLeftOrTop(snap_position)) { |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 427 | left_highlight_bounds = preview_area_bounds; |
| 428 | right_highlight_bounds = other_bounds; |
Avery Musbach | 7a69bab | 2019-04-02 18:41:27 | [diff] [blame] | 429 | if (animate) { |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 430 | if (drag_ending_in_snap) { |
Avery Musbach | 7a69bab | 2019-04-02 18:41:27 | [diff] [blame] | 431 | left_highlight_animation_type = |
| 432 | SPLITVIEW_ANIMATION_PREVIEW_AREA_NIX_INSET; |
| 433 | } else { |
| 434 | left_highlight_animation_type = |
| 435 | SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN; |
| 436 | right_highlight_animation_type = |
| 437 | SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_OUT; |
| 438 | } |
| 439 | } |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 440 | } else { |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 441 | other_bounds.set_origin(highlight_padding_point); |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 442 | left_highlight_bounds = other_bounds; |
| 443 | right_highlight_bounds = preview_area_bounds; |
Avery Musbach | 7a69bab | 2019-04-02 18:41:27 | [diff] [blame] | 444 | if (animate) { |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 445 | if (drag_ending_in_snap) { |
Avery Musbach | 7a69bab | 2019-04-02 18:41:27 | [diff] [blame] | 446 | right_highlight_animation_type = |
| 447 | SPLITVIEW_ANIMATION_PREVIEW_AREA_NIX_INSET; |
| 448 | } else { |
| 449 | left_highlight_animation_type = |
| 450 | SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_OUT; |
| 451 | right_highlight_animation_type = |
| 452 | SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_IN; |
| 453 | } |
| 454 | } |
| 455 | } |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 456 | } else if (GetSnapPosition(previous_window_dragging_state_) != |
| 457 | SplitViewController::NONE && |
| 458 | animate) { |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 459 | if (SplitViewController::IsPhysicalLeftOrTop(snap_position)) { |
Avery Musbach | 7a69bab | 2019-04-02 18:41:27 | [diff] [blame] | 460 | left_highlight_animation_type = |
| 461 | SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_OUT; |
| 462 | right_highlight_animation_type = |
| 463 | SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN; |
| 464 | } else { |
| 465 | left_highlight_animation_type = |
| 466 | SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_SLIDE_IN; |
| 467 | right_highlight_animation_type = |
| 468 | SPLITVIEW_ANIMATION_PREVIEW_AREA_SLIDE_OUT; |
Sammie Quon | 59159ca | 2018-03-01 06:05:14 | [diff] [blame] | 469 | } |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 470 | } |
| 471 | |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 472 | left_highlight_view_->SetBounds(GetMirroredRect(left_highlight_bounds), |
Sammie Quon | ded3461 | 2020-02-04 19:10:41 | [diff] [blame] | 473 | left_highlight_animation_type); |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 474 | right_highlight_view_->SetBounds(GetMirroredRect(right_highlight_bounds), |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 475 | right_highlight_animation_type); |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 476 | |
| 477 | // Calculate the bounds of the views which contain the guidance text and |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 478 | // icon. Rotate the two views in horizontal split view layout. |
Avery Musbach | feb7321 | 2019-11-01 22:53:38 | [diff] [blame] | 479 | const gfx::Size size(right_rotated_view_->GetPreferredSize().width(), |
| 480 | kSplitviewLabelPreferredHeightDp); |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 481 | if (!horizontal) |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 482 | highlight_size.SetSize(highlight_size.height(), highlight_size.width()); |
| 483 | gfx::Rect left_rotated_bounds( |
| 484 | highlight_size.width() / 2 - size.width() / 2, |
| 485 | highlight_size.height() / 2 - size.height() / 2, size.width(), |
| 486 | size.height()); |
Sammie Quon | 8250507f | 2018-02-23 00:08:28 | [diff] [blame] | 487 | gfx::Rect right_rotated_bounds = left_rotated_bounds; |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 488 | left_rotated_bounds.Offset(highlight_padding_point.x(), |
| 489 | highlight_padding_point.y()); |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 490 | if (!horizontal) { |
Min Chen | 632ec8d | 2018-08-15 21:32:08 | [diff] [blame] | 491 | right_bottom_origin.SetPoint(right_bottom_origin.y(), |
| 492 | right_bottom_origin.x()); |
| 493 | } |
Sammie Quon | 8250507f | 2018-02-23 00:08:28 | [diff] [blame] | 494 | right_rotated_bounds.Offset(right_bottom_origin.x(), |
| 495 | right_bottom_origin.y()); |
Sammie Quon | 7e6f269 | 2017-10-27 16:42:52 | [diff] [blame] | 496 | |
| 497 | // In portrait mode, there is no need to rotate the text and warning icon. |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 498 | // In horizontal split view layout, rotate the left text 90 degrees |
| 499 | // clockwise in rtl and 90 degress anti clockwise in ltr. The right text is |
| 500 | // rotated 90 degrees in the opposite direction of the left text. |
Sammie Quon | 7e6f269 | 2017-10-27 16:42:52 | [diff] [blame] | 501 | double left_rotation_angle = 0.0; |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 502 | if (horizontal) |
Sammie Quon | 7e6f269 | 2017-10-27 16:42:52 | [diff] [blame] | 503 | left_rotation_angle = 90.0 * (base::i18n::IsRTL() ? 1 : -1); |
Sammie Quon | 8250507f | 2018-02-23 00:08:28 | [diff] [blame] | 504 | |
| 505 | left_rotated_view_->OnBoundsUpdated(left_rotated_bounds, |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 506 | /*angle=*/left_rotation_angle); |
Sammie Quon | 8250507f | 2018-02-23 00:08:28 | [diff] [blame] | 507 | right_rotated_view_->OnBoundsUpdated(right_rotated_bounds, |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 508 | /*angle=*/-left_rotation_angle); |
| 509 | |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 510 | if (drag_ending_in_snap) { |
| 511 | // Reset the label transforms, in preparation for the next drag (if any). |
Avery Musbach | c089185 | 2019-03-28 22:14:15 | [diff] [blame] | 512 | left_rotated_view_->layer()->SetTransform(gfx::Transform()); |
| 513 | right_rotated_view_->layer()->SetTransform(gfx::Transform()); |
| 514 | return; |
| 515 | } |
| 516 | |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 517 | ui::Layer* preview_label_layer; |
| 518 | ui::Layer* other_highlight_label_layer; |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 519 | if (snap_position == SplitViewController::NONE) { |
| 520 | preview_label_layer = nullptr; |
| 521 | other_highlight_label_layer = nullptr; |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 522 | } else if (SplitViewController::IsPhysicalLeftOrTop(snap_position)) { |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 523 | preview_label_layer = left_rotated_view_->layer(); |
| 524 | other_highlight_label_layer = right_rotated_view_->layer(); |
| 525 | } else { |
| 526 | preview_label_layer = right_rotated_view_->layer(); |
| 527 | other_highlight_label_layer = left_rotated_view_->layer(); |
Sammie Quon | e61bdc1 | 2018-03-17 02:05:54 | [diff] [blame] | 528 | } |
| 529 | |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 530 | // Slide out the labels when a snap preview appears. This code also adjusts |
| 531 | // the label transforms for things like display rotation while there is a |
| 532 | // snap preview. |
| 533 | if (GetSnapPosition(window_dragging_state_) != SplitViewController::NONE) { |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 534 | // How far each label shall slide to stay centered in the corresponding |
| 535 | // highlight as it expands/contracts. Include distance traveled with zero |
| 536 | // opacity (whence a label still slides, not only for simplicity in |
| 537 | // calculating the values below, but also to facilitate that the label |
| 538 | // transform and the highlight transform have matching easing). |
| 539 | const float preview_label_distance = |
| 540 | 0.5f * (preview_area_bounds.width() - highlight_width); |
| 541 | const float other_highlight_label_distance = |
| 542 | 0.5f * (highlight_width - other_highlight_width); |
| 543 | |
| 544 | // Positive for right or down; negative for left or up. |
| 545 | float preview_label_delta, other_highlight_label_delta; |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 546 | if (SplitViewController::IsPhysicalLeftOrTop(snap_position)) { |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 547 | preview_label_delta = preview_label_distance; |
| 548 | other_highlight_label_delta = other_highlight_label_distance; |
| 549 | } else { |
| 550 | preview_label_delta = -preview_label_distance; |
| 551 | other_highlight_label_delta = -other_highlight_label_distance; |
| 552 | } |
| 553 | |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 554 | // x-axis if |horizontal|; else y-axis. |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 555 | gfx::Transform preview_label_transform, other_highlight_label_transform; |
Avery Musbach | 5e29464 | 2019-12-06 21:39:19 | [diff] [blame] | 556 | if (horizontal) { |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 557 | preview_label_transform.Translate(preview_label_delta, 0.f); |
| 558 | other_highlight_label_transform.Translate(other_highlight_label_delta, |
| 559 | 0.f); |
| 560 | } else { |
| 561 | preview_label_transform.Translate(0.f, preview_label_delta); |
| 562 | other_highlight_label_transform.Translate(0.f, |
| 563 | other_highlight_label_delta); |
| 564 | } |
| 565 | |
| 566 | if (animate) { |
| 567 | // Animate the labels sliding out. |
| 568 | DoSplitviewTransformAnimation( |
| 569 | preview_label_layer, |
| 570 | SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_OUT, |
Xiaoqian Dai | 17c45e51 | 2019-12-19 00:14:22 | [diff] [blame] | 571 | preview_label_transform, /*animation_observer=*/nullptr); |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 572 | DoSplitviewTransformAnimation( |
| 573 | other_highlight_label_layer, |
| 574 | SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_OUT, |
Xiaoqian Dai | 17c45e51 | 2019-12-19 00:14:22 | [diff] [blame] | 575 | other_highlight_label_transform, /*animation_observer=*/nullptr); |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 576 | } else { |
| 577 | // Put the labels where they belong. |
| 578 | preview_label_layer->SetTransform(preview_label_transform); |
| 579 | other_highlight_label_layer->SetTransform( |
| 580 | other_highlight_label_transform); |
| 581 | } |
| 582 | return; |
| 583 | } |
| 584 | |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 585 | // Slide in the labels when a snap preview disappears because you drag |
| 586 | // inward. (Having reached this code, we know that the window is not |
| 587 | // becoming snapped, because that case is handled earlier and we bail out.) |
| 588 | if (GetSnapPosition(previous_window_dragging_state_) != |
| 589 | SplitViewController::NONE) { |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 590 | if (animate) { |
| 591 | // Animate the labels sliding in. |
| 592 | DoSplitviewTransformAnimation( |
| 593 | preview_label_layer, SPLITVIEW_ANIMATION_PREVIEW_AREA_TEXT_SLIDE_IN, |
Xiaoqian Dai | 17c45e51 | 2019-12-19 00:14:22 | [diff] [blame] | 594 | gfx::Transform(), /*animation_observer=*/nullptr); |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 595 | DoSplitviewTransformAnimation( |
| 596 | other_highlight_label_layer, |
Xiaoqian Dai | 17c45e51 | 2019-12-19 00:14:22 | [diff] [blame] | 597 | SPLITVIEW_ANIMATION_OTHER_HIGHLIGHT_TEXT_SLIDE_IN, gfx::Transform(), |
| 598 | /*animation_observer=*/nullptr); |
Avery Musbach | db2c622 | 2019-04-02 21:13:20 | [diff] [blame] | 599 | } else { |
| 600 | // Put the labels where they belong. |
| 601 | preview_label_layer->SetTransform(gfx::Transform()); |
| 602 | other_highlight_label_layer->SetTransform(gfx::Transform()); |
| 603 | } |
| 604 | return; |
| 605 | } |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 606 | } |
| 607 | |
Sammie Quon | a75d28c | 2018-05-08 16:39:57 | [diff] [blame] | 608 | SplitViewHighlightView* left_highlight_view_ = nullptr; |
| 609 | SplitViewHighlightView* right_highlight_view_ = nullptr; |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 610 | RotatedImageLabelView* left_rotated_view_ = nullptr; |
| 611 | RotatedImageLabelView* right_rotated_view_ = nullptr; |
| 612 | |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 613 | WindowDraggingState window_dragging_state_ = WindowDraggingState::kNoDrag; |
| 614 | WindowDraggingState previous_window_dragging_state_ = |
| 615 | WindowDraggingState::kNoDrag; |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 616 | |
Avery Musbach | c32f919e | 2019-10-30 20:36:53 | [diff] [blame] | 617 | aura::Window* dragged_window_ = nullptr; |
| 618 | |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 619 | DISALLOW_COPY_AND_ASSIGN(SplitViewDragIndicatorsView); |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 620 | }; |
| 621 | |
Avery Musbach | 8f34929 | 2019-11-12 17:29:53 | [diff] [blame] | 622 | SplitViewDragIndicators::SplitViewDragIndicators(aura::Window* root_window) { |
Avery Musbach | 8f34929 | 2019-11-12 17:29:53 | [diff] [blame] | 623 | widget_ = CreateWidget(root_window); |
| 624 | widget_->SetBounds(GetWorkAreaBoundsNoOverlapWithShelf(root_window)); |
Wei Li | eb7513bb | 2020-08-31 23:56:18 | [diff] [blame] | 625 | indicators_view_ = |
| 626 | widget_->SetContentsView(std::make_unique<SplitViewDragIndicatorsView>()); |
Sammie Quon | 6c5cf1a | 2017-12-12 01:11:37 | [diff] [blame] | 627 | widget_->Show(); |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 628 | } |
| 629 | |
Avery Musbach | ca25838 | 2019-03-26 22:27:33 | [diff] [blame] | 630 | SplitViewDragIndicators::~SplitViewDragIndicators() { |
| 631 | // Allow some extra time for animations to finish. |
| 632 | aura::Window* window = widget_->GetNativeWindow(); |
| 633 | if (window == nullptr) |
| 634 | return; |
James Cook | 00e65e9 | 2019-07-25 03:19:08 | [diff] [blame] | 635 | wm::SetWindowVisibilityAnimationType( |
| 636 | window, WINDOW_VISIBILITY_ANIMATION_TYPE_STEP_END); |
Avery Musbach | ca25838 | 2019-03-26 22:27:33 | [diff] [blame] | 637 | AnimateOnChildWindowVisibilityChanged(window, /*visible=*/false); |
| 638 | } |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 639 | |
Avery Musbach | c32f919e | 2019-10-30 20:36:53 | [diff] [blame] | 640 | void SplitViewDragIndicators::SetDraggedWindow(aura::Window* dragged_window) { |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 641 | DCHECK_EQ(WindowDraggingState::kNoDrag, current_window_dragging_state_); |
Avery Musbach | c32f919e | 2019-10-30 20:36:53 | [diff] [blame] | 642 | indicators_view_->SetDraggedWindow(dragged_window); |
| 643 | } |
| 644 | |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 645 | void SplitViewDragIndicators::SetWindowDraggingState( |
Avery Musbach | 8f34929 | 2019-11-12 17:29:53 | [diff] [blame] | 646 | WindowDraggingState window_dragging_state) { |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 647 | if (window_dragging_state == current_window_dragging_state_) |
Sammie Quon | 4486fd6 | 2017-10-10 20:22:40 | [diff] [blame] | 648 | return; |
Avery Musbach | abe3a2d | 2019-11-04 21:51:27 | [diff] [blame] | 649 | current_window_dragging_state_ = window_dragging_state; |
| 650 | indicators_view_->OnWindowDraggingStateChanged(window_dragging_state); |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 651 | } |
| 652 | |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 653 | void SplitViewDragIndicators::OnDisplayBoundsChanged() { |
Sammie Quon | 2a2d046 | 2018-03-29 01:26:30 | [diff] [blame] | 654 | aura::Window* root_window = widget_->GetNativeView()->GetRootWindow(); |
Min Chen | 10d413c | 2018-12-07 01:27:36 | [diff] [blame] | 655 | widget_->SetBounds(GetWorkAreaBoundsNoOverlapWithShelf(root_window)); |
Sammie Quon | bc2e913b | 2017-10-25 22:28:26 | [diff] [blame] | 656 | } |
| 657 | |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 658 | bool SplitViewDragIndicators::GetIndicatorTypeVisibilityForTesting( |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 659 | IndicatorType type) const { |
Sammie Quon | be8f7b0 | 2018-03-14 02:08:17 | [diff] [blame] | 660 | return indicators_view_->GetViewForIndicatorType(type)->layer()->opacity() > |
| 661 | 0.f; |
Sammie Quon | 16869be | 2018-02-16 02:59:33 | [diff] [blame] | 662 | } |
| 663 | |
Sammie Quon | 3e9f42b | 2020-01-04 02:42:54 | [diff] [blame] | 664 | gfx::Rect SplitViewDragIndicators::GetLeftHighlightViewBounds() const { |
Ahmed Fakhry | 4acdf65 | 2019-09-05 18:53:06 | [diff] [blame] | 665 | return indicators_view_->left_highlight_view()->bounds(); |
| 666 | } |
| 667 | |
Sammie Quon | 3e582d64 | 2017-09-08 02:01:54 | [diff] [blame] | 668 | } // namespace ash |