| // Copyright 2019 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef ASH_WM_COLLISION_DETECTION_COLLISION_DETECTION_UTILS_H_ |
| #define ASH_WM_COLLISION_DETECTION_COLLISION_DETECTION_UTILS_H_ |
| |
| #include "ash/ash_export.h" |
| #include "ui/aura/window.h" |
| #include "ui/display/display.h" |
| #include "ui/gfx/geometry/rect.h" |
| |
| namespace ash { |
| |
| // The inset into the work area for a window's resting position. Visible for |
| // testing. |
| const static int kCollisionWindowWorkAreaInsetsDp = 8; |
| |
| // Provides utility functions to compute resting positions for windows which |
| // wish to avoid other system windows, for example, the PIP and the Automatic |
| // Clicks bubble menu. |
| class ASH_EXPORT CollisionDetectionUtils { |
| public: |
| enum class Gravity { |
| kGravityLeft, |
| kGravityRight, |
| kGravityTop, |
| kGravityBottom, |
| }; |
| |
| // Ordered list of windows which do collision detection. Higher numbers take |
| // higher priority, i.e. the higher RelativePriority of two windows will not |
| // move when the windows are in conflict. In this case, that means the |
| // Picture in Picture window will move out of the way for the Automatic Clicks |
| // menu, and both will move out of the way for default system windows. Windows |
| // with the same relative priority will not affect collision with each other. |
| // kDefault is used for "everything else", and should not be an input to |
| // GetRestingPosition or AvoidObstacles. |
| // TODO(crbug.com/955512): Ensure calculations take place from high to low |
| // priority to reduce number of collision computations. |
| enum class RelativePriority { |
| kPictureInPicture = 0, |
| kAutomaticClicksMenu = 1, |
| kDefault = 2, |
| }; |
| |
| CollisionDetectionUtils() = delete; |
| ~CollisionDetectionUtils() = delete; |
| |
| // Returns the area that the window can be positioned inside for a given |
| // display |display|. |
| static gfx::Rect GetMovementArea(const display::Display& display); |
| |
| // Returns the position the window should come to rest at. For example, |
| // this will be at a screen edge, not in the middle of the screen. |
| // TODO(edcourtney): This should consider drag velocity for fling as well. |
| static gfx::Rect GetRestingPosition(const display::Display& display, |
| const gfx::Rect& bounds_in_screen, |
| RelativePriority priority); |
| |
| // Mark a window as ignored for collision detection. |
| static void IgnoreWindowForCollisionDetection(aura::Window* window); |
| |
| // Allows the windows which use CollisionDetectionUtils to mark their relative |
| // priority when they come in position conflict. |
| static void MarkWindowPriorityForCollisionDetection( |
| aura::Window* window, |
| RelativePriority priority); |
| |
| // Moves |bounds| such that it does not intersect with system ui areas, such |
| // as the unified system tray or the floating keyboard. |
| static gfx::Rect AvoidObstacles(const display::Display& display, |
| const gfx::Rect& bounds_in_screen, |
| RelativePriority priority); |
| |
| // Returns the result of adjusting |bounds| according to |gravity| inside |
| // |region|. |
| static gfx::Rect GetAdjustedBoundsByGravity(const gfx::Rect& bounds, |
| const gfx::Rect& region, |
| Gravity gravity); |
| |
| // Returns the gravity that would make |bounds| fall to the closest edge of |
| // |region|. If |bounds| is outside of |region| then it will return the |
| // gravity as if |bounds| had fallen outside of |region|. See the below |
| // diagram for what the gravity regions look like for a point. |
| // \ TOP / |
| // \____/ R |
| // L |\ /| I |
| // E | \/ | G |
| // F | /\ | H |
| // T |/__\| T |
| // / \ |
| // /BOTTOM |
| static Gravity GetGravityToClosestEdge(const gfx::Rect& bounds, |
| const gfx::Rect& region); |
| |
| private: |
| friend class CollisionDetectionUtilsDisplayTest; |
| friend class CollisionDetectionUtilsLogicTest; |
| |
| // Internal method for collision resolution. Returns a gfx::Rect with the |
| // same size as |bounds|. That rectangle will not intersect any of the |
| // rectangles in |rects| and will be completely inside |work_area|. If such a |
| // rectangle does not exist, returns |bounds|. Otherwise, it will be the |
| // closest such rectangle to |bounds|. |
| static gfx::Rect AvoidObstaclesInternal(const gfx::Rect& work_area, |
| const std::vector<gfx::Rect>& rects, |
| const gfx::Rect& bounds_in_screen, |
| RelativePriority priority); |
| |
| DISALLOW_COPY_AND_ASSIGN(CollisionDetectionUtils); |
| }; |
| |
| } // namespace ash |
| |
| #endif // ASH_WM_COLLISION_DETECTION_COLLISION_DETECTION_UTILS_H_ |