| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 #include "mash/wm/frame/move_loop.h" | |
| 6 | |
| 7 #include "base/auto_reset.h" | |
| 8 #include "base/memory/ptr_util.h" | |
| 9 #include "components/mus/public/cpp/window.h" | |
| 10 #include "components/mus/public/interfaces/input_event_constants.mojom.h" | |
| 11 #include "mash/wm/property_util.h" | |
| 12 #include "ui/base/hit_test.h" | |
| 13 #include "ui/events/event.h" | |
| 14 #include "ui/gfx/geometry/point_conversions.h" | |
| 15 #include "ui/gfx/geometry/rect.h" | |
| 16 | |
| 17 namespace mash { | |
| 18 namespace wm { | |
| 19 | |
| 20 namespace { | |
| 21 | |
| 22 int MouseOnlyEventFlags(int flags) { | |
| 23 return flags & (ui::EF_LEFT_MOUSE_BUTTON | ui::EF_MIDDLE_MOUSE_BUTTON | | |
| 24 ui::EF_RIGHT_MOUSE_BUTTON); | |
| 25 } | |
| 26 | |
| 27 } // namespace | |
| 28 | |
| 29 MoveLoop::~MoveLoop() { | |
| 30 if (target_) | |
| 31 target_->RemoveObserver(this); | |
| 32 } | |
| 33 | |
| 34 // static | |
| 35 std::unique_ptr<MoveLoop> MoveLoop::Create(mus::Window* target, | |
| 36 int ht_location, | |
| 37 const ui::PointerEvent& event) { | |
| 38 DCHECK_EQ(event.type(), ui::ET_POINTER_DOWN); | |
| 39 // Start a move on left mouse, or any other type of pointer. | |
| 40 if (event.IsMousePointerEvent() && | |
| 41 MouseOnlyEventFlags(event.flags()) != ui::EF_LEFT_MOUSE_BUTTON) { | |
| 42 return nullptr; | |
| 43 } | |
| 44 | |
| 45 Type type; | |
| 46 HorizontalLocation h_loc; | |
| 47 VerticalLocation v_loc; | |
| 48 if (!DetermineType(ht_location, &type, &h_loc, &v_loc)) | |
| 49 return nullptr; | |
| 50 | |
| 51 return base::WrapUnique(new MoveLoop(target, event, type, h_loc, v_loc)); | |
| 52 } | |
| 53 | |
| 54 MoveLoop::MoveResult MoveLoop::Move(const ui::PointerEvent& event) { | |
| 55 switch (event.type()) { | |
| 56 case ui::ET_POINTER_CANCELLED: | |
| 57 if (event.pointer_id() == pointer_id_) { | |
| 58 if (target_) | |
| 59 Revert(); | |
| 60 return MoveResult::DONE; | |
| 61 } | |
| 62 return MoveResult::CONTINUE; | |
| 63 | |
| 64 case ui::ET_POINTER_MOVED: | |
| 65 if (target_ && event.pointer_id() == pointer_id_) | |
| 66 MoveImpl(event); | |
| 67 return MoveResult::CONTINUE; | |
| 68 | |
| 69 case ui::ET_POINTER_UP: | |
| 70 if (event.pointer_id() == pointer_id_) { | |
| 71 // TODO(sky): need to support changed_flags. | |
| 72 if (target_) | |
| 73 MoveImpl(event); | |
| 74 return MoveResult::DONE; | |
| 75 } | |
| 76 return MoveResult::CONTINUE; | |
| 77 | |
| 78 default: | |
| 79 break; | |
| 80 } | |
| 81 | |
| 82 return MoveResult::CONTINUE; | |
| 83 } | |
| 84 | |
| 85 void MoveLoop::Revert() { | |
| 86 if (!target_) | |
| 87 return; | |
| 88 | |
| 89 base::AutoReset<bool> resetter(&changing_bounds_, true); | |
| 90 target_->SetBounds(initial_window_bounds_); | |
| 91 SetWindowUserSetBounds(target_, initial_user_set_bounds_); | |
| 92 } | |
| 93 | |
| 94 MoveLoop::MoveLoop(mus::Window* target, | |
| 95 const ui::PointerEvent& event, | |
| 96 Type type, | |
| 97 HorizontalLocation h_loc, | |
| 98 VerticalLocation v_loc) | |
| 99 : target_(target), | |
| 100 type_(type), | |
| 101 h_loc_(h_loc), | |
| 102 v_loc_(v_loc), | |
| 103 pointer_id_(event.pointer_id()), | |
| 104 initial_event_screen_location_(event.root_location()), | |
| 105 initial_window_bounds_(target->bounds()), | |
| 106 initial_user_set_bounds_(GetWindowUserSetBounds(target)), | |
| 107 changing_bounds_(false) { | |
| 108 target->AddObserver(this); | |
| 109 } | |
| 110 | |
| 111 // static | |
| 112 bool MoveLoop::DetermineType(int ht_location, | |
| 113 Type* type, | |
| 114 HorizontalLocation* h_loc, | |
| 115 VerticalLocation* v_loc) { | |
| 116 *h_loc = HorizontalLocation::OTHER; | |
| 117 *v_loc = VerticalLocation::OTHER; | |
| 118 switch (ht_location) { | |
| 119 case HTCAPTION: | |
| 120 *type = Type::MOVE; | |
| 121 *v_loc = VerticalLocation::TOP; | |
| 122 return true; | |
| 123 case HTTOPLEFT: | |
| 124 *type = Type::RESIZE; | |
| 125 *v_loc = VerticalLocation::TOP; | |
| 126 *h_loc = HorizontalLocation::LEFT; | |
| 127 return true; | |
| 128 case HTTOP: | |
| 129 *type = Type::RESIZE; | |
| 130 *v_loc = VerticalLocation::TOP; | |
| 131 return true; | |
| 132 case HTTOPRIGHT: | |
| 133 *type = Type::RESIZE; | |
| 134 *v_loc = VerticalLocation::TOP; | |
| 135 *h_loc = HorizontalLocation::RIGHT; | |
| 136 return true; | |
| 137 case HTRIGHT: | |
| 138 *type = Type::RESIZE; | |
| 139 *h_loc = HorizontalLocation::RIGHT; | |
| 140 return true; | |
| 141 case HTBOTTOMRIGHT: | |
| 142 *type = Type::RESIZE; | |
| 143 *v_loc = VerticalLocation::BOTTOM; | |
| 144 *h_loc = HorizontalLocation::RIGHT; | |
| 145 return true; | |
| 146 case HTBOTTOM: | |
| 147 *type = Type::RESIZE; | |
| 148 *v_loc = VerticalLocation::BOTTOM; | |
| 149 return true; | |
| 150 case HTBOTTOMLEFT: | |
| 151 *type = Type::RESIZE; | |
| 152 *v_loc = VerticalLocation::BOTTOM; | |
| 153 *h_loc = HorizontalLocation::LEFT; | |
| 154 return true; | |
| 155 case HTLEFT: | |
| 156 *type = Type::RESIZE; | |
| 157 *h_loc = HorizontalLocation::LEFT; | |
| 158 return true; | |
| 159 default: | |
| 160 break; | |
| 161 } | |
| 162 return false; | |
| 163 } | |
| 164 | |
| 165 void MoveLoop::MoveImpl(const ui::PointerEvent& event) { | |
| 166 const gfx::Vector2d delta = | |
| 167 event.root_location() - initial_event_screen_location_; | |
| 168 const gfx::Rect new_bounds(DetermineBoundsFromDelta(delta)); | |
| 169 base::AutoReset<bool> resetter(&changing_bounds_, true); | |
| 170 target_->SetBounds(new_bounds); | |
| 171 SetWindowUserSetBounds(target_, new_bounds); | |
| 172 } | |
| 173 | |
| 174 void MoveLoop::Cancel() { | |
| 175 target_->RemoveObserver(this); | |
| 176 target_ = nullptr; | |
| 177 } | |
| 178 | |
| 179 gfx::Rect MoveLoop::DetermineBoundsFromDelta(const gfx::Vector2d& delta) { | |
| 180 if (type_ == Type::MOVE) { | |
| 181 return gfx::Rect(initial_window_bounds_.origin() + delta, | |
| 182 initial_window_bounds_.size()); | |
| 183 } | |
| 184 | |
| 185 // TODO(sky): support better min sizes, make sure doesn't get bigger than | |
| 186 // screen and max. Also make sure keep some portion on screen. | |
| 187 gfx::Rect bounds(initial_window_bounds_); | |
| 188 if (h_loc_ == HorizontalLocation::LEFT) { | |
| 189 const int x = std::min(bounds.right() - 1, bounds.x() + delta.x()); | |
| 190 const int width = bounds.right() - x; | |
| 191 bounds.set_x(x); | |
| 192 bounds.set_width(width); | |
| 193 } else if (h_loc_ == HorizontalLocation::RIGHT) { | |
| 194 bounds.set_width(std::max(1, bounds.width() + delta.x())); | |
| 195 } | |
| 196 | |
| 197 if (v_loc_ == VerticalLocation::TOP) { | |
| 198 const int y = std::min(bounds.bottom() - 1, bounds.y() + delta.y()); | |
| 199 const int height = bounds.bottom() - y; | |
| 200 bounds.set_y(y); | |
| 201 bounds.set_height(height); | |
| 202 } else if (v_loc_ == VerticalLocation::BOTTOM) { | |
| 203 bounds.set_height(std::max(1, bounds.height() + delta.y())); | |
| 204 } | |
| 205 | |
| 206 return bounds; | |
| 207 } | |
| 208 | |
| 209 void MoveLoop::OnTreeChanged(const TreeChangeParams& params) { | |
| 210 if (params.target == target_) | |
| 211 Cancel(); | |
| 212 } | |
| 213 | |
| 214 void MoveLoop::OnWindowBoundsChanged(mus::Window* window, | |
| 215 const gfx::Rect& old_bounds, | |
| 216 const gfx::Rect& new_bounds) { | |
| 217 DCHECK_EQ(window, target_); | |
| 218 if (!changing_bounds_) | |
| 219 Cancel(); | |
| 220 } | |
| 221 | |
| 222 void MoveLoop::OnWindowVisibilityChanged(mus::Window* window) { | |
| 223 DCHECK_EQ(window, target_); | |
| 224 Cancel(); | |
| 225 } | |
| 226 | |
| 227 } // namespace wm | |
| 228 } // namespace mash | |
| OLD | NEW |