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