Avi Drissman | 3a215d1e | 2022-09-07 19:43:09 | [diff] [blame] | 1 | // Copyright 2020 The Chromium Authors |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | #include "ash/drag_drop/tab_drag_drop_delegate.h" |
| 6 | |
Antonio Gomes | 519ab0a8 | 2022-01-10 21:03:21 | [diff] [blame] | 7 | #include "ash/constants/app_types.h" |
Henrique Ferreiro | 8422acb | 2021-06-16 13:56:00 | [diff] [blame] | 8 | #include "ash/constants/ash_features.h" |
Xiaoqian Dai | ce2f784 | 2023-03-17 20:39:31 | [diff] [blame] | 9 | #include "ash/drag_drop/tab_drag_drop_windows_hider.h" |
Antonio Gomes | 40900a31 | 2021-10-07 10:41:09 | [diff] [blame] | 10 | #include "ash/public/cpp/new_window_delegate.h" |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 11 | #include "ash/public/cpp/window_properties.h" |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 12 | #include "ash/screen_util.h" |
| 13 | #include "ash/shell.h" |
| 14 | #include "ash/shell_delegate.h" |
Yuheng Huang | ca5a28d | 2022-02-11 21:55:19 | [diff] [blame] | 15 | #include "ash/wm/overview/overview_controller.h" |
| 16 | #include "ash/wm/overview/overview_session.h" |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 17 | #include "ash/wm/splitview/split_view_constants.h" |
| 18 | #include "ash/wm/splitview/split_view_controller.h" |
| 19 | #include "ash/wm/splitview/split_view_drag_indicators.h" |
| 20 | #include "ash/wm/splitview/split_view_utils.h" |
Sammie Quon | ba51e0d0 | 2023-04-11 19:54:53 | [diff] [blame] | 21 | #include "ash/wm/tablet_mode/tablet_mode_window_state.h" |
Michele Fan | 3c6da02 | 2023-12-09 00:52:45 | [diff] [blame] | 22 | #include "ash/wm/window_util.h" |
Xiaoqian Dai | 02ea809 | 2022-02-24 23:16:02 | [diff] [blame] | 23 | #include "ash/wm/wm_metrics.h" |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 24 | #include "base/pickle.h" |
| 25 | #include "base/strings/utf_string_conversions.h" |
Antonio Gomes | 519ab0a8 | 2022-01-10 21:03:21 | [diff] [blame] | 26 | #include "chromeos/crosapi/cpp/lacros_startup_state.h" |
| 27 | #include "ui/aura/client/aura_constants.h" |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 28 | #include "ui/base/clipboard/clipboard_format_type.h" |
| 29 | #include "ui/base/clipboard/custom_data_helper.h" |
| 30 | #include "ui/base/dragdrop/os_exchange_data.h" |
Lei Zhang | 0c04332 | 2021-04-27 16:43:05 | [diff] [blame] | 31 | #include "ui/compositor/layer.h" |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 32 | #include "ui/compositor/layer_animator.h" |
Yuheng Huang | a6b2b62 | 2022-02-14 20:50:42 | [diff] [blame] | 33 | #include "ui/compositor/presentation_time_recorder.h" |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 34 | #include "ui/compositor/scoped_layer_animation_settings.h" |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 35 | #include "ui/gfx/geometry/rect.h" |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 36 | #include "ui/wm/core/coordinate_conversion.h" |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 37 | |
| 38 | namespace ash { |
| 39 | |
| 40 | namespace { |
| 41 | |
| 42 | // The following distances are copied from tablet_mode_window_drag_delegate.cc. |
| 43 | // TODO(https://crbug.com/1069869): share these constants. |
| 44 | |
| 45 | // Items dragged to within |kDistanceFromEdgeDp| of the screen will get snapped |
| 46 | // even if they have not moved by |kMinimumDragToSnapDistanceDp|. |
| 47 | constexpr float kDistanceFromEdgeDp = 16.f; |
| 48 | // The minimum distance that an item must be moved before it is snapped. This |
| 49 | // prevents accidental snaps. |
| 50 | constexpr float kMinimumDragToSnapDistanceDp = 96.f; |
| 51 | |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 52 | // The scale factor that the source window should scale if the source window is |
| 53 | // not the dragged window && is not in splitscreen when drag starts && the user |
| 54 | // has dragged the window to pass the |kIndicatorThresholdRatio| vertical |
| 55 | // threshold. |
| 56 | constexpr float kSourceWindowScale = 0.85; |
| 57 | |
Yichen Zhou | b81bae01 | 2021-04-09 23:18:10 | [diff] [blame] | 58 | // The UMA histogram that records presentation time for tab dragging in |
| 59 | // tablet mode with webui tab strip enable. |
| 60 | constexpr char kTabDraggingInTabletModeHistogram[] = |
| 61 | "Ash.TabDrag.PresentationTime.TabletMode"; |
| 62 | |
| 63 | constexpr char kTabDraggingInTabletModeMaxLatencyHistogram[] = |
| 64 | "Ash.TabDrag.PresentationTime.MaxLatency.TabletMode"; |
| 65 | |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 66 | DEFINE_UI_CLASS_PROPERTY_KEY(bool, kIsSourceWindowForDrag, false) |
| 67 | |
Antonio Gomes | 519ab0a8 | 2022-01-10 21:03:21 | [diff] [blame] | 68 | bool IsLacrosWindow(const aura::Window* window) { |
| 69 | auto app_type = |
| 70 | static_cast<AppType>(window->GetProperty(aura::client::kAppType)); |
| 71 | return app_type == AppType::LACROS; |
| 72 | } |
| 73 | |
Yuheng Huang | ca5a28d | 2022-02-11 21:55:19 | [diff] [blame] | 74 | // Returns the overview session if overview mode is active, otherwise returns |
| 75 | // nullptr. |
| 76 | OverviewSession* GetOverviewSession() { |
| 77 | return Shell::Get()->overview_controller()->InOverviewSession() |
| 78 | ? Shell::Get()->overview_controller()->overview_session() |
| 79 | : nullptr; |
| 80 | } |
| 81 | |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 82 | } // namespace |
| 83 | |
| 84 | // static |
| 85 | bool TabDragDropDelegate::IsChromeTabDrag(const ui::OSExchangeData& drag_data) { |
Collin Baker | e5fb2f69 | 2020-05-14 01:24:44 | [diff] [blame] | 86 | return Shell::Get()->shell_delegate()->IsTabDrag(drag_data); |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 87 | } |
| 88 | |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 89 | // static |
| 90 | bool TabDragDropDelegate::IsSourceWindowForDrag(const aura::Window* window) { |
| 91 | return window->GetProperty(kIsSourceWindowForDrag); |
| 92 | } |
| 93 | |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 94 | TabDragDropDelegate::TabDragDropDelegate( |
| 95 | aura::Window* root_window, |
| 96 | aura::Window* source_window, |
| 97 | const gfx::Point& start_location_in_screen) |
| 98 | : root_window_(root_window), |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 99 | source_window_(source_window->GetToplevelWindow()), |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 100 | start_location_in_screen_(start_location_in_screen) { |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 101 | DCHECK(root_window_); |
| 102 | DCHECK(source_window_); |
Antonio Gomes | 5ec1a5a | 2023-01-19 02:55:50 | [diff] [blame] | 103 | source_window_->AddObserver(this); |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 104 | source_window_->SetProperty(kIsSourceWindowForDrag, true); |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 105 | split_view_drag_indicators_ = |
| 106 | std::make_unique<SplitViewDragIndicators>(root_window_); |
Yichen Zhou | b81bae01 | 2021-04-09 23:18:10 | [diff] [blame] | 107 | |
| 108 | tab_dragging_recorder_ = CreatePresentationTimeHistogramRecorder( |
| 109 | source_window_->layer()->GetCompositor(), |
| 110 | kTabDraggingInTabletModeHistogram, |
| 111 | kTabDraggingInTabletModeMaxLatencyHistogram); |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 112 | } |
| 113 | |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 114 | TabDragDropDelegate::~TabDragDropDelegate() { |
Yichen Zhou | b81bae01 | 2021-04-09 23:18:10 | [diff] [blame] | 115 | tab_dragging_recorder_.reset(); |
| 116 | |
Antonio Gomes | 5ec1a5a | 2023-01-19 02:55:50 | [diff] [blame] | 117 | if (!source_window_) { |
| 118 | return; |
| 119 | } |
| 120 | |
| 121 | source_window_->RemoveObserver(this); |
| 122 | |
Antonio Gomes | 0012f7c | 2022-07-08 19:28:59 | [diff] [blame] | 123 | if (source_window_->is_destroying()) |
| 124 | return; |
| 125 | |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 126 | if (!source_window_->GetProperty(kIsSourceWindowForDrag)) |
| 127 | return; |
| 128 | |
| 129 | // If we didn't drop to a new window, we must restore the original window. |
| 130 | RestoreSourceWindowBounds(); |
| 131 | source_window_->ClearProperty(kIsSourceWindowForDrag); |
| 132 | } |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 133 | |
| 134 | void TabDragDropDelegate::DragUpdate(const gfx::Point& location_in_screen) { |
| 135 | const gfx::Rect area = |
| 136 | screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer( |
| 137 | root_window_); |
| 138 | |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 139 | SnapPosition snap_position = ash::GetSnapPositionForLocation( |
| 140 | Shell::GetPrimaryRootWindow(), location_in_screen, |
| 141 | start_location_in_screen_, |
| 142 | /*snap_distance_from_edge=*/kDistanceFromEdgeDp, |
| 143 | /*minimum_drag_distance=*/kMinimumDragToSnapDistanceDp, |
| 144 | /*horizontal_edge_inset=*/area.width() * |
| 145 | kHighlightScreenPrimaryAxisRatio + |
| 146 | kHighlightScreenEdgePaddingDp, |
| 147 | /*vertical_edge_inset=*/area.height() * kHighlightScreenPrimaryAxisRatio + |
| 148 | kHighlightScreenEdgePaddingDp); |
Yuheng Huang | eeff7861 | 2022-04-27 20:57:01 | [diff] [blame] | 149 | if (ShouldPreventSnapToTheEdge(location_in_screen)) |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 150 | snap_position = SnapPosition::kNone; |
Yuheng Huang | eeff7861 | 2022-04-27 20:57:01 | [diff] [blame] | 151 | |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 152 | split_view_drag_indicators_->SetWindowDraggingState( |
| 153 | SplitViewDragIndicators::ComputeWindowDraggingState( |
| 154 | true, SplitViewDragIndicators::WindowDraggingState::kFromTop, |
| 155 | snap_position)); |
| 156 | |
Yuheng Huang | e141ef2 | 2021-07-07 18:03:51 | [diff] [blame] | 157 | UpdateSourceWindowBoundsIfNecessary(snap_position, location_in_screen); |
Yichen Zhou | b81bae01 | 2021-04-09 23:18:10 | [diff] [blame] | 158 | |
| 159 | tab_dragging_recorder_->RequestNext(); |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 160 | } |
| 161 | |
Antonio Gomes | 4c8353e | 2021-10-13 13:34:08 | [diff] [blame] | 162 | void TabDragDropDelegate::DropAndDeleteSelf( |
| 163 | const gfx::Point& location_in_screen, |
| 164 | const ui::OSExchangeData& drop_data) { |
Yichen Zhou | b81bae01 | 2021-04-09 23:18:10 | [diff] [blame] | 165 | tab_dragging_recorder_.reset(); |
| 166 | |
Antonio Gomes | 40900a31 | 2021-10-07 10:41:09 | [diff] [blame] | 167 | auto closure = base::BindOnce(&TabDragDropDelegate::OnNewBrowserWindowCreated, |
Antonio Gomes | 4c8353e | 2021-10-13 13:34:08 | [diff] [blame] | 168 | base::Owned(this), location_in_screen); |
Antonio Gomes | 8601b5c73 | 2021-10-14 15:41:47 | [diff] [blame] | 169 | NewWindowDelegate::GetPrimary()->NewWindowForDetachingTab( |
Antonio Gomes | 40900a31 | 2021-10-07 10:41:09 | [diff] [blame] | 170 | source_window_, drop_data, std::move(closure)); |
| 171 | } |
| 172 | |
Antonio Gomes | 5ec1a5a | 2023-01-19 02:55:50 | [diff] [blame] | 173 | void TabDragDropDelegate::OnWindowDestroying(aura::Window* window) { |
| 174 | if (source_window_ == window) { |
| 175 | windows_hider_.reset(); |
| 176 | source_window_->RemoveObserver(this); |
| 177 | source_window_ = nullptr; |
| 178 | } |
| 179 | } |
| 180 | |
Antonio Gomes | 40900a31 | 2021-10-07 10:41:09 | [diff] [blame] | 181 | void TabDragDropDelegate::OnNewBrowserWindowCreated( |
| 182 | const gfx::Point& location_in_screen, |
| 183 | aura::Window* new_window) { |
Xiyuan Xia | 6f93c65 | 2023-04-06 19:43:48 | [diff] [blame] | 184 | // `source_window_` could reset to nullptr during the drag. |
| 185 | if (!source_window_) { |
| 186 | DCHECK(!new_window); |
| 187 | return; |
| 188 | } |
| 189 | |
Antonio Gomes | 519ab0a8 | 2022-01-10 21:03:21 | [diff] [blame] | 190 | auto is_lacros = IsLacrosWindow(source_window_); |
Yuheng Huang | 1b2d3401 | 2022-05-12 17:24:39 | [diff] [blame] | 191 | |
| 192 | // https://crbug.com/1286203: |
| 193 | // It's possible new window is created when the dragged WebContents |
| 194 | // closes itself during the drag session. |
| 195 | if (!new_window) { |
Georg Neis | 16bb891 | 2023-08-11 03:41:30 | [diff] [blame] | 196 | if (is_lacros && !crosapi::lacros_startup_state::IsLacrosEnabled()) { |
| 197 | LOG(ERROR) << "New browser window creation for tab detaching failed.\n" |
| 198 | << "Check whether Lacros is enabled"; |
Yuheng Huang | 1b2d3401 | 2022-05-12 17:24:39 | [diff] [blame] | 199 | } |
Antonio Gomes | 519ab0a8 | 2022-01-10 21:03:21 | [diff] [blame] | 200 | return; |
| 201 | } |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 202 | |
Collin Baker | aec4387 | 2020-05-07 20:28:57 | [diff] [blame] | 203 | const gfx::Rect area = |
| 204 | screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer( |
| 205 | root_window_); |
| 206 | |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 207 | SnapPosition snap_position_in_snapping_zone = ash::GetSnapPosition( |
| 208 | root_window_, new_window, location_in_screen, start_location_in_screen_, |
| 209 | /*snap_distance_from_edge=*/kDistanceFromEdgeDp, |
| 210 | /*minimum_drag_distance=*/kMinimumDragToSnapDistanceDp, |
| 211 | /*horizontal_edge_inset=*/area.width() * |
| 212 | kHighlightScreenPrimaryAxisRatio + |
| 213 | kHighlightScreenEdgePaddingDp, |
| 214 | /*vertical_edge_inset=*/area.height() * kHighlightScreenPrimaryAxisRatio + |
| 215 | kHighlightScreenEdgePaddingDp); |
Yuheng Huang | eeff7861 | 2022-04-27 20:57:01 | [diff] [blame] | 216 | if (ShouldPreventSnapToTheEdge(location_in_screen)) |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 217 | snap_position_in_snapping_zone = SnapPosition::kNone; |
Collin Baker | aec4387 | 2020-05-07 20:28:57 | [diff] [blame] | 218 | |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 219 | if (snap_position_in_snapping_zone == SnapPosition::kNone) { |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 220 | RestoreSourceWindowBounds(); |
Lei Zhang | f2166c6 | 2022-09-17 02:03:11 | [diff] [blame] | 221 | } |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 222 | |
| 223 | // This must be done after restoring the source window's bounds since |
| 224 | // otherwise the SetBounds() call may have no effect. |
| 225 | source_window_->ClearProperty(kIsSourceWindowForDrag); |
| 226 | |
Yuheng Huang | 098abd4b | 2021-07-07 19:32:30 | [diff] [blame] | 227 | SplitViewController* const split_view_controller = |
| 228 | SplitViewController::Get(new_window); |
| 229 | |
| 230 | // If it's already in split view mode, either snap the new window |
| 231 | // to the left or the right depending on the drop location. |
| 232 | const bool in_split_view_mode = split_view_controller->InSplitViewMode(); |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 233 | SnapPosition snap_position = snap_position_in_snapping_zone; |
Yuheng Huang | 098abd4b | 2021-07-07 19:32:30 | [diff] [blame] | 234 | if (in_split_view_mode) { |
| 235 | snap_position = |
| 236 | split_view_controller->ComputeSnapPosition(location_in_screen); |
| 237 | } |
| 238 | |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 239 | if (snap_position == SnapPosition::kNone) { |
Collin Baker | aec4387 | 2020-05-07 20:28:57 | [diff] [blame] | 240 | return; |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 241 | } |
Collin Baker | aec4387 | 2020-05-07 20:28:57 | [diff] [blame] | 242 | |
Yuheng Huang | ca5a28d | 2022-02-11 21:55:19 | [diff] [blame] | 243 | OverviewSession* overview_session = GetOverviewSession(); |
| 244 | // If overview session is present on the other side and the new window is |
| 245 | // about to snap to that side but not in the snapping zone then drop the new |
| 246 | // window into overview. |
| 247 | if (overview_session && |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 248 | snap_position_in_snapping_zone == SnapPosition::kNone && |
Yuheng Huang | ca5a28d | 2022-02-11 21:55:19 | [diff] [blame] | 249 | split_view_controller->GetPositionOfSnappedWindow(source_window_) != |
| 250 | snap_position) { |
| 251 | overview_session->MergeWindowIntoOverviewForWebUITabStrip(new_window); |
| 252 | } else { |
| 253 | split_view_controller->SnapWindow(new_window, snap_position, |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 254 | WindowSnapActionSource::kDragTabToSnap, |
Yuheng Huang | ca5a28d | 2022-02-11 21:55:19 | [diff] [blame] | 255 | /*activate_window=*/true); |
| 256 | } |
Collin Baker | 512a9d4e | 2020-05-12 19:34:33 | [diff] [blame] | 257 | |
Yuheng Huang | 098abd4b | 2021-07-07 19:32:30 | [diff] [blame] | 258 | // Do not snap the source window if already in split view mode. |
| 259 | if (in_split_view_mode) |
| 260 | return; |
| 261 | |
Collin Baker | 512a9d4e | 2020-05-12 19:34:33 | [diff] [blame] | 262 | // The tab drag source window is the last window the user was |
| 263 | // interacting with. When dropping into split view, it makes the most |
| 264 | // sense to snap this window to the opposite side. Do this. |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 265 | SnapPosition opposite_position = (snap_position == SnapPosition::kPrimary) |
| 266 | ? SnapPosition::kSecondary |
| 267 | : SnapPosition::kPrimary; |
Collin Baker | 512a9d4e | 2020-05-12 19:34:33 | [diff] [blame] | 268 | |
| 269 | // |source_window_| is itself a child window of the browser since it |
| 270 | // hosts web content (specifically, the tab strip WebUI). Snap its |
| 271 | // toplevel window which is the browser window. |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 272 | split_view_controller->SnapWindow(source_window_, opposite_position, |
| 273 | WindowSnapActionSource::kDragTabToSnap); |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 274 | } |
| 275 | |
Yuheng Huang | eeff7861 | 2022-04-27 20:57:01 | [diff] [blame] | 276 | bool TabDragDropDelegate::ShouldPreventSnapToTheEdge( |
| 277 | const gfx::Point& location_in_screen) { |
| 278 | SplitViewController* const split_view_controller = |
| 279 | SplitViewController::Get(source_window_); |
| 280 | return !split_view_controller->InSplitViewMode() && |
sophiewen | e2e8abd | 2023-12-05 18:04:12 | [diff] [blame] | 281 | IsLayoutHorizontal(source_window_) && |
Yuheng Huang | eeff7861 | 2022-04-27 20:57:01 | [diff] [blame] | 282 | location_in_screen.y() < |
| 283 | Shell::Get()->shell_delegate()->GetBrowserWebUITabStripHeight(); |
| 284 | } |
| 285 | |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 286 | void TabDragDropDelegate::UpdateSourceWindowBoundsIfNecessary( |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 287 | SnapPosition candidate_snap_position, |
Yuheng Huang | e141ef2 | 2021-07-07 18:03:51 | [diff] [blame] | 288 | const gfx::Point& location_in_screen) { |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 289 | SplitViewController* const split_view_controller = |
| 290 | SplitViewController::Get(source_window_); |
| 291 | |
| 292 | if (split_view_controller->IsWindowInSplitView(source_window_)) |
| 293 | return; |
| 294 | |
| 295 | if (!windows_hider_) { |
Xiaoqian Dai | ce2f784 | 2023-03-17 20:39:31 | [diff] [blame] | 296 | windows_hider_ = std::make_unique<TabDragDropWindowsHider>(source_window_); |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 297 | } |
| 298 | |
| 299 | gfx::Rect new_source_window_bounds; |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 300 | if (candidate_snap_position == SnapPosition::kNone) { |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 301 | const gfx::Rect area = |
| 302 | screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer( |
| 303 | root_window_); |
| 304 | new_source_window_bounds = area; |
Yuheng Huang | e141ef2 | 2021-07-07 18:03:51 | [diff] [blame] | 305 | |
| 306 | // Only shrink the window when the tab is dragged out of WebUI tab strip. |
| 307 | if (location_in_screen.y() > |
| 308 | Shell::Get()->shell_delegate()->GetBrowserWebUITabStripHeight()) { |
| 309 | new_source_window_bounds.ClampToCenteredSize( |
| 310 | gfx::Size(area.width() * kSourceWindowScale, |
| 311 | area.height() * kSourceWindowScale)); |
| 312 | } |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 313 | } else { |
Michele Fan | 11c9ad84 | 2023-12-08 01:27:26 | [diff] [blame] | 314 | const SnapPosition opposite_position = |
| 315 | (candidate_snap_position == SnapPosition::kPrimary) |
| 316 | ? SnapPosition::kSecondary |
| 317 | : SnapPosition::kPrimary; |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 318 | new_source_window_bounds = |
| 319 | SplitViewController::Get(source_window_) |
Michele Fan | 3c6da02 | 2023-12-09 00:52:45 | [diff] [blame] | 320 | ->GetSnappedWindowBoundsInScreen( |
| 321 | opposite_position, source_window_, |
| 322 | window_util::GetSnapRatioForWindow(source_window_)); |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 323 | } |
| 324 | wm::ConvertRectFromScreen(source_window_->parent(), |
| 325 | &new_source_window_bounds); |
| 326 | |
| 327 | if (new_source_window_bounds != source_window_->GetTargetBounds()) { |
| 328 | ui::ScopedLayerAnimationSettings settings( |
| 329 | source_window_->layer()->GetAnimator()); |
| 330 | settings.SetPreemptionStrategy( |
| 331 | ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET); |
| 332 | source_window_->SetBounds(new_source_window_bounds); |
| 333 | } |
| 334 | } |
| 335 | |
| 336 | void TabDragDropDelegate::RestoreSourceWindowBounds() { |
| 337 | if (SplitViewController::Get(source_window_) |
Sammie Quon | ba51e0d0 | 2023-04-11 19:54:53 | [diff] [blame] | 338 | ->IsWindowInSplitView(source_window_)) { |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 339 | return; |
Sammie Quon | ba51e0d0 | 2023-04-11 19:54:53 | [diff] [blame] | 340 | } |
| 341 | |
| 342 | auto* window_state = WindowState::Get(source_window_); |
| 343 | if (window_state->IsFloated()) { |
| 344 | // This will notify `FloatController` to find the ideal floated window |
| 345 | // bounds in tablet mode. |
| 346 | TabletModeWindowState::UpdateWindowPosition( |
| 347 | window_state, WindowState::BoundsChangeAnimationType::kNone); |
| 348 | return; |
| 349 | } |
Collin Baker | 832c793 | 2020-05-19 22:18:41 | [diff] [blame] | 350 | |
| 351 | const gfx::Rect area = |
| 352 | screen_util::GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer( |
| 353 | root_window_); |
| 354 | |
| 355 | source_window_->SetBounds(area); |
Collin Baker | c6fae37 | 2020-05-01 23:37:47 | [diff] [blame] | 356 | } |
| 357 | |
| 358 | } // namespace ash |