1 // Copyright 2019 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 #ifndef ASH_WM_COLLISION_DETECTION_COLLISION_DETECTION_UTILS_H_ 6 #define ASH_WM_COLLISION_DETECTION_COLLISION_DETECTION_UTILS_H_ 7 8 #include "ash/ash_export.h" 9 #include "ui/aura/window.h" 10 #include "ui/display/display.h" 11 #include "ui/gfx/geometry/rect.h" 12 13 namespace ash { 14 15 // The inset into the work area for a window's resting position. Visible for 16 // testing. 17 const static int kCollisionWindowWorkAreaInsetsDp = 8; 18 19 // Provides utility functions to compute resting positions for windows which 20 // wish to avoid other system windows, for example, the PIP and the Automatic 21 // Clicks bubble menu. 22 class ASH_EXPORT CollisionDetectionUtils { 23 public: 24 enum class Gravity { 25 kGravityLeft, 26 kGravityRight, 27 kGravityTop, 28 kGravityBottom, 29 }; 30 31 // Ordered list of windows which do collision detection. Higher numbers take 32 // higher priority, i.e. the higher RelativePriority of two windows will not 33 // move when the windows are in conflict. For example, the Picture in Picture 34 // window will move out of the way for the Automatic Clicks menu, and both 35 // will move out of the way for the Automatic Clicks scroll menu, and all 36 // will move for default system windows. Windows with the same relative 37 // priority will not affect collision with each other. kDefault is used for 38 // "everything else", and should not be an input to GetRestingPosition or 39 // AvoidObstacles. 40 // TODO(crbug.com/955512): Ensure calculations take place from high to low 41 // priority to reduce number of collision computations. 42 enum class RelativePriority { 43 kPictureInPicture = 0, 44 kSwitchAccessMenu = 1, 45 kAutomaticClicksMenu = 2, 46 kAutomaticClicksScrollMenu = 3, 47 kDefault = 4, 48 }; 49 50 CollisionDetectionUtils() = delete; 51 ~CollisionDetectionUtils() = delete; 52 53 // Returns the area that the window can be positioned inside for a given 54 // display |display|. 55 static gfx::Rect GetMovementArea(const display::Display& display); 56 57 // Returns the result of adjusting |bounds_in_screen| according to gravity 58 // inside the movement area of |display| without taking obstacles into 59 // account. 60 static gfx::Rect AdjustToFitMovementAreaByGravity( 61 const display::Display& display, 62 const gfx::Rect& bounds_in_screen); 63 64 // Returns the position the window should come to rest at. For example, 65 // this will be at a screen edge, not in the middle of the screen. 66 // TODO(edcourtney): This should consider drag velocity for fling as well. 67 static gfx::Rect GetRestingPosition(const display::Display& display, 68 const gfx::Rect& bounds_in_screen, 69 RelativePriority priority); 70 71 // Mark a window as ignored for collision detection. 72 static void IgnoreWindowForCollisionDetection(aura::Window* window); 73 74 // Allows the windows which use CollisionDetectionUtils to mark their relative 75 // priority when they come in position conflict. 76 static void MarkWindowPriorityForCollisionDetection( 77 aura::Window* window, 78 RelativePriority priority); 79 80 // Moves |bounds| such that it does not intersect with system ui areas, such 81 // as the unified system tray or the floating keyboard. 82 static gfx::Rect AvoidObstacles(const display::Display& display, 83 const gfx::Rect& bounds_in_screen, 84 RelativePriority priority); 85 86 // Returns the result of adjusting |bounds| according to |gravity| inside 87 // |region|. 88 static gfx::Rect GetAdjustedBoundsByGravity(const gfx::Rect& bounds, 89 const gfx::Rect& region, 90 Gravity gravity); 91 92 // Returns the gravity that would make |bounds| fall to the closest edge of 93 // |region|. If |bounds| is outside of |region| then it will return the 94 // gravity as if |bounds| had fallen outside of |region|. See the below 95 // diagram for what the gravity regions look like for a point. 96 // \ TOP / 97 // \____/ R 98 // L |\ /| I 99 // E | \/ | G 100 // F | /\ | H 101 // T |/__\| T 102 // / \ 103 // /BOTTOM 104 static Gravity GetGravityToClosestEdge(const gfx::Rect& bounds, 105 const gfx::Rect& region); 106 107 private: 108 friend class CollisionDetectionUtilsDisplayTest; 109 friend class CollisionDetectionUtilsLogicTest; 110 111 // Internal method for collision resolution. Returns a gfx::Rect with the 112 // same size as |bounds|. That rectangle will not intersect any of the 113 // rectangles in |rects| and will be completely inside |work_area|. If such a 114 // rectangle does not exist, returns |bounds|. Otherwise, it will be the 115 // closest such rectangle to |bounds|. 116 static gfx::Rect AvoidObstaclesInternal(const gfx::Rect& work_area, 117 const std::vector<gfx::Rect>& rects, 118 const gfx::Rect& bounds_in_screen, 119 RelativePriority priority); 120 121 DISALLOW_COPY_AND_ASSIGN(CollisionDetectionUtils); 122 }; 123 124 } // namespace ash 125 126 #endif // ASH_WM_COLLISION_DETECTION_COLLISION_DETECTION_UTILS_H_ 127