1 // Copyright 2014 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "ash/screen_util.h"
7 #include "ash/display/display_configuration_controller.h"
8 #include "ash/display/mirror_window_controller.h"
9 #include "ash/display/window_tree_host_manager.h"
10 #include "ash/public/cpp/shell_window_ids.h"
11 #include "ash/shelf/shelf.h"
12 #include "ash/shell.h"
13 #include "ash/wm/desks/desks_util.h"
14 #include "ash/wm/window_state.h"
15 #include "ash/wm/work_area_insets.h"
16 #include "base/check_op.h"
17 #include "ui/aura/client/screen_position_client.h"
18 #include "ui/aura/window_event_dispatcher.h"
19 #include "ui/aura/window_tree_host.h"
20 #include "ui/display/display.h"
21 #include "ui/display/manager/display_manager.h"
22 #include "ui/display/screen.h"
23 #include "ui/gfx/geometry/size_conversions.h"
24 #include "ui/wm/core/coordinate_conversion.h"
28 namespace screen_util {
30 gfx::Rect GetMaximizedWindowBoundsInParent(aura::Window* window) {
31 if (Shelf::ForWindow(window)->shelf_widget())
32 return GetDisplayWorkAreaBoundsInParent(window);
33 return GetDisplayBoundsInParent(window);
36 gfx::Rect GetDisplayBoundsInParent(aura::Window* window) {
38 display::Screen::GetScreen()->GetDisplayNearestWindow(window).bounds();
39 ::wm::ConvertRectFromScreen(window->parent(), &result);
43 gfx::Rect GetFullscreenWindowBoundsInParent(aura::Window* window) {
44 gfx::Rect result = GetDisplayBoundsInParent(window);
45 const WorkAreaInsets* const work_area_insets =
46 WorkAreaInsets::ForWindow(window->GetRootWindow());
48 gfx::Insets().set_top(work_area_insets->accessibility_panel_height() +
49 work_area_insets->docked_magnifier_height()));
53 gfx::Rect GetDisplayWorkAreaBoundsInParent(aura::Window* window) {
54 // If it is application window under `non_lock_screen_containers`, use
55 // `in_session_user_work_area_insets`, otherwise, use `user_work_area_insets`.
56 const aura::Window* non_lock_screen_containers = Shell::GetContainer(
57 window->GetRootWindow(), kShellWindowId_NonLockScreenContainersContainer);
59 non_lock_screen_containers->Contains(window)
60 ? WorkAreaInsets::ForWindow(window)
61 ->in_session_user_work_area_insets()
62 : WorkAreaInsets::ForWindow(window)->user_work_area_insets();
64 display::Screen::GetScreen()->GetDisplayNearestWindow(window).bounds();
66 ::wm::ConvertRectFromScreen(window->parent(), &bounds);
70 // TODO(yongshun): Remove or consolidate this function with
71 // `GetDisplayWorkAreaBoundsInParent`.
72 gfx::Rect GetDisplayWorkAreaBoundsInParentForLockScreen(aura::Window* window) {
73 gfx::Rect bounds = WorkAreaInsets::ForWindow(window)->user_work_area_bounds();
74 ::wm::ConvertRectFromScreen(window->parent(), &bounds);
78 // TODO(yongshun): Remove or consolidate this function with
79 // `GetDisplayWorkAreaBoundsInParent`.
80 gfx::Rect GetDisplayWorkAreaBoundsInParentForActiveDeskContainer(
81 aura::Window* window) {
82 aura::Window* root_window = window->GetRootWindow();
83 return GetDisplayWorkAreaBoundsInParent(
84 desks_util::GetActiveDeskContainerForRoot(root_window));
87 // TODO(yongshun): Remove or consolidate this function with
88 // `GetDisplayWorkAreaBoundsInParent`.
89 gfx::Rect GetDisplayWorkAreaBoundsInScreenForActiveDeskContainer(
90 aura::Window* window) {
92 GetDisplayWorkAreaBoundsInParentForActiveDeskContainer(window);
93 ::wm::ConvertRectToScreen(window->GetRootWindow(), &bounds);
97 gfx::Rect GetDisplayBoundsWithShelf(aura::Window* window) {
98 if (!Shell::Get()->display_manager()->IsInUnifiedMode()) {
99 return display::Screen::GetScreen()
100 ->GetDisplayNearestWindow(window)
104 // In Unified Mode, the display that should contain the shelf depends on the
105 // current shelf alignment.
106 const display::Display shelf_display =
108 ->display_configuration_controller()
109 ->GetPrimaryMirroringDisplayForUnifiedDesktop();
110 DCHECK_NE(shelf_display.id(), display::kInvalidDisplayId);
112 // Transform the bounds back to the unified host's coordinates.
113 auto inverse_unified_transform =
114 window->GetRootWindow()->GetHost()->GetInverseRootTransform();
115 return inverse_unified_transform.MapRect(shelf_display.bounds());
118 gfx::Rect SnapBoundsToDisplayEdge(const gfx::Rect& bounds,
119 const aura::Window* window) {
120 display::Display display =
121 display::Screen::GetScreen()->GetDisplayNearestWindow(
122 const_cast<aura::Window*>(window));
124 const float dsf = display.device_scale_factor();
125 const gfx::Size display_size_in_pixel = display.GetSizeInPixel();
126 const gfx::Size scaled_size_in_pixel =
127 gfx::ScaleToFlooredSize(display.size(), dsf);
129 // Adjusts |bounds| such that the scaled enclosed bounds are atleast as big as
130 // the scaled enclosing unadjusted bounds.
131 gfx::Rect snapped_bounds = bounds;
132 if (scaled_size_in_pixel.width() < display_size_in_pixel.width() &&
133 display.bounds().right() == bounds.right()) {
134 snapped_bounds.Inset(gfx::Insets::TLBR(0, 0, 0, -1));
135 DCHECK_GE(gfx::ScaleToEnclosedRect(snapped_bounds, dsf).right(),
136 gfx::ScaleToEnclosingRect(bounds, dsf).right());
138 if (scaled_size_in_pixel.height() < display_size_in_pixel.height() &&
139 display.bounds().bottom() == bounds.bottom()) {
140 snapped_bounds.Inset(gfx::Insets::TLBR(0, 0, -1, 0));
141 DCHECK_GE(gfx::ScaleToEnclosedRect(snapped_bounds, dsf).bottom(),
142 gfx::ScaleToEnclosingRect(bounds, dsf).bottom());
145 return snapped_bounds;
148 gfx::Rect GetIdealBoundsForMaximizedOrFullscreenOrPinnedState(
149 aura::Window* window) {
150 auto* window_state = WindowState::Get(window);
151 if (window_state->IsMaximized()) {
152 auto* shelf = ash::Shelf::ForWindow(window);
153 if (shelf->auto_hide_behavior() == ash::ShelfAutoHideBehavior::kAlways) {
155 ash::screen_util::GetFullscreenWindowBoundsInParent(window);
156 ::wm::ConvertRectToScreen(window->parent(), &bounds);
159 if (shelf->auto_hide_behavior() ==
160 ash::ShelfAutoHideBehavior::kAlwaysHidden) {
161 return display::Screen::GetScreen()
162 ->GetDisplayNearestWindow(const_cast<aura::Window*>(window))
166 ash::WorkAreaInsets::ForWindow(window)->ComputeStableWorkArea();
169 if (window_state->IsFullscreen() || window_state->IsPinned()) {
171 ash::screen_util::GetFullscreenWindowBoundsInParent(window);
172 ::wm::ConvertRectToScreen(window->parent(), &bounds);
175 NOTREACHED() << "The window is not maximzied or fullscreen or pinned. state="
176 << window_state->GetStateType();
177 return window->GetBoundsInScreen();
180 } // namespace screen_util