blob: 07a09858e79bf033edcbebe137e2a03454cdbf3c [file] [log] [blame]
// Copyright 2018 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.
#include "ash/wm/pip/pip_positioner.h"
#include <algorithm>
#include "ash/root_window_controller.h"
#include "ash/shelf/shelf.h"
#include "ash/shell.h"
#include "ash/system/status_area_widget.h"
#include "ash/system/unified/unified_system_tray.h"
#include "ash/wm/window_state.h"
#include "ash/wm/window_util.h"
#include "ui/aura/window.h"
#include "ui/keyboard/keyboard_controller.h"
namespace ash {
namespace {
const int kPipWorkAreaInsetsDp = 8;
enum { GRAVITY_LEFT, GRAVITY_RIGHT, GRAVITY_TOP, GRAVITY_BOTTOM };
// Returns the result of adjusting |bounds| according to |gravity| inside
// |region|.
gfx::Rect GetAdjustedBoundsByGravity(const gfx::Rect& bounds,
const gfx::Rect& region,
int gravity) {
switch (gravity) {
case GRAVITY_LEFT:
return gfx::Rect(region.x(), bounds.y(), bounds.width(), bounds.height());
case GRAVITY_RIGHT:
return gfx::Rect(region.right() - bounds.width(), bounds.y(),
bounds.width(), bounds.height());
case GRAVITY_TOP:
return gfx::Rect(bounds.x(), region.y(), bounds.width(), bounds.height());
case GRAVITY_BOTTOM:
return gfx::Rect(bounds.x(), region.bottom() - bounds.height(),
bounds.width(), bounds.height());
default:
NOTREACHED();
}
return bounds;
}
} // namespace
gfx::Rect PipPositioner::GetMovementArea(const display::Display& display) {
gfx::Rect work_area = display.work_area();
auto* keyboard_controller = keyboard::KeyboardController::Get();
// Include keyboard if it's not floating.
if (keyboard_controller->IsEnabled() &&
keyboard_controller->GetActiveContainerType() !=
keyboard::ContainerType::FLOATING) {
gfx::Rect keyboard_bounds = keyboard_controller->visual_bounds_in_screen();
work_area.Subtract(keyboard_bounds);
}
work_area.Inset(kPipWorkAreaInsetsDp, kPipWorkAreaInsetsDp);
return work_area;
}
gfx::Rect PipPositioner::GetBoundsForDrag(const display::Display& display,
const gfx::Rect& bounds) {
gfx::Rect drag_bounds = bounds;
drag_bounds.AdjustToFit(GetMovementArea(display));
return drag_bounds;
}
gfx::Rect PipPositioner::GetRestingPosition(const display::Display& display,
const gfx::Rect& bounds) {
gfx::Rect resting_bounds = bounds;
gfx::Rect area = GetMovementArea(display);
resting_bounds.AdjustToFit(area);
gfx::Point pip_center = resting_bounds.CenterPoint();
gfx::Point area_center = area.CenterPoint();
gfx::Vector2d direction = pip_center - area_center;
int gravity = 0;
if (std::abs(direction.x()) > std::abs(direction.y())) {
gravity = direction.x() < 0 ? GRAVITY_LEFT : GRAVITY_RIGHT;
} else {
gravity = direction.y() < 0 ? GRAVITY_TOP : GRAVITY_BOTTOM;
}
return GetAdjustedBoundsByGravity(resting_bounds, area, gravity);
}
} // namespace ash