| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2012 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 "ash/common/wm/wm_toplevel_window_event_handler.h" | |
| 6 | |
| 7 #include "ash/common/wm/window_resizer.h" | |
| 8 #include "ash/common/wm/window_state.h" | |
| 9 #include "ash/common/wm/window_state_observer.h" | |
| 10 #include "ash/common/wm/wm_event.h" | |
| 11 #include "ash/common/wm_shell.h" | |
| 12 #include "ash/common/wm_window.h" | |
| 13 #include "ui/aura/window.h" | |
| 14 #include "ui/aura/window_observer.h" | |
| 15 #include "ui/base/hit_test.h" | |
| 16 #include "ui/events/event.h" | |
| 17 | |
| 18 namespace { | |
| 19 const double kMinHorizVelocityForWindowSwipe = 1100; | |
| 20 const double kMinVertVelocityForWindowMinimize = 1000; | |
| 21 } | |
| 22 | |
| 23 namespace ash { | |
| 24 namespace wm { | |
| 25 | |
| 26 namespace { | |
| 27 | |
| 28 // Returns whether |window| can be moved via a two finger drag given | |
| 29 // the hittest results of the two fingers. | |
| 30 bool CanStartTwoFingerMove(WmWindow* window, | |
| 31 int window_component1, | |
| 32 int window_component2) { | |
| 33 // We allow moving a window via two fingers when the hittest components are | |
| 34 // HTCLIENT. This is done so that a window can be dragged via two fingers when | |
| 35 // the tab strip is full and hitting the caption area is difficult. We check | |
| 36 // the window type and the state type so that we do not steal touches from the | |
| 37 // web contents. | |
| 38 if (!window->GetWindowState()->IsNormalOrSnapped() || | |
| 39 window->GetType() != ui::wm::WINDOW_TYPE_NORMAL) { | |
| 40 return false; | |
| 41 } | |
| 42 int component1_behavior = | |
| 43 WindowResizer::GetBoundsChangeForWindowComponent(window_component1); | |
| 44 int component2_behavior = | |
| 45 WindowResizer::GetBoundsChangeForWindowComponent(window_component2); | |
| 46 return (component1_behavior & WindowResizer::kBoundsChange_Resizes) == 0 && | |
| 47 (component2_behavior & WindowResizer::kBoundsChange_Resizes) == 0; | |
| 48 } | |
| 49 | |
| 50 // Returns whether |window| can be moved or resized via one finger given | |
| 51 // |window_component|. | |
| 52 bool CanStartOneFingerDrag(int window_component) { | |
| 53 return WindowResizer::GetBoundsChangeForWindowComponent(window_component) != | |
| 54 0; | |
| 55 } | |
| 56 | |
| 57 // Returns the window component containing |event|'s location. | |
| 58 int GetWindowComponent(WmWindow* window, const ui::LocatedEvent& event) { | |
| 59 return window->GetNonClientComponent(event.location()); | |
| 60 } | |
| 61 | |
| 62 } // namespace | |
| 63 | |
| 64 // ScopedWindowResizer --------------------------------------------------------- | |
| 65 | |
| 66 // Wraps a WindowResizer and installs an observer on its target window. When | |
| 67 // the window is destroyed ResizerWindowDestroyed() is invoked back on the | |
| 68 // WmToplevelWindowEventHandler to clean up. | |
| 69 class WmToplevelWindowEventHandler::ScopedWindowResizer | |
| 70 : public aura::WindowObserver, | |
| 71 public wm::WindowStateObserver { | |
| 72 public: | |
| 73 ScopedWindowResizer(WmToplevelWindowEventHandler* handler, | |
| 74 std::unique_ptr<WindowResizer> resizer); | |
| 75 ~ScopedWindowResizer() override; | |
| 76 | |
| 77 // Returns true if the drag moves the window and does not resize. | |
| 78 bool IsMove() const; | |
| 79 | |
| 80 WindowResizer* resizer() { return resizer_.get(); } | |
| 81 | |
| 82 // WindowObserver overrides: | |
| 83 void OnWindowDestroying(aura::Window* window) override; | |
| 84 | |
| 85 // WindowStateObserver overrides: | |
| 86 void OnPreWindowStateTypeChange(wm::WindowState* window_state, | |
| 87 wm::WindowStateType type) override; | |
| 88 | |
| 89 private: | |
| 90 WmToplevelWindowEventHandler* handler_; | |
| 91 std::unique_ptr<WindowResizer> resizer_; | |
| 92 | |
| 93 // Whether ScopedWindowResizer grabbed capture. | |
| 94 bool grabbed_capture_; | |
| 95 | |
| 96 DISALLOW_COPY_AND_ASSIGN(ScopedWindowResizer); | |
| 97 }; | |
| 98 | |
| 99 WmToplevelWindowEventHandler::ScopedWindowResizer::ScopedWindowResizer( | |
| 100 WmToplevelWindowEventHandler* handler, | |
| 101 std::unique_ptr<WindowResizer> resizer) | |
| 102 : handler_(handler), resizer_(std::move(resizer)), grabbed_capture_(false) { | |
| 103 WmWindow* target = resizer_->GetTarget(); | |
| 104 target->aura_window()->AddObserver(this); | |
| 105 target->GetWindowState()->AddObserver(this); | |
| 106 | |
| 107 if (!target->HasCapture()) { | |
| 108 grabbed_capture_ = true; | |
| 109 target->SetCapture(); | |
| 110 } | |
| 111 } | |
| 112 | |
| 113 WmToplevelWindowEventHandler::ScopedWindowResizer::~ScopedWindowResizer() { | |
| 114 WmWindow* target = resizer_->GetTarget(); | |
| 115 target->aura_window()->RemoveObserver(this); | |
| 116 target->GetWindowState()->RemoveObserver(this); | |
| 117 if (grabbed_capture_) | |
| 118 target->ReleaseCapture(); | |
| 119 } | |
| 120 | |
| 121 bool WmToplevelWindowEventHandler::ScopedWindowResizer::IsMove() const { | |
| 122 return resizer_->details().bounds_change == | |
| 123 WindowResizer::kBoundsChange_Repositions; | |
| 124 } | |
| 125 | |
| 126 void WmToplevelWindowEventHandler::ScopedWindowResizer:: | |
| 127 OnPreWindowStateTypeChange(wm::WindowState* window_state, | |
| 128 wm::WindowStateType old) { | |
| 129 handler_->CompleteDrag(DragResult::SUCCESS); | |
| 130 } | |
| 131 | |
| 132 void WmToplevelWindowEventHandler::ScopedWindowResizer::OnWindowDestroying( | |
| 133 aura::Window* window) { | |
| 134 DCHECK_EQ(resizer_->GetTarget(), WmWindow::Get(window)); | |
| 135 handler_->ResizerWindowDestroyed(); | |
| 136 } | |
| 137 | |
| 138 // WmToplevelWindowEventHandler | |
| 139 // -------------------------------------------------- | |
| 140 | |
| 141 WmToplevelWindowEventHandler::WmToplevelWindowEventHandler(WmShell* shell) | |
| 142 : shell_(shell), first_finger_hittest_(HTNOWHERE) { | |
| 143 shell_->AddDisplayObserver(this); | |
| 144 } | |
| 145 | |
| 146 WmToplevelWindowEventHandler::~WmToplevelWindowEventHandler() { | |
| 147 shell_->RemoveDisplayObserver(this); | |
| 148 } | |
| 149 | |
| 150 void WmToplevelWindowEventHandler::OnKeyEvent(ui::KeyEvent* event) { | |
| 151 if (window_resizer_.get() && event->type() == ui::ET_KEY_PRESSED && | |
| 152 event->key_code() == ui::VKEY_ESCAPE) { | |
| 153 CompleteDrag(DragResult::REVERT); | |
| 154 } | |
| 155 } | |
| 156 | |
| 157 void WmToplevelWindowEventHandler::OnMouseEvent(ui::MouseEvent* event, | |
| 158 WmWindow* target) { | |
| 159 if (event->handled()) | |
| 160 return; | |
| 161 if ((event->flags() & | |
| 162 (ui::EF_MIDDLE_MOUSE_BUTTON | ui::EF_RIGHT_MOUSE_BUTTON)) != 0) | |
| 163 return; | |
| 164 | |
| 165 if (event->type() == ui::ET_MOUSE_CAPTURE_CHANGED) { | |
| 166 // Capture is grabbed when both gesture and mouse drags start. Handle | |
| 167 // capture loss regardless of which type of drag is in progress. | |
| 168 HandleCaptureLost(event); | |
| 169 return; | |
| 170 } | |
| 171 | |
| 172 if (in_gesture_drag_) | |
| 173 return; | |
| 174 | |
| 175 switch (event->type()) { | |
| 176 case ui::ET_MOUSE_PRESSED: | |
| 177 HandleMousePressed(target, event); | |
| 178 break; | |
| 179 case ui::ET_MOUSE_DRAGGED: | |
| 180 HandleDrag(target, event); | |
| 181 break; | |
| 182 case ui::ET_MOUSE_RELEASED: | |
| 183 HandleMouseReleased(target, event); | |
| 184 break; | |
| 185 case ui::ET_MOUSE_MOVED: | |
| 186 HandleMouseMoved(target, event); | |
| 187 break; | |
| 188 case ui::ET_MOUSE_EXITED: | |
| 189 HandleMouseExited(target, event); | |
| 190 break; | |
| 191 default: | |
| 192 break; | |
| 193 } | |
| 194 } | |
| 195 | |
| 196 void WmToplevelWindowEventHandler::OnGestureEvent(ui::GestureEvent* event, | |
| 197 WmWindow* target) { | |
| 198 if (event->handled()) | |
| 199 return; | |
| 200 if (!target->HasNonClientArea()) | |
| 201 return; | |
| 202 | |
| 203 if (window_resizer_.get() && !in_gesture_drag_) | |
| 204 return; | |
| 205 | |
| 206 if (window_resizer_.get() && | |
| 207 window_resizer_->resizer()->GetTarget() != target) { | |
| 208 return; | |
| 209 } | |
| 210 | |
| 211 if (event->details().touch_points() > 2) { | |
| 212 if (CompleteDrag(DragResult::SUCCESS)) | |
| 213 event->StopPropagation(); | |
| 214 return; | |
| 215 } | |
| 216 | |
| 217 switch (event->type()) { | |
| 218 case ui::ET_GESTURE_TAP_DOWN: { | |
| 219 int component = GetWindowComponent(target, *event); | |
| 220 if (!(WindowResizer::GetBoundsChangeForWindowComponent(component) & | |
| 221 WindowResizer::kBoundsChange_Resizes)) | |
| 222 return; | |
| 223 target->ShowResizeShadow(component); | |
| 224 return; | |
| 225 } | |
| 226 case ui::ET_GESTURE_END: { | |
| 227 target->HideResizeShadow(); | |
| 228 | |
| 229 if (window_resizer_.get() && | |
| 230 (event->details().touch_points() == 1 || | |
| 231 !CanStartOneFingerDrag(first_finger_hittest_))) { | |
| 232 CompleteDrag(DragResult::SUCCESS); | |
| 233 event->StopPropagation(); | |
| 234 } | |
| 235 return; | |
| 236 } | |
| 237 case ui::ET_GESTURE_BEGIN: { | |
| 238 if (event->details().touch_points() == 1) { | |
| 239 first_finger_hittest_ = GetWindowComponent(target, *event); | |
| 240 } else if (window_resizer_.get()) { | |
| 241 if (!window_resizer_->IsMove()) { | |
| 242 // The transition from resizing with one finger to resizing with two | |
| 243 // fingers causes unintended resizing because the location of | |
| 244 // ET_GESTURE_SCROLL_UPDATE jumps from the position of the first | |
| 245 // finger to the position in the middle of the two fingers. For this | |
| 246 // reason two finger resizing is not supported. | |
| 247 CompleteDrag(DragResult::SUCCESS); | |
| 248 event->StopPropagation(); | |
| 249 } | |
| 250 } else { | |
| 251 int second_finger_hittest = GetWindowComponent(target, *event); | |
| 252 if (CanStartTwoFingerMove(target, first_finger_hittest_, | |
| 253 second_finger_hittest)) { | |
| 254 gfx::Point location_in_parent = | |
| 255 event->details().bounding_box().CenterPoint(); | |
| 256 AttemptToStartDrag(target, location_in_parent, HTCAPTION, | |
| 257 aura::client::WINDOW_MOVE_SOURCE_TOUCH, | |
| 258 EndClosure()); | |
| 259 event->StopPropagation(); | |
| 260 } | |
| 261 } | |
| 262 return; | |
| 263 } | |
| 264 case ui::ET_GESTURE_SCROLL_BEGIN: { | |
| 265 // The one finger drag is not started in ET_GESTURE_BEGIN to avoid the | |
| 266 // window jumping upon initiating a two finger drag. When a one finger | |
| 267 // drag is converted to a two finger drag, a jump occurs because the | |
| 268 // location of the ET_GESTURE_SCROLL_UPDATE event switches from the single | |
| 269 // finger's position to the position in the middle of the two fingers. | |
| 270 if (window_resizer_.get()) | |
| 271 return; | |
| 272 int component = GetWindowComponent(target, *event); | |
| 273 if (!CanStartOneFingerDrag(component)) | |
| 274 return; | |
| 275 gfx::Point location_in_parent( | |
| 276 target->ConvertPointToTarget(target->GetParent(), event->location())); | |
| 277 AttemptToStartDrag(target, location_in_parent, component, | |
| 278 aura::client::WINDOW_MOVE_SOURCE_TOUCH, EndClosure()); | |
| 279 event->StopPropagation(); | |
| 280 return; | |
| 281 } | |
| 282 default: | |
| 283 break; | |
| 284 } | |
| 285 | |
| 286 if (!window_resizer_.get()) | |
| 287 return; | |
| 288 | |
| 289 switch (event->type()) { | |
| 290 case ui::ET_GESTURE_SCROLL_UPDATE: | |
| 291 HandleDrag(target, event); | |
| 292 event->StopPropagation(); | |
| 293 return; | |
| 294 case ui::ET_GESTURE_SCROLL_END: | |
| 295 // We must complete the drag here instead of as a result of ET_GESTURE_END | |
| 296 // because otherwise the drag will be reverted when EndMoveLoop() is | |
| 297 // called. | |
| 298 // TODO(pkotwicz): Pass drag completion status to | |
| 299 // WindowMoveClient::EndMoveLoop(). | |
| 300 CompleteDrag(DragResult::SUCCESS); | |
| 301 event->StopPropagation(); | |
| 302 return; | |
| 303 case ui::ET_SCROLL_FLING_START: | |
| 304 CompleteDrag(DragResult::SUCCESS); | |
| 305 | |
| 306 // TODO(pkotwicz): Fix tests which inadvertantly start flings and check | |
| 307 // window_resizer_->IsMove() instead of the hittest component at |event|'s | |
| 308 // location. | |
| 309 if (GetWindowComponent(target, *event) != HTCAPTION || | |
| 310 !target->GetWindowState()->IsNormalOrSnapped()) { | |
| 311 return; | |
| 312 } | |
| 313 | |
| 314 if (event->details().velocity_y() > kMinVertVelocityForWindowMinimize) { | |
| 315 SetWindowStateTypeFromGesture(target, wm::WINDOW_STATE_TYPE_MINIMIZED); | |
| 316 } else if (event->details().velocity_y() < | |
| 317 -kMinVertVelocityForWindowMinimize) { | |
| 318 SetWindowStateTypeFromGesture(target, wm::WINDOW_STATE_TYPE_MAXIMIZED); | |
| 319 } else if (event->details().velocity_x() > | |
| 320 kMinHorizVelocityForWindowSwipe) { | |
| 321 SetWindowStateTypeFromGesture(target, | |
| 322 wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED); | |
| 323 } else if (event->details().velocity_x() < | |
| 324 -kMinHorizVelocityForWindowSwipe) { | |
| 325 SetWindowStateTypeFromGesture(target, | |
| 326 wm::WINDOW_STATE_TYPE_LEFT_SNAPPED); | |
| 327 } | |
| 328 event->StopPropagation(); | |
| 329 return; | |
| 330 case ui::ET_GESTURE_SWIPE: | |
| 331 DCHECK_GT(event->details().touch_points(), 0); | |
| 332 if (event->details().touch_points() == 1) | |
| 333 return; | |
| 334 if (!target->GetWindowState()->IsNormalOrSnapped()) | |
| 335 return; | |
| 336 | |
| 337 CompleteDrag(DragResult::SUCCESS); | |
| 338 | |
| 339 if (event->details().swipe_down()) { | |
| 340 SetWindowStateTypeFromGesture(target, wm::WINDOW_STATE_TYPE_MINIMIZED); | |
| 341 } else if (event->details().swipe_up()) { | |
| 342 SetWindowStateTypeFromGesture(target, wm::WINDOW_STATE_TYPE_MAXIMIZED); | |
| 343 } else if (event->details().swipe_right()) { | |
| 344 SetWindowStateTypeFromGesture(target, | |
| 345 wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED); | |
| 346 } else { | |
| 347 SetWindowStateTypeFromGesture(target, | |
| 348 wm::WINDOW_STATE_TYPE_LEFT_SNAPPED); | |
| 349 } | |
| 350 event->StopPropagation(); | |
| 351 return; | |
| 352 default: | |
| 353 return; | |
| 354 } | |
| 355 } | |
| 356 | |
| 357 bool WmToplevelWindowEventHandler::AttemptToStartDrag( | |
| 358 WmWindow* window, | |
| 359 const gfx::Point& point_in_parent, | |
| 360 int window_component, | |
| 361 aura::client::WindowMoveSource source, | |
| 362 const EndClosure& end_closure) { | |
| 363 if (window_resizer_.get()) | |
| 364 return false; | |
| 365 std::unique_ptr<WindowResizer> resizer( | |
| 366 CreateWindowResizer(window, point_in_parent, window_component, source)); | |
| 367 if (!resizer) | |
| 368 return false; | |
| 369 | |
| 370 end_closure_ = end_closure; | |
| 371 window_resizer_.reset(new ScopedWindowResizer(this, std::move(resizer))); | |
| 372 | |
| 373 pre_drag_window_bounds_ = window->GetBounds(); | |
| 374 in_gesture_drag_ = (source == aura::client::WINDOW_MOVE_SOURCE_TOUCH); | |
| 375 return true; | |
| 376 } | |
| 377 | |
| 378 void WmToplevelWindowEventHandler::RevertDrag() { | |
| 379 CompleteDrag(DragResult::REVERT); | |
| 380 } | |
| 381 | |
| 382 bool WmToplevelWindowEventHandler::CompleteDrag(DragResult result) { | |
| 383 if (!window_resizer_) | |
| 384 return false; | |
| 385 | |
| 386 std::unique_ptr<ScopedWindowResizer> resizer(std::move(window_resizer_)); | |
| 387 switch (result) { | |
| 388 case DragResult::SUCCESS: | |
| 389 resizer->resizer()->CompleteDrag(); | |
| 390 break; | |
| 391 case DragResult::REVERT: | |
| 392 resizer->resizer()->RevertDrag(); | |
| 393 break; | |
| 394 case DragResult::WINDOW_DESTROYED: | |
| 395 // We explicitly do not invoke RevertDrag() since that may do things to | |
| 396 // the window that was destroyed. | |
| 397 break; | |
| 398 } | |
| 399 | |
| 400 first_finger_hittest_ = HTNOWHERE; | |
| 401 in_gesture_drag_ = false; | |
| 402 if (!end_closure_.is_null()) { | |
| 403 // Clear local state in case running the closure deletes us. | |
| 404 EndClosure end_closure = end_closure_; | |
| 405 end_closure_.Reset(); | |
| 406 end_closure.Run(result); | |
| 407 } | |
| 408 return true; | |
| 409 } | |
| 410 | |
| 411 void WmToplevelWindowEventHandler::HandleMousePressed(WmWindow* target, | |
| 412 ui::MouseEvent* event) { | |
| 413 if (event->phase() != ui::EP_PRETARGET || !target->HasNonClientArea()) | |
| 414 return; | |
| 415 | |
| 416 // We also update the current window component here because for the | |
| 417 // mouse-drag-release-press case, where the mouse is released and | |
| 418 // pressed without mouse move event. | |
| 419 int component = GetWindowComponent(target, *event); | |
| 420 if ((event->flags() & (ui::EF_IS_DOUBLE_CLICK | ui::EF_IS_TRIPLE_CLICK)) == | |
| 421 0 && | |
| 422 WindowResizer::GetBoundsChangeForWindowComponent(component)) { | |
| 423 gfx::Point location_in_parent( | |
| 424 target->ConvertPointToTarget(target->GetParent(), event->location())); | |
| 425 AttemptToStartDrag(target, location_in_parent, component, | |
| 426 aura::client::WINDOW_MOVE_SOURCE_MOUSE, EndClosure()); | |
| 427 // Set as handled so that other event handlers do no act upon the event | |
| 428 // but still receive it so that they receive both parts of each pressed/ | |
| 429 // released pair. | |
| 430 event->SetHandled(); | |
| 431 } else { | |
| 432 CompleteDrag(DragResult::SUCCESS); | |
| 433 } | |
| 434 } | |
| 435 | |
| 436 void WmToplevelWindowEventHandler::HandleMouseReleased(WmWindow* target, | |
| 437 ui::MouseEvent* event) { | |
| 438 if (event->phase() == ui::EP_PRETARGET) | |
| 439 CompleteDrag(DragResult::SUCCESS); | |
| 440 } | |
| 441 | |
| 442 void WmToplevelWindowEventHandler::HandleDrag(WmWindow* target, | |
| 443 ui::LocatedEvent* event) { | |
| 444 // This function only be triggered to move window | |
| 445 // by mouse drag or touch move event. | |
| 446 DCHECK(event->type() == ui::ET_MOUSE_DRAGGED || | |
| 447 event->type() == ui::ET_TOUCH_MOVED || | |
| 448 event->type() == ui::ET_GESTURE_SCROLL_UPDATE); | |
| 449 | |
| 450 // Drag actions are performed pre-target handling to prevent spurious mouse | |
| 451 // moves from the move/size operation from being sent to the target. | |
| 452 if (event->phase() != ui::EP_PRETARGET) | |
| 453 return; | |
| 454 | |
| 455 if (!window_resizer_) | |
| 456 return; | |
| 457 window_resizer_->resizer()->Drag( | |
| 458 target->ConvertPointToTarget(target->GetParent(), event->location()), | |
| 459 event->flags()); | |
| 460 event->StopPropagation(); | |
| 461 } | |
| 462 | |
| 463 void WmToplevelWindowEventHandler::HandleMouseMoved(WmWindow* target, | |
| 464 ui::LocatedEvent* event) { | |
| 465 // Shadow effects are applied after target handling. Note that we don't | |
| 466 // respect ER_HANDLED here right now since we have not had a reason to allow | |
| 467 // the target to cancel shadow rendering. | |
| 468 if (event->phase() != ui::EP_POSTTARGET || !target->HasNonClientArea()) | |
| 469 return; | |
| 470 | |
| 471 // TODO(jamescook): Move the resize cursor update code into here from | |
| 472 // CompoundEventFilter? | |
| 473 if (event->flags() & ui::EF_IS_NON_CLIENT) { | |
| 474 int component = target->GetNonClientComponent(event->location()); | |
| 475 target->ShowResizeShadow(component); | |
| 476 } else { | |
| 477 target->HideResizeShadow(); | |
| 478 } | |
| 479 } | |
| 480 | |
| 481 void WmToplevelWindowEventHandler::HandleMouseExited(WmWindow* target, | |
| 482 ui::LocatedEvent* event) { | |
| 483 // Shadow effects are applied after target handling. Note that we don't | |
| 484 // respect ER_HANDLED here right now since we have not had a reason to allow | |
| 485 // the target to cancel shadow rendering. | |
| 486 if (event->phase() != ui::EP_POSTTARGET) | |
| 487 return; | |
| 488 | |
| 489 target->HideResizeShadow(); | |
| 490 } | |
| 491 | |
| 492 void WmToplevelWindowEventHandler::HandleCaptureLost(ui::LocatedEvent* event) { | |
| 493 if (event->phase() == ui::EP_PRETARGET) { | |
| 494 // We complete the drag instead of reverting it, as reverting it will result | |
| 495 // in a weird behavior when a dragged tab produces a modal dialog while the | |
| 496 // drag is in progress. crbug.com/558201. | |
| 497 CompleteDrag(DragResult::SUCCESS); | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 void WmToplevelWindowEventHandler::SetWindowStateTypeFromGesture( | |
| 502 WmWindow* window, | |
| 503 wm::WindowStateType new_state_type) { | |
| 504 wm::WindowState* window_state = window->GetWindowState(); | |
| 505 // TODO(oshima): Move extra logic (set_unminimize_to_restore_bounds, | |
| 506 // SetRestoreBoundsInParent) that modifies the window state | |
| 507 // into WindowState. | |
| 508 switch (new_state_type) { | |
| 509 case wm::WINDOW_STATE_TYPE_MINIMIZED: | |
| 510 if (window_state->CanMinimize()) { | |
| 511 window_state->Minimize(); | |
| 512 window_state->set_unminimize_to_restore_bounds(true); | |
| 513 window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); | |
| 514 } | |
| 515 break; | |
| 516 case wm::WINDOW_STATE_TYPE_MAXIMIZED: | |
| 517 if (window_state->CanMaximize()) { | |
| 518 window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); | |
| 519 window_state->Maximize(); | |
| 520 } | |
| 521 break; | |
| 522 case wm::WINDOW_STATE_TYPE_LEFT_SNAPPED: | |
| 523 if (window_state->CanSnap()) { | |
| 524 window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); | |
| 525 const wm::WMEvent event(wm::WM_EVENT_SNAP_LEFT); | |
| 526 window_state->OnWMEvent(&event); | |
| 527 } | |
| 528 break; | |
| 529 case wm::WINDOW_STATE_TYPE_RIGHT_SNAPPED: | |
| 530 if (window_state->CanSnap()) { | |
| 531 window_state->SetRestoreBoundsInParent(pre_drag_window_bounds_); | |
| 532 const wm::WMEvent event(wm::WM_EVENT_SNAP_RIGHT); | |
| 533 window_state->OnWMEvent(&event); | |
| 534 } | |
| 535 break; | |
| 536 default: | |
| 537 NOTREACHED(); | |
| 538 } | |
| 539 } | |
| 540 | |
| 541 void WmToplevelWindowEventHandler::ResizerWindowDestroyed() { | |
| 542 CompleteDrag(DragResult::WINDOW_DESTROYED); | |
| 543 } | |
| 544 | |
| 545 void WmToplevelWindowEventHandler::OnDisplayConfigurationChanging() { | |
| 546 CompleteDrag(DragResult::REVERT); | |
| 547 } | |
| 548 | |
| 549 } // namespace wm | |
| 550 } // namespace ash | |
| OLD | NEW |