Avi Drissman | 3a215d1e | 2022-09-07 19:43:09 | [diff] [blame] | 1 | // Copyright 2018 The Chromium Authors |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [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 | |
Evan Stade | eb42d77 | 2019-05-03 01:51:34 | [diff] [blame] | 5 | #include "ash/frame/snap_controller_impl.h" |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 6 | |
Sophie Wen | 68b8f2f | 2024-06-20 18:27:36 | [diff] [blame] | 7 | #include "ash/wm/splitview/split_view_utils.h" |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 8 | #include "ash/wm/window_positioning_utils.h" |
| 9 | #include "ash/wm/window_state.h" |
| 10 | #include "ash/wm/wm_event.h" |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 11 | #include "ash/wm/wm_metrics.h" |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 12 | #include "ash/wm/workspace/phantom_window_controller.h" |
Sammie Quon | 7e9455c | 2023-10-27 20:06:27 | [diff] [blame] | 13 | #include "chromeos/utils/haptics_util.h" |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 14 | #include "ui/aura/window.h" |
Yongshun Liu | 7c7c855b | 2021-11-16 19:46:03 | [diff] [blame] | 15 | #include "ui/events/devices/haptic_touchpad_effects.h" |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 16 | #include "ui/wm/core/coordinate_conversion.h" |
| 17 | |
| 18 | namespace ash { |
| 19 | |
Evan Stade | eb42d77 | 2019-05-03 01:51:34 | [diff] [blame] | 20 | SnapControllerImpl::SnapControllerImpl() = default; |
| 21 | SnapControllerImpl::~SnapControllerImpl() = default; |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 22 | |
Evan Stade | eb42d77 | 2019-05-03 01:51:34 | [diff] [blame] | 23 | bool SnapControllerImpl::CanSnap(aura::Window* window) { |
James Cook | 00e65e9 | 2019-07-25 03:19:08 | [diff] [blame] | 24 | return WindowState::Get(window)->CanSnap(); |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 25 | } |
| 26 | |
Evan Stade | eb42d77 | 2019-05-03 01:51:34 | [diff] [blame] | 27 | void SnapControllerImpl::ShowSnapPreview(aura::Window* window, |
Yongshun Liu | 7c7c855b | 2021-11-16 19:46:03 | [diff] [blame] | 28 | chromeos::SnapDirection snap, |
| 29 | bool allow_haptic_feedback) { |
Antonio Gomes | 5c83325 | 2020-10-13 18:42:19 | [diff] [blame] | 30 | if (snap == chromeos::SnapDirection::kNone) { |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 31 | phantom_window_controller_.reset(); |
| 32 | return; |
| 33 | } |
| 34 | |
| 35 | if (!phantom_window_controller_ || |
| 36 | phantom_window_controller_->window() != window) { |
| 37 | phantom_window_controller_ = |
| 38 | std::make_unique<PhantomWindowController>(window); |
| 39 | } |
Cattalyya Nuengsigkapian | ffc3961 | 2021-10-02 00:14:23 | [diff] [blame] | 40 | const SnapViewType snap_type = snap == chromeos::SnapDirection::kPrimary |
| 41 | ? SnapViewType::kPrimary |
| 42 | : SnapViewType::kSecondary; |
Sophie Wen | 68b8f2f | 2024-06-20 18:27:36 | [diff] [blame] | 43 | gfx::Rect phantom_bounds_in_screen = GetSnappedWindowBoundsInParent( |
| 44 | window, snap_type, |
| 45 | GetPhantomSnapRatio(window, window->GetRootWindow(), snap_type)); |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 46 | ::wm::ConvertRectToScreen(window->parent(), &phantom_bounds_in_screen); |
Yongshun Liu | 7c7c855b | 2021-11-16 19:46:03 | [diff] [blame] | 47 | |
| 48 | const bool need_haptic_feedback = |
| 49 | allow_haptic_feedback && |
| 50 | phantom_window_controller_->GetTargetWindowBounds() != |
| 51 | phantom_bounds_in_screen; |
| 52 | |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 53 | phantom_window_controller_->Show(phantom_bounds_in_screen); |
Yongshun Liu | 7c7c855b | 2021-11-16 19:46:03 | [diff] [blame] | 54 | |
| 55 | // Fire a haptic event if necessary. |
| 56 | if (need_haptic_feedback) { |
Sammie Quon | 7e9455c | 2023-10-27 20:06:27 | [diff] [blame] | 57 | chromeos::haptics_util::PlayHapticTouchpadEffect( |
Yongshun Liu | 7c7c855b | 2021-11-16 19:46:03 | [diff] [blame] | 58 | ui::HapticTouchpadEffect::kSnap, |
| 59 | ui::HapticTouchpadEffectStrength::kMedium); |
| 60 | } |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 61 | } |
| 62 | |
Antonio Gomes | 5c83325 | 2020-10-13 18:42:19 | [diff] [blame] | 63 | void SnapControllerImpl::CommitSnap(aura::Window* window, |
Sophie Wen | e41f451 | 2022-07-25 18:38:58 | [diff] [blame] | 64 | chromeos::SnapDirection snap, |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 65 | float snap_ratio, |
| 66 | SnapRequestSource snap_request_source) { |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 67 | phantom_window_controller_.reset(); |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 68 | if (snap == chromeos::SnapDirection::kNone) { |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 69 | return; |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 70 | } |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 71 | |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 72 | WindowSnapActionSource snap_action_source = |
| 73 | WindowSnapActionSource::kNotSpecified; |
| 74 | switch (snap_request_source) { |
| 75 | case SnapRequestSource::kSnapButton: |
| 76 | snap_action_source = |
| 77 | WindowSnapActionSource::kLongPressCaptionButtonToSnap; |
| 78 | break; |
| 79 | case SnapRequestSource::kWindowLayoutMenu: |
| 80 | snap_action_source = WindowSnapActionSource::kSnapByWindowLayoutMenu; |
| 81 | break; |
| 82 | case SnapRequestSource::kFromLacrosSnapButtonOrWindowLayoutMenu: |
Michele Fan | fdb37542 | 2024-02-07 01:36:20 | [diff] [blame] | 83 | snap_action_source = |
| 84 | WindowSnapActionSource::kLacrosSnapButtonOrWindowLayoutMenu; |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 85 | break; |
| 86 | } |
| 87 | |
Xiaoqian Dai | bd3d237f | 2023-04-29 00:18:46 | [diff] [blame] | 88 | const WindowSnapWMEvent snap_event(snap == chromeos::SnapDirection::kPrimary |
| 89 | ? WM_EVENT_SNAP_PRIMARY |
| 90 | : WM_EVENT_SNAP_SECONDARY, |
Xiaoqian Dai | 1fbf010 | 2023-04-29 00:39:04 | [diff] [blame] | 91 | snap_ratio, snap_action_source); |
| 92 | WindowState::Get(window)->OnWMEvent(&snap_event); |
Evan Stade | 1b050fed | 2018-09-21 21:17:17 | [diff] [blame] | 93 | } |
| 94 | |
| 95 | } // namespace ash |